/// <summary>
        /// Adds custom traffic lights at the specified node and segment.
        /// Light states (red, yellow, green) are taken from the "live" state, that is the traffic light's light state right before the custom light takes control.
        /// </summary>
        /// <param name="segmentId"></param>
        /// <param name="startNode"></param>
        public CustomSegmentLights AddLiveSegmentLights(ushort segmentId, bool startNode)
        {
            SegmentGeometry    segGeometry = SegmentGeometry.Get(segmentId);
            SegmentEndGeometry endGeometry = startNode ? segGeometry.StartNodeGeometry : segGeometry.EndNodeGeometry;

            if (!endGeometry.IsValid())
            {
                Log.Error($"CustomTrafficLightsManager.AddLiveSegmentLights: Segment {segmentId} is not connected to a node. startNode={startNode}");
                return(null);
            }

            var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            RoadBaseAI.TrafficLightState vehicleLightState;
            RoadBaseAI.TrafficLightState pedestrianLightState;
            bool vehicles;
            bool pedestrians;

            RoadBaseAI.GetTrafficLightState(endGeometry.NodeId(), ref Singleton <NetManager> .instance.m_segments.m_buffer[segmentId],
                                            currentFrameIndex - 256u, out vehicleLightState, out pedestrianLightState, out vehicles,
                                            out pedestrians);

            return(AddSegmentLights(segmentId, startNode,
                                    vehicleLightState == RoadBaseAI.TrafficLightState.Green
                                        ? RoadBaseAI.TrafficLightState.Green
                                        : RoadBaseAI.TrafficLightState.Red));
        }
        public bool IsEnteringBlockedJunctionAllowedConfigurable(ushort segmentId, bool startNode, ref NetNode node)
        {
#if DEBUG
            bool debug = GlobalConfig.Instance.Debug.Switches[11];
#endif

            SegmentEndGeometry endGeo = SegmentGeometry.Get(segmentId)?.GetEnd(startNode);

            if (endGeo == null)
            {
                Log.Warning($"JunctionRestrictionsManager.IsEnteringBlockedJunctionAllowedConfigurable({segmentId}, {startNode}): Could not get segment end geometry");
                return(false);
            }

            bool ret =
                (node.m_flags & NetNode.Flags.Junction) != NetNode.Flags.None &&
                node.Info?.m_class?.m_service != ItemClass.Service.Beautification &&
                !endGeo.OutgoingOneWay;
            ;
#if DEBUG
            if (debug)
            {
                Log._Debug($"JunctionRestrictionsManager.IsEnteringBlockedJunctionAllowedConfigurable({segmentId}, {startNode}): ret={ret}, flags={node.m_flags}, service={node.Info?.m_class?.m_service}, outgoingOneWay={endGeo.OutgoingOneWay}");
            }
#endif
            return(ret);
        }
Exemple #3
0
        public ISegmentEnd GetOrAddSegmentEnd(ushort segmentId, bool startNode)
        {
            ISegmentEnd end = GetSegmentEnd(segmentId, startNode);

            if (end != null)
            {
                return(end);
            }

            SegmentGeometry segGeo = SegmentGeometry.Get(segmentId);

            if (segGeo == null)
            {
                Log.Warning($"SegmentEndManager.GetOrAddSegmentEnd({segmentId}, {startNode}): Refusing to add segment end for invalid segment.");
                return(null);
            }

            SegmentEndGeometry endGeo = segGeo.GetEnd(startNode);

            if (endGeo == null)
            {
                Log.Warning($"SegmentEndManager.GetOrAddSegmentEnd({segmentId}, {startNode}): Refusing to add segment end for invalid segment end.");
                return(null);
            }

            return(SegmentEnds[GetIndex(segmentId, startNode)] = new SegmentEnd(segmentId, startNode));
        }
        public bool SetSegmentLights(ushort nodeId, ushort segmentId, ICustomSegmentLights lights)
        {
            SegmentEndGeometry endGeo = SegmentGeometry.Get(segmentId)?.GetEnd(nodeId);

            if (endGeo == null)
            {
                return(false);
            }

            CustomSegment customSegment = CustomSegments[segmentId];

            if (customSegment == null)
            {
                customSegment             = new CustomSegment();
                CustomSegments[segmentId] = customSegment;
            }

            if (endGeo.StartNode)
            {
                customSegment.StartNodeLights = lights;
            }
            else
            {
                customSegment.EndNodeLights = lights;
            }
            return(true);
        }
        //private bool defaultPedestrianCrossingAllowed;

        public void UpdateDefaults(SegmentEndGeometry segmentEndGeometry)
        {
            NodeGeometry nodeGeo = NodeGeometry.Get(segmentEndGeometry.NodeId());

            bool newDefaultEnterWhenBlockedAllowed = false;
            bool newDefaultUturnAllowed            = false;

            //NetNode.Flags _nodeFlags = NetNode.Flags.None;
            Constants.ServiceFactory.NetService.ProcessNode(segmentEndGeometry.NodeId(), delegate(ushort nodeId, ref NetNode node) {
                //_nodeFlags = node.m_flags;
                int numOutgoing = 0;
                int numIncoming = 0;
                node.CountLanes(nodeId, 0, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, true, ref numOutgoing, ref numIncoming);
                newDefaultEnterWhenBlockedAllowed = numOutgoing == 1 || numIncoming == 1;

                if (Options.allowUTurns)
                {
                    newDefaultUturnAllowed =
                        (node.m_flags & (NetNode.Flags.Junction | NetNode.Flags.Transition | NetNode.Flags.Bend | NetNode.Flags.End | NetNode.Flags.OneWayOut)) != NetNode.Flags.None &&
                        node.Info?.m_class?.m_service != ItemClass.Service.Beautification
                    ;
                }
                else
                {
                    newDefaultUturnAllowed = (node.m_flags & (NetNode.Flags.End | NetNode.Flags.OneWayOut)) != NetNode.Flags.None;
                }
                return(true);
            });
            defaultEnterWhenBlockedAllowed = newDefaultEnterWhenBlockedAllowed;
            defaultUturnAllowed            = newDefaultUturnAllowed;
            //Log._Debug($"SegmentEndFlags.UpdateDefaults: this={this} _nodeFlags={_nodeFlags} defaultEnterWhenBlockedAllowed={defaultEnterWhenBlockedAllowed}");
        }
        public bool IsLaneChangingAllowedWhenGoingStraightConfigurable(ushort segmentId, bool startNode, ref NetNode node)
        {
#if DEBUG
            bool debug = GlobalConfig.Instance.Debug.Switches[11];
#endif

            SegmentEndGeometry endGeo = SegmentGeometry.Get(segmentId)?.GetEnd(startNode);

            if (endGeo == null)
            {
                Log.Warning($"JunctionRestrictionsManager.IsLaneChangingAllowedWhenGoingStraightConfigurable({segmentId}, {startNode}): Could not get segment end geometry");
                return(false);
            }

            bool ret =
                (node.m_flags & (NetNode.Flags.Junction | NetNode.Flags.Transition)) != NetNode.Flags.None &&
                node.Info?.m_class?.m_service != ItemClass.Service.Beautification &&
                !endGeo.OutgoingOneWay &&
                node.CountSegments() > 2
            ;
#if DEBUG
            if (debug)
            {
                Log._Debug($"JunctionRestrictionsManager.IsLaneChangingAllowedWhenGoingStraightConfigurable({segmentId}, {startNode}): ret={ret}, flags={node.m_flags}, service={node.Info?.m_class?.m_service}, incomingOneWay={endGeo.IncomingOneWay}, outgoingOneWay={endGeo.OutgoingOneWay}, node.CountSegments()={node.CountSegments()}");
            }
#endif
            return(ret);
        }
        public CustomSegmentLights GetSegmentLights(ushort nodeId, ushort segmentId)
        {
            SegmentEndGeometry endGeometry = SegmentGeometry.Get(segmentId).GetEnd(nodeId);

            if (endGeometry == null)
            {
                return(null);
            }
            return(GetSegmentLights(segmentId, endGeometry.StartNode, false));
        }
        public short ClockwiseIndexOfSegmentEnd(ISegmentEndId endId)
        {
            SegmentEndGeometry endGeo = SegmentGeometry.Get(endId.SegmentId)?.GetEnd(endId.StartNode);

            if (endGeo == null)
            {
                return(0);
            }
            return(endGeo.GetClockwiseIndex());
        }
        /// <summary>
        /// Adds custom traffic lights at the specified node and segment.
        /// Light stats are set to the given light state, or to "Red" if no light state is given.
        /// </summary>
        /// <param name="segmentId"></param>
        /// <param name="startNode"></param>
        /// <param name="lightState">(optional) light state to set</param>
        public ICustomSegmentLights AddSegmentLights(ushort segmentId, bool startNode, RoadBaseAI.TrafficLightState lightState = RoadBaseAI.TrafficLightState.Red)
        {
#if DEBUG
            Log._Debug($"CustomTrafficLights.AddSegmentLights: Adding segment light: {segmentId} @ startNode={startNode}");
#endif

            SegmentGeometry segGeometry = SegmentGeometry.Get(segmentId);
            if (segGeometry == null)
            {
                Log.Error($"CustomTrafficLightsManager.AddSegmentLights: Segment {segmentId} is invalid.");
                return(null);
            }

            SegmentEndGeometry endGeometry = segGeometry.GetEnd(startNode);
            if (endGeometry == null)
            {
                Log.Error($"CustomTrafficLightsManager.AddSegmentLights: Segment {segmentId} is not connected to a node @ start {startNode}");
                return(null);
            }

            CustomSegment customSegment = CustomSegments[segmentId];
            if (customSegment == null)
            {
                customSegment             = new CustomSegment();
                CustomSegments[segmentId] = customSegment;
            }
            else
            {
                ICustomSegmentLights existingLights = startNode ? customSegment.StartNodeLights : customSegment.EndNodeLights;

                if (existingLights != null)
                {
                    existingLights.SetLights(lightState);
                    return(existingLights);
                }
            }

            SubscribeToSegmentGeometry(segmentId);
            if (startNode)
            {
                customSegment.StartNodeLights = new CustomSegmentLights(this, segmentId, startNode, false);
                customSegment.StartNodeLights.SetLights(lightState);
                return(customSegment.StartNodeLights);
            }
            else
            {
                customSegment.EndNodeLights = new CustomSegmentLights(this, segmentId, startNode, false);
                customSegment.EndNodeLights.SetLights(lightState);
                return(customSegment.EndNodeLights);
            }
        }
        public bool GetDefaultEnteringBlockedJunctionAllowed(ushort segmentId, bool startNode, ref NetNode node)
        {
#if DEBUG
            bool debug = GlobalConfig.Instance.Debug.Switches[11];
#endif

            SegmentEndGeometry endGeo = SegmentGeometry.Get(segmentId)?.GetEnd(startNode);

            if (endGeo == null)
            {
                Log.Warning($"JunctionRestrictionsManager.GetDefaultEnteringBlockedJunctionAllowed({segmentId}, {startNode}): Could not get segment end geometry");
                return(false);
            }

            if (!IsEnteringBlockedJunctionAllowedConfigurable(segmentId, startNode, ref node))
            {
                bool res = (node.m_flags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) != NetNode.Flags.Junction || node.CountSegments() == 2;
#if DEBUG
                if (debug)
                {
                    Log._Debug($"JunctionRestrictionsManager.GetDefaultEnteringBlockedJunctionAllowed({segmentId}, {startNode}): Setting is not configurable. res={res}, flags={node.m_flags}, node.CountSegments()={node.CountSegments()}");
                }
#endif
                return(res);
            }

            bool ret;
            if (Options.allowEnterBlockedJunctions)
            {
                ret = true;
            }
            else
            {
                int numOutgoing = 0;
                int numIncoming = 0;
                node.CountLanes(endGeo.NodeId(), 0, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, true, ref numOutgoing, ref numIncoming);
                ret = numOutgoing == 1 || numIncoming == 1;
            }

#if DEBUG
            if (debug)
            {
                Log._Debug($"JunctionRestrictionsManager.GetDefaultEnteringBlockedJunctionAllowed({segmentId}, {startNode}): Setting is configurable. ret={ret}");
            }
#endif

            return(ret);
        }
Exemple #11
0
        public bool UpdateSegmentEnd(ushort segmentId, bool startNode)
        {
            SegmentGeometry segGeo = SegmentGeometry.Get(segmentId);

            if (segGeo == null)
            {
#if DEBUGGEO
                Log._Debug($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Segment {segmentId} is invalid. Removing all segment ends.");
#endif
                RemoveSegmentEnds(segmentId);
                return(false);
            }

            SegmentEndGeometry endGeo = segGeo.GetEnd(startNode);
            if (endGeo == null)
            {
                Log._Debug($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Segment end {segmentId} @ {startNode} is invalid. Removing segment end.");
                RemoveSegmentEnd(segmentId, startNode);
                return(false);
            }

            if (TrafficPriorityManager.Instance.HasSegmentPrioritySign(segmentId, startNode) ||
                TrafficLightSimulationManager.Instance.HasTimedSimulation(endGeo.NodeId()))
            {
                Log._Debug($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Segment {segmentId} @ {startNode} has timed light or priority sign. Adding segment end {segmentId} @ {startNode}");
                ISegmentEnd end = GetOrAddSegmentEnd(segmentId, startNode);
                if (end == null)
                {
                    Log.Warning($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Failed to add segment end.");
                    return(false);
                }
                else
                {
                    Log._Debug($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Added segment end. Updating now.");
                    end.Update();
                    Log._Debug($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Update of segment end finished.");
                    return(true);
                }
            }
            else
            {
#if DEBUGGEO
                Log._Debug($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Segment {segmentId} @ {startNode} neither has timed light nor priority sign. Removing segment end {segmentId} @ {startNode}");
#endif
                RemoveSegmentEnd(segmentId, startNode);
                return(false);
            }
        }
        //private bool defaultPedestrianCrossingAllowed;

        public void UpdateDefaults(SegmentEndGeometry segmentEndGeometry)
        {
            NodeGeometry nodeGeo = NodeGeometry.Get(segmentEndGeometry.NodeId());

            bool newDefaultEnterWhenBlockedAllowed = false;

            NetNode.Flags _nodeFlags = NetNode.Flags.None;
            Constants.ServiceFactory.NetService.ProcessNode(segmentEndGeometry.NodeId(), delegate(ushort nodeId, ref NetNode node) {
                _nodeFlags      = node.m_flags;
                int numOutgoing = 0;
                int numIncoming = 0;
                node.CountLanes(nodeId, 0, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, true, ref numOutgoing, ref numIncoming);
                newDefaultEnterWhenBlockedAllowed = numOutgoing == 1 || numIncoming == 1;
                return(true);
            });
            defaultEnterWhenBlockedAllowed = newDefaultEnterWhenBlockedAllowed;
            //Log._Debug($"SegmentEndFlags.UpdateDefaults: this={this} _nodeFlags={_nodeFlags} defaultEnterWhenBlockedAllowed={defaultEnterWhenBlockedAllowed}");
        }
Exemple #13
0
        protected void UpdateSegment(SegmentGeometry geometry)
        {
#if DEBUG
            bool debug = GlobalConfig.Instance.Debug.Switches[25];
            if (debug)
            {
                Log._Debug($"TurnOnRedManager.UpdateSegment({geometry.SegmentId}) called.");
            }
#endif

            ResetSegment(geometry.SegmentId);
            SegmentEndGeometry startEndGeo = geometry.GetEnd(true);
            if (startEndGeo != null)
            {
                UpdateSegmentEnd(startEndGeo);
            }

            SegmentEndGeometry endEndGeo = geometry.GetEnd(false);
            if (endEndGeo != null)
            {
                UpdateSegmentEnd(endEndGeo);
            }
        }
Exemple #14
0
        protected void UpdateSegmentEnd(SegmentEndGeometry endGeo)
        {
#if DEBUG
            bool debug = GlobalConfig.Instance.Debug.Switches[25];
            if (debug)
            {
                Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}) called.");
            }
#endif

            // check if traffic can flow to the node and that there is at least one outgoing segment
            if (endGeo.OutgoingOneWay || endGeo.NumOutgoingSegments <= 0)
            {
#if DEBUG
                if (debug)
                {
                    Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): outgoing one-way or insufficient number of outgoing segments.");
                }
#endif
                return;
            }

            bool   lhd    = Services.SimulationService.LeftHandDrive;
            ushort nodeId = endGeo.NodeId();

            // check node
            // note that we must not check for the `TrafficLights` flag here because the flag might not be loaded yet
            bool nodeValid = false;
            Services.NetService.ProcessNode(nodeId, delegate(ushort nId, ref NetNode node) {
                nodeValid =
                    (node.m_flags & NetNode.Flags.LevelCrossing) == NetNode.Flags.None &&
                    node.Info?.m_class?.m_service != ItemClass.Service.Beautification;
                return(true);
            });

            if (!nodeValid)
            {
#if DEBUG
                if (debug)
                {
                    Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): node invalid");
                }
#endif
                return;
            }

            // get left/right segments
            ushort leftSegmentId  = 0;
            ushort rightSegmentId = 0;
            Services.NetService.ProcessSegment(endGeo.SegmentId, delegate(ushort segId, ref NetSegment seg) {
                seg.GetLeftAndRightSegments(nodeId, out leftSegmentId, out rightSegmentId);
                return(true);
            });

#if DEBUG
            if (debug)
            {
                Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): got left/right segments: {leftSegmentId}/{rightSegmentId}");
            }
#endif

            // validate left/right segments according to geometric properties
            if (leftSegmentId != 0 && !endGeo.IsLeftSegment(leftSegmentId))
            {
#if DEBUG
                if (debug)
                {
                    Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): left segment is not geometrically left");
                }
#endif
                leftSegmentId = 0;
            }

            if (rightSegmentId != 0 && !endGeo.IsRightSegment(rightSegmentId))
            {
#if DEBUG
                if (debug)
                {
                    Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): right segment is not geometrically right");
                }
#endif
                rightSegmentId = 0;
            }

            // check for incoming one-ways
            if (leftSegmentId != 0 && SegmentGeometry.Get(leftSegmentId).GetEnd(nodeId).IncomingOneWay)
            {
#if DEBUG
                if (debug)
                {
                    Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): left segment is incoming one-way");
                }
#endif
                leftSegmentId = 0;
            }

            if (rightSegmentId != 0 && SegmentGeometry.Get(rightSegmentId).GetEnd(nodeId).IncomingOneWay)
            {
#if DEBUG
                if (debug)
                {
                    Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): right segment is incoming one-way");
                }
#endif
                rightSegmentId = 0;
            }

            if (endGeo.IncomingOneWay)
            {
                if (lhd && rightSegmentId != 0 || !lhd && leftSegmentId != 0)
                {
                    // special case: one-way to one-way in non-preferred direction
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): source is incoming one-way. checking for one-way in non-preferred direction");
                    }
#endif
                    ushort             targetSegmentId = lhd ? rightSegmentId : leftSegmentId;
                    SegmentEndGeometry targetEndGeo    = SegmentGeometry.Get(targetSegmentId)?.GetEnd(nodeId);
                    if (targetEndGeo == null || !targetEndGeo.OutgoingOneWay)
                    {
                        if (targetEndGeo == null)
                        {
                            Log.Error($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): One-way to one-way: Target segment end geometry not found for segment id {targetSegmentId} @ {nodeId}");
                        }

                        // disallow turn in non-preferred direction
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): turn in non-preferred direction {(lhd ? "right" : "left")} disallowed");
                        }
#endif
                        if (lhd)
                        {
                            rightSegmentId = 0;
                        }
                        else
                        {
                            leftSegmentId = 0;
                        }
                    }
                }
            }
            else if (lhd)
            {
                // default case (LHD): turn in preferred direction
                rightSegmentId = 0;
            }
            else
            {
                // default case (RHD): turn in preferred direction
                leftSegmentId = 0;
            }

            int index = GetIndex(endGeo.SegmentId, endGeo.StartNode);
            TurnOnRedSegments[index].leftSegmentId  = leftSegmentId;
            TurnOnRedSegments[index].rightSegmentId = rightSegmentId;

#if DEBUG
            if (debug)
            {
                Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): Finished calculation. leftSegmentId={leftSegmentId}, rightSegmentId={rightSegmentId}");
            }
#endif
        }
        public bool LoadData(List <Configuration.SegmentNodeConf> data)
        {
            bool success = true;

            Log.Info($"Loading junction restrictions. {data.Count} elements");
            foreach (Configuration.SegmentNodeConf segNodeConf in data)
            {
                try {
                    if (!Services.NetService.IsSegmentValid(segNodeConf.segmentId))
                    {
                        continue;
                    }

                    Log._Debug($"JunctionRestrictionsManager.LoadData: Loading junction restrictions for segment {segNodeConf.segmentId}: startNodeFlags={segNodeConf.startNodeFlags} endNodeFlags={segNodeConf.endNodeFlags}");

                    if (segNodeConf.startNodeFlags != null)
                    {
                        SegmentEndGeometry startNodeSegGeo = SegmentGeometry.Get(segNodeConf.segmentId)?.GetEnd(true);
                        if (startNodeSegGeo != null)
                        {
                            Configuration.SegmentNodeFlags flags = segNodeConf.startNodeFlags;

                            Services.NetService.ProcessNode(startNodeSegGeo.NodeId(), delegate(ushort nId, ref NetNode node) {
                                if (flags.uturnAllowed != null && IsUturnAllowedConfigurable(segNodeConf.segmentId, true, ref node))
                                {
                                    SetUturnAllowed(segNodeConf.segmentId, true, (bool)flags.uturnAllowed);
                                }

                                if (flags.turnOnRedAllowed != null && IsNearTurnOnRedAllowedConfigurable(segNodeConf.segmentId, true, ref node))
                                {
                                    SetNearTurnOnRedAllowed(segNodeConf.segmentId, true, (bool)flags.turnOnRedAllowed);
                                }

                                if (flags.farTurnOnRedAllowed != null && IsNearTurnOnRedAllowedConfigurable(segNodeConf.segmentId, true, ref node))
                                {
                                    SetFarTurnOnRedAllowed(segNodeConf.segmentId, true, (bool)flags.farTurnOnRedAllowed);
                                }

                                if (flags.straightLaneChangingAllowed != null && IsLaneChangingAllowedWhenGoingStraightConfigurable(segNodeConf.segmentId, true, ref node))
                                {
                                    SetLaneChangingAllowedWhenGoingStraight(segNodeConf.segmentId, true, (bool)flags.straightLaneChangingAllowed);
                                }

                                if (flags.enterWhenBlockedAllowed != null && IsEnteringBlockedJunctionAllowedConfigurable(segNodeConf.segmentId, true, ref node))
                                {
                                    SetEnteringBlockedJunctionAllowed(segNodeConf.segmentId, true, (bool)flags.enterWhenBlockedAllowed);
                                }

                                if (flags.pedestrianCrossingAllowed != null && IsPedestrianCrossingAllowedConfigurable(segNodeConf.segmentId, true, ref node))
                                {
                                    SetPedestrianCrossingAllowed(segNodeConf.segmentId, true, (bool)flags.pedestrianCrossingAllowed);
                                }

                                return(true);
                            });
                        }
                        else
                        {
                            Log.Warning($"JunctionRestrictionsManager.LoadData(): Could not get segment end geometry for segment {segNodeConf.segmentId} @ start node");
                        }
                    }

                    if (segNodeConf.endNodeFlags != null)
                    {
                        SegmentEndGeometry endNodeSegGeo = SegmentGeometry.Get(segNodeConf.segmentId)?.GetEnd(false);
                        if (endNodeSegGeo != null)
                        {
                            Configuration.SegmentNodeFlags flags = segNodeConf.endNodeFlags;

                            Services.NetService.ProcessNode(endNodeSegGeo.NodeId(), delegate(ushort nId, ref NetNode node) {
                                if (flags.uturnAllowed != null && IsUturnAllowedConfigurable(segNodeConf.segmentId, false, ref node))
                                {
                                    SetUturnAllowed(segNodeConf.segmentId, false, (bool)flags.uturnAllowed);
                                }

                                if (flags.straightLaneChangingAllowed != null && IsLaneChangingAllowedWhenGoingStraightConfigurable(segNodeConf.segmentId, false, ref node))
                                {
                                    SetLaneChangingAllowedWhenGoingStraight(segNodeConf.segmentId, false, (bool)flags.straightLaneChangingAllowed);
                                }

                                if (flags.enterWhenBlockedAllowed != null && IsEnteringBlockedJunctionAllowedConfigurable(segNodeConf.segmentId, false, ref node))
                                {
                                    SetEnteringBlockedJunctionAllowed(segNodeConf.segmentId, false, (bool)flags.enterWhenBlockedAllowed);
                                }

                                if (flags.pedestrianCrossingAllowed != null && IsPedestrianCrossingAllowedConfigurable(segNodeConf.segmentId, false, ref node))
                                {
                                    SetPedestrianCrossingAllowed(segNodeConf.segmentId, false, (bool)flags.pedestrianCrossingAllowed);
                                }

                                if (flags.turnOnRedAllowed != null)
                                {
                                    SetNearTurnOnRedAllowed(segNodeConf.segmentId, false, (bool)flags.turnOnRedAllowed);
                                }

                                if (flags.farTurnOnRedAllowed != null)
                                {
                                    SetFarTurnOnRedAllowed(segNodeConf.segmentId, false, (bool)flags.farTurnOnRedAllowed);
                                }
                                return(true);
                            });
                        }
                        else
                        {
                            Log.Warning($"JunctionRestrictionsManager.LoadData(): Could not get segment end geometry for segment {segNodeConf.segmentId} @ end node");
                        }
                    }
                } catch (Exception e) {
                    // ignore, as it's probably corrupt save data. it'll be culled on next save
                    Log.Warning($"Error loading junction restrictions @ segment {segNodeConf.segmentId}: " + e.ToString());
                    success = false;
                }
            }
            return(success);
        }
 /// <summary>
 /// Handles a segment replacement
 /// </summary>
 /// <param name="replacement">segment replacement</param>
 /// <param name="newEndGeo">new segment end geometry</param>
 protected virtual void HandleSegmentEndReplacement(SegmentEndReplacement replacement, SegmentEndGeometry newEndGeo)
 {
 }
        public void OnUpdate(GeometryUpdate update)
        {
            if (update.segmentGeometry != null)
            {
                // Handle a segment update
                SegmentGeometry geometry = update.segmentGeometry;
                if (!geometry.IsValid())
                {
#if DEBUGGEO
                    if (GlobalConfig.Instance.Debug.Switches[5])
                    {
                        Log._Debug($"{this.GetType().Name}.HandleInvalidSegment({geometry.SegmentId})");
                    }
#endif
                    HandleInvalidSegment(geometry);
                }
                else
                {
#if DEBUGGEO
                    if (GlobalConfig.Instance.Debug.Switches[5])
                    {
                        Log._Debug($"{this.GetType().Name}.HandleValidSegment({geometry.SegmentId})");
                    }
#endif
                    HandleValidSegment(geometry);
                }
            }
            else if (update.nodeGeometry != null)
            {
                // Handle a node update
                NodeGeometry geometry = update.nodeGeometry;
                if (!geometry.IsValid())
                {
#if DEBUGGEO
                    if (GlobalConfig.Instance.Debug.Switches[5])
                    {
                        Log._Debug($"{this.GetType().Name}.HandleInvalidNode({geometry.NodeId})");
                    }
#endif
                    HandleInvalidNode(geometry);
                }
                else
                {
#if DEBUGGEO
                    if (GlobalConfig.Instance.Debug.Switches[5])
                    {
                        Log._Debug($"{this.GetType().Name}.HandleValidNode({geometry.NodeId})");
                    }
#endif
                    HandleValidNode(geometry);
                }
            }
            else
            {
                // Handle a segment end replacement
                SegmentEndGeometry endGeo = SegmentGeometry.Get(update.replacement.newSegmentEndId.SegmentId)?.GetEnd(update.replacement.newSegmentEndId.StartNode);
                if (endGeo != null)
                {
#if DEBUGGEO
                    if (GlobalConfig.Instance.Debug.Switches[5])
                    {
                        Log._Debug($"{this.GetType().Name}.HandleSegmentReplacement({update.replacement.oldSegmentEndId} -> {update.replacement.newSegmentEndId})");
                    }
#endif
                    HandleSegmentEndReplacement(update.replacement, endGeo);
                }
            }
        }
Exemple #18
0
        public void CalculateAutoPedestrianLightState(bool propagate = true)
        {
#if DEBUGTTL
            bool debug = GlobalConfig.Instance.Debug.Switches[7] && GlobalConfig.Instance.Debug.NodeId == NodeId;
#endif

#if DEBUGTTL
            if (debug)
            {
                Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Calculating pedestrian light state of seg. {SegmentId} @ node {NodeId}");
            }
#endif

            SegmentEndGeometry segmentEndGeometry = SegmentGeometry.Get(SegmentId)?.GetEnd(StartNode);

            if (segmentEndGeometry == null)
            {
                Log._Debug($"Could not get SegmentEndGeometry for segment {SegmentId} @ {NodeId}.");
                AutoPedestrianLightState = RoadBaseAI.TrafficLightState.Green;
                return;
            }

            ushort nodeId = segmentEndGeometry.NodeId();
            if (nodeId != NodeId)
            {
                Log.Warning($"CustomSegmentLights.CalculateAutoPedestrianLightState: Node id mismatch! segment end node is {nodeId} but we are node {NodeId}. segmentEndGeometry={segmentEndGeometry} this={this}");
                return;
            }

            if (propagate)
            {
                foreach (ushort otherSegmentId in segmentEndGeometry.ConnectedSegments)
                {
                    if (otherSegmentId == 0)
                    {
                        continue;
                    }

                    ICustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId);
                    if (otherLights == null)
                    {
#if DEBUGTTL
                        if (debug)
                        {
                            Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Expected other (propagate) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}");
                        }
#endif
                        continue;
                    }

                    otherLights.CalculateAutoPedestrianLightState(false);
                }
            }

            if (IsAnyGreen())
            {
#if DEBUGTTL
                if (debug)
                {
                    Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Any green at seg. {SegmentId} @ {NodeId}");
                }
#endif
                AutoPedestrianLightState = RoadBaseAI.TrafficLightState.Red;
                return;
            }

#if DEBUGTTL
            if (debug)
            {
                Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Querying incoming segments at seg. {SegmentId} @ {NodeId}");
            }
#endif
            RoadBaseAI.TrafficLightState autoPedestrianLightState = RoadBaseAI.TrafficLightState.Green;

            ItemClass prevConnectionClass = null;
            Constants.ServiceFactory.NetService.ProcessSegment(SegmentId, delegate(ushort prevSegId, ref NetSegment segment) {
                prevConnectionClass = segment.Info.GetConnectionClass();
                return(true);
            });

            if (!segmentEndGeometry.IncomingOneWay)
            {
                // query straight segments
                foreach (ushort otherSegmentId in segmentEndGeometry.IncomingStraightSegments)
                {
                    if (otherSegmentId == 0)
                    {
                        continue;
                    }
#if DEBUGTTL
                    if (debug)
                    {
                        Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Checking incoming straight segment {otherSegmentId} at seg. {SegmentId} @ {NodeId}");
                    }
#endif

                    ICustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId);
                    if (otherLights == null)
                    {
#if DEBUGTTL
                        if (debug)
                        {
                            Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Expected other (straight) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}");
                        }
#endif
                        continue;
                    }

                    SegmentGeometry otherGeo = SegmentGeometry.Get(otherSegmentId);
                    if (otherGeo == null)
                    {
#if DEBUGTTL
                        if (debug)
                        {
                            Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Expected other (straight) segment geometry at segment {otherSegmentId} @ {NodeId} (startNode={otherLights.StartNode}) but there was none. Original segment id: {SegmentId}");
                        }
#endif
                        continue;
                    }

                    ItemClass nextConnectionClass = null;
                    Constants.ServiceFactory.NetService.ProcessSegment(otherSegmentId, delegate(ushort otherSegId, ref NetSegment segment) {
                        nextConnectionClass = segment.Info.GetConnectionClass();
                        return(true);
                    });

                    if (nextConnectionClass.m_service != prevConnectionClass.m_service)
                    {
#if DEBUGTTL
                        if (debug)
                        {
                            Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Other (straight) segment {otherSegmentId} @ {NodeId} has different connection service than segment {SegmentId} ({nextConnectionClass.m_service} vs. {prevConnectionClass.m_service}). Ignoring traffic light state.");
                        }
#endif
                        continue;
                    }

                    if (!otherLights.IsAllMainRed())
                    {
#if DEBUGTTL
                        if (debug)
                        {
                            Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Not all main red at {otherSegmentId} at seg. {SegmentId} @ {NodeId}");
                        }
#endif
                        autoPedestrianLightState = RoadBaseAI.TrafficLightState.Red;
                        break;
                    }
                }

                // query left/right segments
                if (autoPedestrianLightState == RoadBaseAI.TrafficLightState.Green)
                {
                    bool lhd = Constants.ServiceFactory.SimulationService.LeftHandDrive;
                    foreach (ushort otherSegmentId in lhd ? segmentEndGeometry.IncomingLeftSegments : segmentEndGeometry.IncomingRightSegments)
                    {
                        if (otherSegmentId == 0)
                        {
                            continue;
                        }

#if DEBUGTTL
                        if (debug)
                        {
                            Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Checking left/right segment {otherSegmentId} at seg. {SegmentId} @ {NodeId}");
                        }
#endif

                        ICustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId);
                        if (otherLights == null)
                        {
#if DEBUGTTL
                            if (debug)
                            {
                                Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Expected other (left/right) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}");
                            }
#endif
                            continue;
                        }

                        ItemClass nextConnectionClass = null;
                        Constants.ServiceFactory.NetService.ProcessSegment(otherSegmentId, delegate(ushort otherSegId, ref NetSegment segment) {
                            nextConnectionClass = segment.Info.GetConnectionClass();
                            return(true);
                        });

                        if (nextConnectionClass.m_service != prevConnectionClass.m_service)
                        {
#if DEBUGTTL
                            if (debug)
                            {
                                Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Other (left/right) segment {otherSegmentId} @ {NodeId} has different connection service than segment {SegmentId} ({nextConnectionClass.m_service} vs. {prevConnectionClass.m_service}). Ignoring traffic light state.");
                            }
#endif
                            continue;
                        }

                        if ((lhd && !otherLights.IsAllRightRed()) || (!lhd && !otherLights.IsAllLeftRed()))
                        {
#if DEBUGTTL
                            if (debug)
                            {
                                Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Not all left red at {otherSegmentId} at seg. {SegmentId} @ {NodeId}");
                            }
#endif
                            autoPedestrianLightState = RoadBaseAI.TrafficLightState.Red;
                            break;
                        }
                    }
                }
            }

            AutoPedestrianLightState = autoPedestrianLightState;
#if DEBUGTTL
            if (debug)
            {
                Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Calculated AutoPedestrianLightState for segment {SegmentId} @ {NodeId}: {AutoPedestrianLightState}");
            }
#endif
        }
Exemple #19
0
        internal void CalculateAutoPedestrianLightState(bool propagate = true)
        {
            //Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Calculating pedestrian light state of node {NodeId}");
            SegmentGeometry    segGeo             = SegmentGeometry.Get(SegmentId);
            SegmentEndGeometry segmentEndGeometry = StartNode ? segGeo.StartNodeGeometry : segGeo.EndNodeGeometry;

            if (segmentEndGeometry == null)
            {
                Log._Debug($"Could not get SegmentEndGeometry for segment {SegmentId} @ {NodeId}.");
                AutoPedestrianLightState = RoadBaseAI.TrafficLightState.Green;
                return;
            }
            ushort nodeId = segmentEndGeometry.NodeId();

            if (propagate)
            {
                foreach (ushort otherSegmentId in segmentEndGeometry.ConnectedSegments)
                {
                    if (otherSegmentId == 0)
                    {
                        continue;
                    }

                    CustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId);
                    if (otherLights == null)
                    {
                        //Log._Debug($"Expected other (propagate) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}");
                        continue;
                    }

                    otherLights.CalculateAutoPedestrianLightState(false);
                }
            }

            if (IsAnyGreen())
            {
                //Log._Debug($"Any green at seg. {SegmentId} @ {NodeId}");
                AutoPedestrianLightState = RoadBaseAI.TrafficLightState.Red;
                return;
            }

            //Log._Debug($"Querying incoming segments at seg. {SegmentId} @ {NodeId}");
            RoadBaseAI.TrafficLightState autoPedestrianLightState = RoadBaseAI.TrafficLightState.Green;

            if (!segmentEndGeometry.IncomingOneWay)
            {
                // query straight segments
                foreach (ushort otherSegmentId in segmentEndGeometry.IncomingStraightSegments)
                {
                    if (otherSegmentId == 0)
                    {
                        continue;
                    }
                    //Log._Debug($"Checking incoming straight segment {otherSegmentId} at seg. {SegmentId} @ {NodeId}");

                    CustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId);
                    if (otherLights == null)
                    {
                        //Log._Debug($"Expected other (straight) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}");
                        continue;
                    }

                    if (!otherLights.IsAllMainRed())
                    {
                        //Log._Debug($"Not all main red at {otherSegmentId} at seg. {SegmentId} @ {NodeId}");
                        autoPedestrianLightState = RoadBaseAI.TrafficLightState.Red;
                        break;
                    }
                }

                // query left/right segments
                if (autoPedestrianLightState == RoadBaseAI.TrafficLightState.Green)
                {
                    bool lhd = TrafficPriorityManager.IsLeftHandDrive();
                    foreach (ushort otherSegmentId in lhd ? segmentEndGeometry.IncomingLeftSegments : segmentEndGeometry.IncomingRightSegments)
                    {
                        if (otherSegmentId == 0)
                        {
                            continue;
                        }

                        //Log._Debug($"Checking left/right segment {otherSegmentId} at seg. {SegmentId} @ {NodeId}");

                        CustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId);
                        if (otherLights == null)
                        {
                            //Log._Debug($"Expected other (left/right) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}");
                            continue;
                        }

                        if ((lhd && !otherLights.IsAllRightRed()) || (!lhd && !otherLights.IsAllLeftRed()))
                        {
                            //Log._Debug($"Not all left red at {otherSegmentId} at seg. {SegmentId} @ {NodeId}");
                            autoPedestrianLightState = RoadBaseAI.TrafficLightState.Red;
                            break;
                        }
                    }
                }
            }

            AutoPedestrianLightState = autoPedestrianLightState;
            //Log.Warning($"Calculated AutoPedestrianLightState for segment {SegmentId} @ {NodeId}: {AutoPedestrianLightState}");
        }
        protected override void HandleSegmentEndReplacement(SegmentEndReplacement replacement, SegmentEndGeometry endGeo)
        {
            ISegmentEndId oldSegmentEndId = replacement.oldSegmentEndId;
            ISegmentEndId newSegmentEndId = replacement.newSegmentEndId;

            SegmentEndFlags flags;

            if (oldSegmentEndId.StartNode)
            {
                flags = invalidSegmentFlags[oldSegmentEndId.SegmentId].startNodeFlags;
                invalidSegmentFlags[oldSegmentEndId.SegmentId].startNodeFlags.Reset();
            }
            else
            {
                flags = invalidSegmentFlags[oldSegmentEndId.SegmentId].endNodeFlags;
                invalidSegmentFlags[oldSegmentEndId.SegmentId].endNodeFlags.Reset();
            }

            Services.NetService.ProcessNode(endGeo.NodeId(), delegate(ushort nId, ref NetNode node) {
                flags.UpdateDefaults(newSegmentEndId.SegmentId, newSegmentEndId.StartNode, ref node);
                return(true);
            });
            Log._Debug($"JunctionRestrictionsManager.HandleSegmentEndReplacement({replacement}): Segment replacement detected: {oldSegmentEndId.SegmentId} -> {newSegmentEndId.SegmentId} @ {newSegmentEndId.StartNode}");
            SetSegmentEndFlags(newSegmentEndId.SegmentId, newSegmentEndId.StartNode, flags);
        }