public bool SetSegmentLights(ushort nodeId,
                                     ushort segmentId,
                                     ICustomSegmentLights lights)
        {
            bool?startNode = Services.NetService.IsStartNode(segmentId, nodeId);

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

            CustomSegment customSegment = customSegments_[segmentId];

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

            if ((bool)startNode)
            {
                customSegment.StartNodeLights = lights;
            }
            else
            {
                customSegment.EndNodeLights = lights;
            }

            return(true);
        }
        public void SetLightMode(ushort segmentId,
                                 bool startNode,
                                 ExtVehicleType vehicleType,
                                 LightMode mode)
        {
            ICustomSegmentLights liveLights = GetSegmentLights(segmentId, startNode);

            if (liveLights == null)
            {
                Log.Warning(
                    $"CustomSegmentLightsManager.SetLightMode({segmentId}, {startNode}, " +
                    $"{vehicleType}, {mode}): Could not retrieve segment lights.");
                return;
            }

            ICustomSegmentLight liveLight = liveLights.GetCustomLight(vehicleType);

            if (liveLight == null)
            {
                Log.Error(
                    $"CustomSegmentLightsManager.SetLightMode: Cannot change light mode on seg. " +
                    $"{segmentId} @ {startNode} for vehicle type {vehicleType} to {mode}: Vehicle light not found");
                return;
            }

            liveLight.CurrentMode = mode;
        }
        public bool ApplyLightModes(ushort segmentId,
                                    bool startNode,
                                    ICustomSegmentLights otherLights)
        {
            ICustomSegmentLights sourceLights = GetSegmentLights(segmentId, startNode);

            if (sourceLights == null)
            {
                Log.Warning(
                    $"CustomSegmentLightsManager.ApplyLightModes({segmentId}, {startNode}, " +
                    $"{otherLights}): Could not retrieve segment lights.");
                return(false);
            }

            foreach (KeyValuePair <ExtVehicleType, ICustomSegmentLight> e in sourceLights.CustomLights)
            {
                ExtVehicleType      vehicleType = e.Key;
                ICustomSegmentLight targetLight = e.Value;

                if (otherLights.CustomLights.TryGetValue(vehicleType, out ICustomSegmentLight sourceLight))
                {
                    targetLight.CurrentMode = sourceLight.CurrentMode;
                }
            }

            return(true);
        }
Ejemplo n.º 4
0
        private bool IsPedestrianLightHovered(Rect myRect3,
                                              int segmentId,
                                              bool hoveredSegment,
                                              ICustomSegmentLights segmentLights)
        {
            if (!myRect3.Contains(Event.current.mousePosition))
            {
                return(hoveredSegment);
            }

            if (segmentLights.PedestrianLightState == null)
            {
                return(false);
            }

            hoveredButton[0] = segmentId;
            hoveredButton[1] = 2;

            if (!MainTool.CheckClicked())
            {
                return(true);
            }

            if (!segmentLights.ManualPedestrianMode)
            {
                segmentLights.ManualPedestrianMode = true;
            }
            else
            {
                segmentLights.ChangeLightPedestrian();
            }

            return(true);
        }
        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);
        }
Ejemplo n.º 6
0
        private bool RenderCounter(int segmentId, Vector3 screenPos, float modeWidth, float modeHeight, float zoom,
                                   ICustomSegmentLights segmentLights, bool hoveredSegment)
        {
            SetAlpha(segmentId, 0);

            var myRectCounter = new Rect(screenPos.x - modeWidth / 2, screenPos.y - modeHeight / 2 - 6f * zoom, modeWidth, modeHeight);

            GUI.DrawTexture(myRectCounter, TextureResources.LightCounterTexture2D);

            var counterSize = 20f * zoom;

            var counter = segmentLights.LastChange();

            var myRectCounterNum = new Rect(screenPos.x - counterSize + 15f * zoom + (counter >= 10 ? -5 * zoom : 0f),
                                            screenPos.y - counterSize + 11f * zoom, counterSize, counterSize);

            _counterStyle.fontSize         = (int)(18f * zoom);
            _counterStyle.normal.textColor = new Color(1f, 1f, 1f);

            GUI.Label(myRectCounterNum, counter.ToString(), _counterStyle);

            if (!myRectCounter.Contains(Event.current.mousePosition))
            {
                return(hoveredSegment);
            }
            _hoveredButton[0] = segmentId;
            _hoveredButton[1] = 0;
            return(true);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Configures traffic light for and for all lane types at input segmentId, nodeId, and step.
        /// </summary>
        /// <param name="step"></param>
        /// <param name="nodeId"></param>
        /// <param name="segmentId"></param>
        /// <param name="m">Determines which directions are green</param>
        private static void SetupHelper(ITimedTrafficLightsStep step, ushort nodeId, ushort segmentId, GreenDir m)
        {
            bool startNode = (bool)netService.IsStartNode(segmentId, nodeId);

            //get step data for side seg
            ICustomSegmentLights liveSegmentLights = customTrafficLightsManager.GetSegmentLights(segmentId, startNode);

            //for each lane type
            foreach (ExtVehicleType vehicleType in liveSegmentLights.VehicleTypes)
            {
                //set light mode
                ICustomSegmentLight liveSegmentLight = liveSegmentLights.GetCustomLight(vehicleType);
                liveSegmentLight.CurrentMode = LightMode.All;

                TimedLight(nodeId).ChangeLightMode(
                    segmentId,
                    vehicleType,
                    liveSegmentLight.CurrentMode);

                // set light states
                var green = RoadBaseAI.TrafficLightState.Green;
                var red   = RoadBaseAI.TrafficLightState.Red;
                switch (m)
                {
                case GreenDir.AllRed:
                    liveSegmentLight.SetStates(red, red, red);
                    break;

                case GreenDir.AllGreen:
                    liveSegmentLight.SetStates(green, green, green);
                    break;

                case GreenDir.ShortOnly: {
                    // calculate directions
                    ref ExtSegmentEnd segEnd = ref segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, nodeId)];
                    ref NetNode       node   = ref Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId];
                    segEndMan.CalculateOutgoingLeftStraightRightSegments(ref segEnd, ref node, out bool bLeft, out bool bForward, out bool bRight);
                    bool bShort = RHT ? bRight : bLeft;
                    bool bLong  = RHT ? bLeft : bRight;

                    if (bShort)
                    {
                        SetStates(liveSegmentLight, red, red, green);
                    }
                    else if (bLong)
                    {
                        // go forward instead of short
                        SetStates(liveSegmentLight, green, red, red);
                    }
                    else
                    {
                        Debug.LogAssertion("Unreachable code.");
                        liveSegmentLight.SetStates(green, green, green);
                    }
                    break;
                }
        AddSegmentLights(ushort segmentId,
                         bool startNode,
                         RoadBaseAI.TrafficLightState lightState =
                         RoadBaseAI.TrafficLightState.Red)
        {
#if DEBUG
            Log._Trace($"CustomTrafficLights.AddSegmentLights: Adding segment light: {segmentId} @ startNode={startNode}");
#endif
            if (!Services.NetService.IsSegmentValid(segmentId))
            {
                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);
                }
            }

            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);
            }
        }
        /// <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);
            }
        }
Ejemplo n.º 10
0
        private bool RenderManualPedestrianLightSwitch(float zoom,
                                                       int segmentId,
                                                       Vector3 screenPos,
                                                       float lightWidth,
                                                       ICustomSegmentLights segmentLights,
                                                       bool hoveredSegment)
        {
            if (segmentLights.PedestrianLightState == null)
            {
                return(false);
            }

            Color guiColor = GUI.color;
            float manualPedestrianWidth  = 36f * zoom;
            float manualPedestrianHeight = 35f * zoom;

            guiColor.a = TrafficManagerTool.GetHandleAlpha(
                hoveredButton[0] == segmentId &&
                (hoveredButton[1] == 1 ||
                 hoveredButton[1] == 2));

            GUI.color = guiColor;

            var myRect2 = new Rect(
                screenPos.x - (manualPedestrianWidth / 2) - lightWidth + (5f * zoom),
                screenPos.y - (manualPedestrianHeight / 2) - (9f * zoom),
                manualPedestrianWidth,
                manualPedestrianHeight);

            GUI.DrawTexture(
                myRect2,
                segmentLights.ManualPedestrianMode
                    ? TrafficLightTextures.PedestrianModeManual
                    : TrafficLightTextures.PedestrianModeAutomatic);

            if (!myRect2.Contains(Event.current.mousePosition))
            {
                return(hoveredSegment);
            }

            hoveredButton[0] = segmentId;
            hoveredButton[1] = 1;

            if (!MainTool.CheckClicked())
            {
                return(true);
            }

            segmentLights.ManualPedestrianMode = !segmentLights.ManualPedestrianMode;
            return(true);
        }
        private static void GetCustomTrafficLightState(ushort nodeId, ushort fromSegmentId, byte fromLaneIndex, ushort toSegmentId, out RoadBaseAI.TrafficLightState vehicleLightState, out RoadBaseAI.TrafficLightState pedestrianLightState, ref TrafficLightSimulation nodeSim)
        {
            SegmentGeometry segmentGeometry = SegmentGeometry.Get(fromSegmentId, false);

            if (segmentGeometry == null)
            {
                //Log.Error(string.Format("GetTrafficLightState: No geometry information @ node {0}, segment {1}.", nodeId, fromSegmentId));
                vehicleLightState    = RoadBaseAI.TrafficLightState.Green;
                pedestrianLightState = RoadBaseAI.TrafficLightState.Green;
                return;
            }
            bool startNode = segmentGeometry.StartNodeId() == nodeId;
            ICustomSegmentLights segmentLights = CustomSegmentLightsManager.Instance.GetSegmentLights(fromSegmentId, startNode, false, RoadBaseAI.TrafficLightState.Red);

            if (segmentLights != null)
            {
                pedestrianLightState = (segmentLights.PedestrianLightState.HasValue ? segmentLights.PedestrianLightState.Value : RoadBaseAI.TrafficLightState.Green);
            }
            else
            {
                pedestrianLightState = RoadBaseAI.TrafficLightState.Green;
            }
            ICustomSegmentLight customSegmentLight = (segmentLights == null) ? null : segmentLights.GetCustomLight(fromLaneIndex);

            if (segmentLights == null || customSegmentLight == null)
            {
                vehicleLightState = RoadBaseAI.TrafficLightState.Green;
                return;
            }
            if (toSegmentId == fromSegmentId)
            {
                vehicleLightState = (Constants.ServiceFactory.SimulationService.LeftHandDrive ? customSegmentLight.LightRight : customSegmentLight.LightLeft);
                return;
            }
            if (segmentGeometry.IsLeftSegment(toSegmentId, startNode))
            {
                vehicleLightState = customSegmentLight.LightLeft;
                return;
            }
            if (segmentGeometry.IsRightSegment(toSegmentId, startNode))
            {
                vehicleLightState = customSegmentLight.LightRight;
                return;
            }
            vehicleLightState = customSegmentLight.LightMain;
        }
Ejemplo n.º 12
0
        public void SetLights(ICustomSegmentLights otherLights)
        {
            foreach (KeyValuePair <ExtVehicleType, ICustomSegmentLight> e in otherLights.CustomLights)
            {
                ICustomSegmentLight ourLight = null;
                if (!CustomLights.TryGetValue(e.Key, out ourLight))
                {
                    continue;
                }

                ourLight.SetStates(e.Value.LightMain, e.Value.LightLeft, e.Value.LightRight, false);
                //ourLight.LightPedestrian = e.Value.LightPedestrian;
            }
            InternalPedestrianLightState = otherLights.InternalPedestrianLightState;
            manualPedestrianMode         = otherLights.ManualPedestrianMode;
            AutoPedestrianLightState     = otherLights.AutoPedestrianLightState;
        }
Ejemplo n.º 13
0
        private bool RenderManualPedestrianLightSwitch(float zoom, int segmentId, Vector3 screenPos, float lightWidth,
                                                       ICustomSegmentLights segmentLights, bool hoveredSegment)
        {
            if (segmentLights.PedestrianLightState == null)
            {
                return(false);
            }

            var guiColor = GUI.color;
            var manualPedestrianWidth  = 36f * zoom;
            var manualPedestrianHeight = 35f * zoom;

            guiColor.a = MainTool.GetHandleAlpha(_hoveredButton[0] == segmentId && (_hoveredButton[1] == 1 || _hoveredButton[1] == 2));

            GUI.color = guiColor;

            var myRect2 = new Rect(screenPos.x - manualPedestrianWidth / 2 - lightWidth + 5f * zoom,
                                   screenPos.y - manualPedestrianHeight / 2 - 9f * zoom, manualPedestrianWidth, manualPedestrianHeight);

            GUI.DrawTexture(myRect2, segmentLights.ManualPedestrianMode ? TextureResources.PedestrianModeManualTexture2D : TextureResources.PedestrianModeAutomaticTexture2D);

            if (!myRect2.Contains(Event.current.mousePosition))
            {
                return(hoveredSegment);
            }

            _hoveredButton[0] = segmentId;
            _hoveredButton[1] = 1;

            if (!MainTool.CheckClicked())
            {
                return(true);
            }

            segmentLights.ManualPedestrianMode = !segmentLights.ManualPedestrianMode;
            return(true);
        }
        public bool CustomCheckTrafficLights(ushort node, ushort segment)
        {
            var netManager = Singleton <NetManager> .instance;

            var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
            var num          = (uint)((node << 8) / 32768);
            var stepWaitTime = currentFrameIndex - num & 255u;

            // NON-STOCK CODE START //
            var nodeSimulation = Options.timedLightsEnabled ? TrafficLightSimulationManager.Instance.GetNodeSimulation(node) : null;

            RoadBaseAI.TrafficLightState pedestrianLightState;
            bool startNode = netManager.m_segments.m_buffer[segment].m_startNode == node;

            ICustomSegmentLights lights = null;

            if (nodeSimulation != null && nodeSimulation.IsSimulationActive())
            {
                lights = CustomSegmentLightsManager.Instance.GetSegmentLights(segment, startNode, false);
            }

            if (lights == null)
            {
                // NON-STOCK CODE END //
                RoadBaseAI.TrafficLightState vehicleLightState;
                bool vehicles;
                bool pedestrians;

                RoadBaseAI.GetTrafficLightState(node, ref netManager.m_segments.m_buffer[segment], currentFrameIndex - num, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians);
                if ((pedestrianLightState == RoadBaseAI.TrafficLightState.GreenToRed || pedestrianLightState == RoadBaseAI.TrafficLightState.Red) && !pedestrians && stepWaitTime >= 196u)
                {
                    RoadBaseAI.SetTrafficLightState(node, ref netManager.m_segments.m_buffer[segment], currentFrameIndex - num, vehicleLightState, pedestrianLightState, vehicles, true);
                    return(true);
                }
                // NON-STOCK CODE START //
            }
            else
            {
                if (lights.InvalidPedestrianLight)
                {
                    pedestrianLightState = RoadBaseAI.TrafficLightState.Green;
                }
                else
                {
                    pedestrianLightState = (RoadBaseAI.TrafficLightState)lights.PedestrianLightState;
                }
            }
            // NON-STOCK CODE END //

            switch (pedestrianLightState)
            {
            case RoadBaseAI.TrafficLightState.RedToGreen:
                if (stepWaitTime < 60u)
                {
                    return(false);
                }
                break;

            case RoadBaseAI.TrafficLightState.Red:
            case RoadBaseAI.TrafficLightState.GreenToRed:
                return(false);
            }
            return(true);
        }
Ejemplo n.º 15
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
        }
Ejemplo n.º 16
0
        public bool CustomCheckTrafficLights(ushort nodeId, ushort segmentId)
        {
#if DEBUGTTL
            bool debug = GlobalConfig.Instance.Debug.Switches[7] && GlobalConfig.Instance.Debug.NodeId == nodeId;
#endif

            var netManager = Singleton <NetManager> .instance;

            var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
            var num          = (uint)(((int)nodeId << 8) / 32768);
            var stepWaitTime = currentFrameIndex - num & 255u;

            // NON-STOCK CODE START //

            bool customSim = false;
#if BENCHMARK
            using (var bm = new Benchmark(null, "GetNodeSimulation")) {
#endif
            customSim = Options.timedLightsEnabled && TrafficLightSimulationManager.Instance.HasActiveSimulation(nodeId);
#if BENCHMARK
        }
#endif
            RoadBaseAI.TrafficLightState pedestrianLightState;
            bool startNode = netManager.m_segments.m_buffer[segmentId].m_startNode == nodeId;

            ICustomSegmentLights lights = null;
#if BENCHMARK
            using (var bm = new Benchmark(null, "GetSegmentLights")) {
#endif
            if (customSim)
            {
                lights = CustomSegmentLightsManager.Instance.GetSegmentLights(segmentId, startNode, false);
            }
#if BENCHMARK
        }
#endif

            if (lights == null)
            {
                // NON-STOCK CODE END //
                RoadBaseAI.TrafficLightState vehicleLightState;
                bool vehicles;
                bool pedestrians;

#if DEBUGTTL
                if (debug)
                {
                    Log._Debug($"CustomHumanAI.CustomCheckTrafficLights({nodeId}, {segmentId}): No custom simulation!");
                }
#endif

                RoadBaseAI.GetTrafficLightState(nodeId, ref netManager.m_segments.m_buffer[segmentId], currentFrameIndex - num, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians);
                if (pedestrianLightState == RoadBaseAI.TrafficLightState.GreenToRed || pedestrianLightState == RoadBaseAI.TrafficLightState.Red)
                {
                    if (!pedestrians && stepWaitTime >= 196u)
                    {
                        RoadBaseAI.SetTrafficLightState(nodeId, ref netManager.m_segments.m_buffer[segmentId], currentFrameIndex - num, vehicleLightState, pedestrianLightState, vehicles, true);
                    }
                    return(false);
                }
                // NON-STOCK CODE START //
            }
            else
            {
                if (lights.InvalidPedestrianLight)
                {
                    pedestrianLightState = RoadBaseAI.TrafficLightState.Green;
                }
                else
                {
                    pedestrianLightState = (RoadBaseAI.TrafficLightState)lights.PedestrianLightState;
                }

#if DEBUGTTL
                if (debug)
                {
                    Log._Debug($"CustomHumanAI.CustomCheckTrafficLights({nodeId}, {segmentId}): Custom simulation! pedestrianLightState={pedestrianLightState}, lights.InvalidPedestrianLight={lights.InvalidPedestrianLight}");
                }
#endif
            }
            // NON-STOCK CODE END //

            switch (pedestrianLightState)
            {
            case RoadBaseAI.TrafficLightState.RedToGreen:
                if (stepWaitTime < 60u)
                {
                    return(false);
                }
                break;

            case RoadBaseAI.TrafficLightState.Red:
            case RoadBaseAI.TrafficLightState.GreenToRed:
                return(false);
            }
            return(true);
        }
        public List <Configuration.TimedTrafficLights> SaveData(ref bool success)
        {
            var ret = new List <Configuration.TimedTrafficLights>();

            for (uint nodeId = 0; nodeId < NetManager.MAX_NODE_COUNT; ++nodeId)
            {
                try {
                    if (!TrafficLightSimulations[nodeId].IsTimedLight())
                    {
                        continue;
                    }

#if DEBUGSAVE
                    Log._Debug($"Going to save timed light at node {nodeId}.");
#endif
                    ITimedTrafficLights timedNode = TrafficLightSimulations[nodeId].timedLight;
                    timedNode.OnGeometryUpdate();

                    var cnfTimedLights = new Configuration.TimedTrafficLights {
                        nodeId    = timedNode.NodeId,
                        nodeGroup = new List <ushort>(timedNode.NodeGroup),
                        started   = timedNode.IsStarted()
                    };
                    ret.Add(cnfTimedLights);

                    int stepIndex = timedNode.CurrentStep;
                    if (timedNode.IsStarted() &&
                        timedNode.GetStep(timedNode.CurrentStep).IsInEndTransition())
                    {
                        // if in end transition save the next step
                        stepIndex = (stepIndex + 1) % timedNode.NumSteps();
                    }

                    cnfTimedLights.currentStep = stepIndex;
                    cnfTimedLights.timedSteps  = new List <Configuration.TimedTrafficLightsStep>();

                    for (var j = 0; j < timedNode.NumSteps(); j++)
                    {
#if DEBUGSAVE
                        Log._Debug($"Saving timed light step {j} at node {nodeId}.");
#endif
                        ITimedTrafficLightsStep timedStep = timedNode.GetStep(j);
                        var cnfTimedStep = new Configuration.TimedTrafficLightsStep {
                            minTime         = timedStep.MinTime,
                            maxTime         = timedStep.MaxTime,
                            changeMetric    = (int)timedStep.ChangeMetric,
                            waitFlowBalance = timedStep.WaitFlowBalance,
                            segmentLights   = new Dictionary <ushort, Configuration.CustomSegmentLights>()
                        };
                        cnfTimedLights.timedSteps.Add(cnfTimedStep);

                        foreach (KeyValuePair <ushort, ICustomSegmentLights> e
                                 in timedStep.CustomSegmentLights)
                        {
#if DEBUGSAVE
                            Log._Debug($"Saving timed light step {j}, segment {e.Key} at node {nodeId}.");
#endif

                            ICustomSegmentLights segLights = e.Value;
                            ushort lightsNodeId            = segLights.NodeId;

                            var cnfSegLights = new Configuration.CustomSegmentLights {
                                nodeId               = lightsNodeId,        // TODO not needed
                                segmentId            = segLights.SegmentId, // TODO not needed
                                customLights         = new Dictionary <ExtVehicleType, Configuration.CustomSegmentLight>(),
                                pedestrianLightState = segLights.PedestrianLightState,
                                manualPedestrianMode = segLights.ManualPedestrianMode
                            };

                            if (lightsNodeId == 0 || lightsNodeId != timedNode.NodeId)
                            {
                                Log.Warning(
                                    "Inconsistency detected: Timed traffic light @ node " +
                                    $"{timedNode.NodeId} contains custom traffic lights for the invalid " +
                                    $"segment ({segLights.SegmentId}) at step {j}: nId={lightsNodeId}");
                                continue;
                            }

                            cnfTimedStep.segmentLights.Add(e.Key, cnfSegLights);

#if DEBUGSAVE
                            Log._Debug($"Saving pedestrian light @ seg. {e.Key}, step {j}: " +
                                       $"{cnfSegLights.pedestrianLightState} {cnfSegLights.manualPedestrianMode}");
#endif

                            foreach (KeyValuePair <API.Traffic.Enums.ExtVehicleType,
                                                   ICustomSegmentLight> e2 in segLights.CustomLights)
                            {
#if DEBUGSAVE
                                Log._Debug($"Saving timed light step {j}, segment {e.Key}, vehicleType " +
                                           $"{e2.Key} at node {nodeId}.");
#endif
                                ICustomSegmentLight segLight = e2.Value;
                                var cnfSegLight = new Configuration.CustomSegmentLight {
                                    nodeId      = lightsNodeId,        // TODO not needed
                                    segmentId   = segLights.SegmentId, // TODO not needed
                                    currentMode = (int)segLight.CurrentMode,
                                    leftLight   = segLight.LightLeft,
                                    mainLight   = segLight.LightMain,
                                    rightLight  = segLight.LightRight
                                };

                                cnfSegLights.customLights.Add(
                                    LegacyExtVehicleType.ToOld(e2.Key),
                                    cnfSegLight);
                            }
                        }
                    }
                }
                catch (Exception e) {
                    Log.Error(
                        $"Exception occurred while saving timed traffic light @ {nodeId}: {e}");
                    success = false;
                }
            }

            return(ret);
        }
        public bool LoadData(List <Configuration.TimedTrafficLights> data)
        {
            bool success = true;

            Log.Info($"Loading {data.Count} timed traffic lights (new method)");

            var nodesWithSimulation = new HashSet <ushort>();

            foreach (Configuration.TimedTrafficLights cnfTimedLights in data)
            {
                nodesWithSimulation.Add(cnfTimedLights.nodeId);
            }

            var masterNodeIdBySlaveNodeId = new Dictionary <ushort, ushort>();
            var nodeGroupByMasterNodeId   = new Dictionary <ushort, List <ushort> >();

            foreach (Configuration.TimedTrafficLights cnfTimedLights in data)
            {
                try {
                    // TODO most of this should not be necessary at all if the classes around TimedTrafficLights class were properly designed
                    // enforce uniqueness of node ids
                    List <ushort> currentNodeGroup = cnfTimedLights.nodeGroup.Distinct().ToList();

                    if (!currentNodeGroup.Contains(cnfTimedLights.nodeId))
                    {
                        currentNodeGroup.Add(cnfTimedLights.nodeId);
                    }

                    // remove any nodes that are not configured to have a simulation
                    currentNodeGroup = new List <ushort>(
                        currentNodeGroup.Intersect(nodesWithSimulation));

                    // remove invalid nodes from the group; find if any of the nodes in the group is already a master node
                    ushort masterNodeId     = 0;
                    int    foundMasterNodes = 0;

                    for (int i = 0; i < currentNodeGroup.Count;)
                    {
                        ushort nodeId = currentNodeGroup[i];

                        if (!Services.NetService.IsNodeValid(currentNodeGroup[i]))
                        {
                            currentNodeGroup.RemoveAt(i);
                            continue;
                        }

                        if (nodeGroupByMasterNodeId.ContainsKey(nodeId))
                        {
                            // this is a known master node
                            if (foundMasterNodes > 0)
                            {
                                // we already found another master node. ignore this node.
                                currentNodeGroup.RemoveAt(i);
                                continue;
                            }

                            // we found the first master node
                            masterNodeId = nodeId;
                            ++foundMasterNodes;
                        }

                        ++i;
                    }

                    if (masterNodeId == 0)
                    {
                        // no master node defined yet, set the first node as a master node
                        masterNodeId = currentNodeGroup[0];
                    }

                    // ensure the master node is the first node in the list (TimedTrafficLights
                    // depends on this at the moment...)
                    currentNodeGroup.Remove(masterNodeId);
                    currentNodeGroup.Insert(0, masterNodeId);

                    // update the saved node group and master-slave info
                    nodeGroupByMasterNodeId[masterNodeId] = currentNodeGroup;

                    foreach (ushort nodeId in currentNodeGroup)
                    {
                        masterNodeIdBySlaveNodeId[nodeId] = masterNodeId;
                    }
                } catch (Exception e) {
                    Log.WarningFormat(
                        "Error building timed traffic light group for TimedNode {0} (NodeGroup: {1}): {2}",
                        cnfTimedLights.nodeId,
                        string.Join(", ", cnfTimedLights.nodeGroup.Select(x => x.ToString()).ToArray()),
                        e);
                    success = false;
                }
            }

            foreach (Configuration.TimedTrafficLights cnfTimedLights in data)
            {
                try {
                    if (!masterNodeIdBySlaveNodeId.ContainsKey(cnfTimedLights.nodeId))
                    {
                        continue;
                    }

                    ushort        masterNodeId = masterNodeIdBySlaveNodeId[cnfTimedLights.nodeId];
                    List <ushort> nodeGroup    = nodeGroupByMasterNodeId[masterNodeId];

#if DEBUGLOAD
                    Log._Debug($"Adding timed light at node {cnfTimedLights.nodeId}. NodeGroup: " +
                               $"{string.Join(", ", nodeGroup.Select(x => x.ToString()).ToArray())}");
#endif
                    SetUpTimedTrafficLight(cnfTimedLights.nodeId, nodeGroup);

                    int j = 0;
                    foreach (Configuration.TimedTrafficLightsStep cnfTimedStep in cnfTimedLights.timedSteps)
                    {
#if DEBUGLOAD
                        Log._Debug($"Loading timed step {j} at node {cnfTimedLights.nodeId}");
#endif
                        ITimedTrafficLightsStep step =
                            TrafficLightSimulations[cnfTimedLights.nodeId].timedLight.AddStep(
                                cnfTimedStep.minTime,
                                cnfTimedStep.maxTime,
                                (StepChangeMetric)cnfTimedStep.changeMetric,
                                cnfTimedStep.waitFlowBalance);

                        foreach (KeyValuePair <ushort, Configuration.CustomSegmentLights> e in
                                 cnfTimedStep.segmentLights)
                        {
                            if (!Services.NetService.IsSegmentValid(e.Key))
                            {
                                continue;
                            }

                            e.Value.nodeId = cnfTimedLights.nodeId;

#if DEBUGLOAD
                            Log._Debug($"Loading timed step {j}, segment {e.Key} at node {cnfTimedLights.nodeId}");
#endif
                            ICustomSegmentLights lights = null;
                            if (!step.CustomSegmentLights.TryGetValue(e.Key, out lights))
                            {
#if DEBUGLOAD
                                Log._Debug($"No segment lights found at timed step {j} for segment " +
                                           $"{e.Key}, node {cnfTimedLights.nodeId}");
#endif
                                continue;
                            }

                            Configuration.CustomSegmentLights cnfLights = e.Value;

#if DEBUGLOAD
                            Log._Debug($"Loading pedestrian light @ seg. {e.Key}, step {j}: " +
                                       $"{cnfLights.pedestrianLightState} {cnfLights.manualPedestrianMode}");
#endif
                            lights.ManualPedestrianMode = cnfLights.manualPedestrianMode;
                            lights.PedestrianLightState = cnfLights.pedestrianLightState;

                            bool first = true; // v1.10.2 transitional code
                            foreach (KeyValuePair <ExtVehicleType, Configuration.CustomSegmentLight> e2
                                     in cnfLights.customLights)
                            {
#if DEBUGLOAD
                                Log._Debug($"Loading timed step {j}, segment {e.Key}, vehicleType " +
                                           $"{e2.Key} at node {cnfTimedLights.nodeId}");
#endif
                                if (!lights.CustomLights.TryGetValue(
                                        LegacyExtVehicleType.ToNew(e2.Key),
                                        out ICustomSegmentLight light))
                                {
#if DEBUGLOAD
                                    Log._Debug($"No segment light found for timed step {j}, segment " +
                                               $"{e.Key}, vehicleType {e2.Key} at node {cnfTimedLights.nodeId}");
#endif
                                    // v1.10.2 transitional code START
                                    if (first)
                                    {
                                        first = false;
                                        if (!lights.CustomLights.TryGetValue(
                                                CustomSegmentLights
                                                .DEFAULT_MAIN_VEHICLETYPE,
                                                out light))
                                        {
#if DEBUGLOAD
                                            Log._Debug($"No segment light found for timed step {j}, " +
                                                       $"segment {e.Key}, DEFAULT vehicleType {CustomSegmentLights.DEFAULT_MAIN_VEHICLETYPE} " +
                                                       $"at node {cnfTimedLights.nodeId}");
#endif
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        // v1.10.2 transitional code END
                                        continue;

                                        // v1.10.2 transitional code START
                                    }

                                    // v1.10.2 transitional code END
                                }

                                Configuration.CustomSegmentLight cnfLight = e2.Value;

                                light.InternalCurrentMode = (LightMode)cnfLight.currentMode; // TODO improve & remove
                                light.SetStates(
                                    cnfLight.mainLight,
                                    cnfLight.leftLight,
                                    cnfLight.rightLight,
                                    false);
                            }
                        }

                        ++j;
                    }
                } catch (Exception e) {
                    // ignore, as it's probably corrupt save data. it'll be culled on next save
                    Log.Warning($"Error loading data from TimedNode (new method): {e}");
                    success = false;
                }
            }

            foreach (Configuration.TimedTrafficLights cnfTimedLights in data)
            {
                try {
                    ITimedTrafficLights timedNode =
                        TrafficLightSimulations[cnfTimedLights.nodeId].timedLight;

                    timedNode.Housekeeping();
                    if (cnfTimedLights.started)
                    {
                        timedNode.Start(cnfTimedLights.currentStep);
                    }
                } catch (Exception e) {
                    Log.Warning($"Error starting timed light @ {cnfTimedLights.nodeId}: {e}");
                    success = false;
                }
            }

            return(success);
        }
        // TODO this should be optimized
        protected void GetCustomTrafficLightState(
#if DEBUG
            ushort vehicleId,
            ref Vehicle vehicleData,
#endif
            ushort nodeId,
            ushort fromSegmentId,
            byte fromLaneIndex,
            ushort toSegmentId,
            out TrafficLightState vehicleLightState,
            out TrafficLightState pedestrianLightState,
            ref TrafficLightSimulation nodeSim)
        {
            // get responsible traffic light
            // Log._Debug($"GetTrafficLightState: Getting custom light for vehicle {vehicleId} @
            //     node {nodeId}, segment {fromSegmentId}, lane {fromLaneIndex}.");
            // SegmentGeometry geometry = SegmentGeometry.Get(fromSegmentId);
            // if (geometry == null) {
            //    Log.Error($"GetTrafficLightState: No geometry information @ node {nodeId}, segment {fromSegmentId}.");
            //    vehicleLightState = TrafficLightState.Green;
            //    pedestrianLightState = TrafficLightState.Green;
            //    return;
            // }

            // determine node position at `fromSegment` (start/end)
            // bool isStartNode = geometry.StartNodeId == nodeId;
            bool?isStartNode = Services.NetService.IsStartNode(fromSegmentId, nodeId);

            if (isStartNode == null)
            {
                Log.Error($"GetTrafficLightState: Invalid node {nodeId} for segment {fromSegmentId}.");
                vehicleLightState    = TrafficLightState.Green;
                pedestrianLightState = TrafficLightState.Green;
                return;
            }

            ICustomSegmentLights lights =
                CustomSegmentLightsManager.Instance.GetSegmentLights(
                    fromSegmentId,
                    (bool)isStartNode,
                    false);

            if (lights != null)
            {
                // get traffic lights state for pedestrians
                pedestrianLightState = lights.PedestrianLightState ?? TrafficLightState.Green;
            }
            else
            {
                pedestrianLightState = TrafficLightState.Green;
                Log._Debug($"GetTrafficLightState: No pedestrian light @ node {nodeId}, " +
                           $"segment {fromSegmentId} found.");
            }

            ICustomSegmentLight light = lights == null ? null : lights.GetCustomLight(fromLaneIndex);

            if (lights == null || light == null)
            {
                // Log.Warning($"GetTrafficLightState: No custom light for vehicle {vehicleId} @ node
                //     {nodeId}, segment {fromSegmentId}, lane {fromLaneIndex} found. lights null?
                //     {lights == null} light null? {light == null}");
                vehicleLightState = TrafficLightState.Green;
                return;
            }

            // get traffic light state from responsible traffic light
            vehicleLightState = light.GetLightState(toSegmentId);
#if DEBUG
            // Log._Debug($"GetTrafficLightState: Getting light for vehicle {vehicleId} @ node {nodeId},
            //     segment {fromSegmentId}, lane {fromLaneIndex}. vehicleLightState={vehicleLightState},
            //     pedestrianLightState={pedestrianLightState}");
#endif
        }
        public List <Configuration.TimedTrafficLights> SaveData(ref bool success)
        {
            List <Configuration.TimedTrafficLights> ret = new List <Configuration.TimedTrafficLights>();

            for (uint nodeId = 0; nodeId < NetManager.MAX_NODE_COUNT; ++nodeId)
            {
                try {
                    ITrafficLightSimulation sim = GetNodeSimulation((ushort)nodeId);
                    if (sim == null || !sim.IsTimedLight())
                    {
                        continue;
                    }

                    Log._Debug($"Going to save timed light at node {nodeId}.");

                    var timedNode = sim.TimedLight;
                    timedNode.OnGeometryUpdate();

                    Configuration.TimedTrafficLights cnfTimedLights = new Configuration.TimedTrafficLights();
                    ret.Add(cnfTimedLights);

                    cnfTimedLights.nodeId    = timedNode.NodeId;
                    cnfTimedLights.nodeGroup = new List <ushort>(timedNode.NodeGroup);
                    cnfTimedLights.started   = timedNode.IsStarted();
                    int stepIndex = timedNode.CurrentStep;
                    if (timedNode.IsStarted() && timedNode.GetStep(timedNode.CurrentStep).IsInEndTransition())
                    {
                        // if in end transition save the next step
                        stepIndex = (stepIndex + 1) % timedNode.NumSteps();
                    }
                    cnfTimedLights.currentStep = stepIndex;
                    cnfTimedLights.timedSteps  = new List <Configuration.TimedTrafficLightsStep>();

                    for (var j = 0; j < timedNode.NumSteps(); j++)
                    {
                        Log._Debug($"Saving timed light step {j} at node {nodeId}.");
                        ITimedTrafficLightsStep timedStep = timedNode.GetStep(j);
                        Configuration.TimedTrafficLightsStep cnfTimedStep = new Configuration.TimedTrafficLightsStep();
                        cnfTimedLights.timedSteps.Add(cnfTimedStep);

                        cnfTimedStep.minTime         = timedStep.MinTime;
                        cnfTimedStep.maxTime         = timedStep.MaxTime;
                        cnfTimedStep.changeMetric    = (int)timedStep.ChangeMetric;
                        cnfTimedStep.waitFlowBalance = timedStep.WaitFlowBalance;
                        cnfTimedStep.segmentLights   = new Dictionary <ushort, Configuration.CustomSegmentLights>();
                        foreach (KeyValuePair <ushort, ICustomSegmentLights> e in timedStep.CustomSegmentLights)
                        {
                            Log._Debug($"Saving timed light step {j}, segment {e.Key} at node {nodeId}.");

                            ICustomSegmentLights segLights = e.Value;
                            Configuration.CustomSegmentLights cnfSegLights = new Configuration.CustomSegmentLights();

                            ushort lightsNodeId = segLights.NodeId;
                            if (lightsNodeId == 0 || lightsNodeId != timedNode.NodeId)
                            {
                                Log.Warning($"Inconsistency detected: Timed traffic light @ node {timedNode.NodeId} contains custom traffic lights for the invalid segment ({segLights.SegmentId}) at step {j}: nId={lightsNodeId}");
                                continue;
                            }

                            cnfSegLights.nodeId               = lightsNodeId;               // TODO not needed
                            cnfSegLights.segmentId            = segLights.SegmentId;        // TODO not needed
                            cnfSegLights.customLights         = new Dictionary <ExtVehicleType, Configuration.CustomSegmentLight>();
                            cnfSegLights.pedestrianLightState = segLights.PedestrianLightState;
                            cnfSegLights.manualPedestrianMode = segLights.ManualPedestrianMode;

                            cnfTimedStep.segmentLights.Add(e.Key, cnfSegLights);

                            Log._Debug($"Saving pedestrian light @ seg. {e.Key}, step {j}: {cnfSegLights.pedestrianLightState} {cnfSegLights.manualPedestrianMode}");

                            foreach (KeyValuePair <ExtVehicleType, ICustomSegmentLight> e2 in segLights.CustomLights)
                            {
                                Log._Debug($"Saving timed light step {j}, segment {e.Key}, vehicleType {e2.Key} at node {nodeId}.");

                                ICustomSegmentLight segLight = e2.Value;
                                Configuration.CustomSegmentLight cnfSegLight = new Configuration.CustomSegmentLight();
                                cnfSegLights.customLights.Add(e2.Key, cnfSegLight);

                                cnfSegLight.nodeId      = lightsNodeId;                            // TODO not needed
                                cnfSegLight.segmentId   = segLights.SegmentId;                     // TODO not needed
                                cnfSegLight.currentMode = (int)segLight.CurrentMode;
                                cnfSegLight.leftLight   = segLight.LightLeft;
                                cnfSegLight.mainLight   = segLight.LightMain;
                                cnfSegLight.rightLight  = segLight.LightRight;
                            }
                        }
                    }
                } catch (Exception e) {
                    Log.Error($"Exception occurred while saving timed traffic light @ {nodeId}: {e.ToString()}");
                    success = false;
                }
            }
            return(ret);
        }
Ejemplo n.º 21
0
        public bool CustomCheckTrafficLights(ushort nodeId, ushort segmentId)
        {
#if DEBUG
            bool logTimedLights = DebugSwitch.TimedTrafficLights.Get() &&
                                  DebugSettings.NodeId == nodeId;
#endif
            NetManager netManager        = Singleton <NetManager> .instance;
            uint       currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex;
            uint       simGroup          = (uint)nodeId >> 7;
            uint       stepWaitTime      = currentFrameIndex - simGroup & 255u;

            // NON-STOCK CODE START
            bool customSim = Options.timedLightsEnabled &&
                             TrafficLightSimulationManager.Instance.HasActiveSimulation(nodeId);

            RoadBaseAI.TrafficLightState pedestrianLightState;
            NetSegment[] segmentsBuffer = netManager.m_segments.m_buffer;
            bool         startNode      = segmentsBuffer[segmentId].m_startNode == nodeId;

            ICustomSegmentLights lights = null;
            using (var bm = Benchmark.MaybeCreateBenchmark(null, "GetSegmentLights")) {
                if (customSim)
                {
                    lights = CustomSegmentLightsManager.Instance.GetSegmentLights(
                        segmentId,
                        startNode,
                        false);
                }
            }

            if (lights == null)
            {
                // NON-STOCK CODE END
#if DEBUG
                Log._DebugIf(
                    logTimedLights,
                    () => $"CustomHumanAI.CustomCheckTrafficLights({nodeId}, " +
                    $"{segmentId}): No custom simulation!");
#endif

                RoadBaseAI.GetTrafficLightState(
                    nodeId,
                    ref segmentsBuffer[segmentId],
                    currentFrameIndex - simGroup,
                    out RoadBaseAI.TrafficLightState vehicleLightState,
                    out pedestrianLightState,
                    out bool vehicles,
                    out bool pedestrians);

                if (pedestrianLightState == RoadBaseAI.TrafficLightState.GreenToRed ||
                    pedestrianLightState == RoadBaseAI.TrafficLightState.Red)
                {
                    if (!pedestrians && stepWaitTime >= 196u)
                    {
                        RoadBaseAI.SetTrafficLightState(
                            nodeId,
                            ref segmentsBuffer[segmentId],
                            currentFrameIndex - simGroup,
                            vehicleLightState,
                            pedestrianLightState,
                            vehicles,
                            true);
                    }

                    return(false);
                }

                // NON-STOCK CODE START
            }
            else
            {
                if (lights.InvalidPedestrianLight)
                {
                    pedestrianLightState = RoadBaseAI.TrafficLightState.Green;
                }
                else
                {
                    pedestrianLightState = (RoadBaseAI.TrafficLightState)lights.PedestrianLightState;
                }

#if DEBUG
                Log._DebugIf(
                    logTimedLights,
                    () => $"CustomHumanAI.CustomCheckTrafficLights({nodeId}, {segmentId}): " +
                    $"Custom simulation! pedestrianLightState={pedestrianLightState}, " +
                    $"lights.InvalidPedestrianLight={lights.InvalidPedestrianLight}");
#endif
            }

            // NON-STOCK CODE END
            switch (pedestrianLightState)
            {
            case RoadBaseAI.TrafficLightState.RedToGreen:
                if (stepWaitTime < 60u)
                {
                    return(false);
                }

                break;

            case RoadBaseAI.TrafficLightState.Red:
            case RoadBaseAI.TrafficLightState.GreenToRed:
                return(false);
            }

            return(true);
        }
        public void OnUpdate(NodeGeometry nodeGeometry)
        {
#if DEBUG
            Log._Debug($"TrafficLightSimulation: OnUpdate @ node {NodeId} ({nodeGeometry.NodeId})");
#endif

            if (!IsManualLight() && !IsTimedLight())
            {
                return;
            }

            if (!nodeGeometry.IsValid())
            {
                // node has become invalid. Remove manual/timed traffic light and destroy custom lights
                Constants.ManagerFactory.TrafficLightSimulationManager.RemoveNodeFromSimulation(NodeId, false, false);
                return;
            }

            if (!Flags.mayHaveTrafficLight(NodeId))
            {
                Log._Debug($"Housekeeping: Node {NodeId} has traffic light simulation but must not have a traffic light!");
                Constants.ManagerFactory.TrafficLightSimulationManager.RemoveNodeFromSimulation(NodeId, false, true);
                return;
            }

            ICustomSegmentLightsManager customTrafficLightsManager = Constants.ManagerFactory.CustomSegmentLightsManager;

            foreach (SegmentEndGeometry end in nodeGeometry.SegmentEndGeometries)
            {
                if (end == null)
                {
                    continue;
                }

#if DEBUG
                Log._Debug($"TrafficLightSimulation: OnUpdate @ node {NodeId}: Adding live traffic lights to segment {end.SegmentId}");
#endif

                // add custom lights

                /*if (!customTrafficLightsManager.IsSegmentLight(end.SegmentId, end.StartNode)) {
                 *      customTrafficLightsManager.AddSegmentLights(end.SegmentId, end.StartNode);
                 * }*/

                // housekeep timed light
                ICustomSegmentLights lights = customTrafficLightsManager.GetSegmentLights(end.SegmentId, end.StartNode);
                if (lights == null)
                {
                    Log.Warning($"TrafficLightSimulation.OnUpdate() @ node {NodeId}: Could not retrieve live segment lights for segment {end.SegmentId} @ start {end.StartNode}.");
                    continue;
                }
                lights.Housekeeping(true, true);
            }

            // ensure there is a physical traffic light
            Constants.ServiceFactory.NetService.ProcessNode(NodeId, delegate(ushort nodeId, ref NetNode node) {
                Constants.ManagerFactory.TrafficLightManager.AddTrafficLight(NodeId, ref node);
                return(true);
            });

            TimedLight?.OnGeometryUpdate();
            TimedLight?.Housekeeping();
        }
Ejemplo n.º 23
0
        public override void OnToolGUI(Event e)
        {
            IExtSegmentManager    segMan    = Constants.ManagerFactory.ExtSegmentManager;
            IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager;
            var hoveredSegment = false;

            if (SelectedNodeId != 0)
            {
                CustomSegmentLightsManager    customTrafficLightsManager = CustomSegmentLightsManager.Instance;
                TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance;
                JunctionRestrictionsManager   junctionRestrictionsManager = JunctionRestrictionsManager.Instance;

                if (!tlsMan.HasManualSimulation(SelectedNodeId))
                {
                    return;
                }

                tlsMan.TrafficLightSimulations[SelectedNodeId].Housekeeping();

                // TODO check
                // if (Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode].CountSegments() == 2) {
                //     _guiManualTrafficLightsCrosswalk(
                //         ref Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode]);
                //     return;
                // }
                NetNode[]    nodesBuffer    = Singleton <NetManager> .instance.m_nodes.m_buffer;
                NetSegment[] segmentsBuffer = Singleton <NetManager> .instance.m_segments.m_buffer;

                for (int i = 0; i < 8; ++i)
                {
                    ushort segmentId = nodesBuffer[SelectedNodeId].GetSegment(i);
                    if (segmentId == 0)
                    {
                        continue;
                    }

                    bool startNode =
                        (bool)Constants.ServiceFactory.NetService.IsStartNode(
                            segmentId,
                            SelectedNodeId);
                    Vector3 position = CalculateNodePositionForSegment(
                        nodesBuffer[SelectedNodeId],
                        ref segmentsBuffer[segmentId]);
                    ICustomSegmentLights segmentLights =
                        customTrafficLightsManager.GetSegmentLights(segmentId, startNode, false);

                    if (segmentLights == null)
                    {
                        continue;
                    }

                    bool showPedLight = segmentLights.PedestrianLightState != null &&
                                        junctionRestrictionsManager.IsPedestrianCrossingAllowed(
                        segmentLights.SegmentId,
                        segmentLights.StartNode);
                    bool visible = MainTool.WorldToScreenPoint(position, out Vector3 screenPos);

                    if (!visible)
                    {
                        continue;
                    }

                    Vector3 diff = position - Camera.main.transform.position;
                    float   zoom = 1.0f / diff.magnitude * 100f;

                    // original / 2.5
                    float lightWidth  = 41f * zoom;
                    float lightHeight = 97f * zoom;

                    float pedestrianWidth  = 36f * zoom;
                    float pedestrianHeight = 61f * zoom;

                    // SWITCH MODE BUTTON
                    float modeWidth  = 41f * zoom;
                    float modeHeight = 38f * zoom;

                    Color guiColor = GUI.color;

                    if (showPedLight)
                    {
                        // pedestrian light

                        // SWITCH MANUAL PEDESTRIAN LIGHT BUTTON
                        hoveredSegment = RenderManualPedestrianLightSwitch(
                            zoom,
                            segmentId,
                            screenPos,
                            lightWidth,
                            segmentLights,
                            hoveredSegment);

                        // SWITCH PEDESTRIAN LIGHT
                        guiColor.a = TrafficManagerTool.GetHandleAlpha(
                            hoveredButton[0] == segmentId && hoveredButton[1] == 2 &&
                            segmentLights.ManualPedestrianMode);
                        GUI.color = guiColor;

                        var myRect3 = new Rect(
                            screenPos.x - pedestrianWidth / 2 - lightWidth + 5f * zoom,
                            screenPos.y - pedestrianHeight / 2 + 22f * zoom,
                            pedestrianWidth,
                            pedestrianHeight);

                        switch (segmentLights.PedestrianLightState)
                        {
                        case RoadBaseAI.TrafficLightState.Green: {
                            GUI.DrawTexture(
                                myRect3,
                                TrafficLightTextures.PedestrianGreenLight);
                            break;
                        }

                        // also: case RoadBaseAI.TrafficLightState.Red:
                        default: {
                            GUI.DrawTexture(
                                myRect3,
                                TrafficLightTextures.PedestrianRedLight);
                            break;
                        }
                        }

                        hoveredSegment = IsPedestrianLightHovered(
                            myRect3,
                            segmentId,
                            hoveredSegment,
                            segmentLights);
                    }

                    int lightOffset = -1;

                    foreach (ExtVehicleType vehicleType in segmentLights.VehicleTypes)
                    {
                        ++lightOffset;
                        ICustomSegmentLight segmentLight = segmentLights.GetCustomLight(vehicleType);

                        Vector3 offsetScreenPos = screenPos;
                        offsetScreenPos.y -= (lightHeight + 10f * zoom) * lightOffset;

                        SetAlpha(segmentId, -1);

                        var myRect1 = new Rect(
                            offsetScreenPos.x - modeWidth / 2,
                            offsetScreenPos.y - modeHeight / 2 + modeHeight - 7f * zoom,
                            modeWidth,
                            modeHeight);

                        GUI.DrawTexture(myRect1, TrafficLightTextures.LightMode);

                        hoveredSegment = GetHoveredSegment(
                            myRect1,
                            segmentId,
                            hoveredSegment,
                            segmentLight);

                        // COUNTER
                        hoveredSegment = RenderCounter(
                            segmentId,
                            offsetScreenPos,
                            modeWidth,
                            modeHeight,
                            zoom,
                            segmentLights,
                            hoveredSegment);

                        if (vehicleType != ExtVehicleType.None)
                        {
                            // Info sign
                            float infoWidth  = 56.125f * zoom;
                            float infoHeight = 51.375f * zoom;

                            int numInfos = 0;

                            for (int k = 0; k < TrafficManagerTool.InfoSignsToDisplay.Length; ++k)
                            {
                                if ((TrafficManagerTool.InfoSignsToDisplay[k] & vehicleType) ==
                                    ExtVehicleType.None)
                                {
                                    continue;
                                }

                                var infoRect = new Rect(
                                    offsetScreenPos.x + modeWidth / 2f +
                                    (7f * zoom * (float)(numInfos + 1)) + (infoWidth * (float)numInfos),
                                    offsetScreenPos.y - (infoHeight / 2f),
                                    infoWidth,
                                    infoHeight);
                                guiColor.a = TrafficManagerTool.GetHandleAlpha(false);

                                GUI.DrawTexture(
                                    infoRect,
                                    RoadUITextures.VehicleInfoSignTextures[TrafficManagerTool.InfoSignsToDisplay[k]]);

                                ++numInfos;
                            }
                        }

                        ExtSegment    seg    = segMan.ExtSegments[segmentId];
                        ExtSegmentEnd segEnd =
                            segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, startNode)];
                        if (seg.oneWay && segEnd.outgoing)
                        {
                            continue;
                        }

                        segEndMan.CalculateOutgoingLeftStraightRightSegments(
                            ref segEnd,
                            ref nodesBuffer[segmentId],
                            out bool hasLeftSegment,
                            out bool hasForwardSegment,
                            out bool hasRightSegment);

                        switch (segmentLight.CurrentMode)
                        {
                        case LightMode.Simple: {
                            hoveredSegment = SimpleManualSegmentLightMode(
                                segmentId,
                                offsetScreenPos,
                                lightWidth,
                                pedestrianWidth,
                                zoom,
                                lightHeight,
                                segmentLight,
                                hoveredSegment);
                            break;
                        }

                        case LightMode.SingleLeft: {
                            hoveredSegment = LeftForwardRManualSegmentLightMode(
                                hasLeftSegment,
                                segmentId,
                                offsetScreenPos,
                                lightWidth,
                                pedestrianWidth,
                                zoom,
                                lightHeight,
                                segmentLight,
                                hoveredSegment,
                                hasForwardSegment,
                                hasRightSegment);
                            break;
                        }

                        case LightMode.SingleRight: {
                            hoveredSegment = RightForwardLSegmentLightMode(
                                segmentId,
                                offsetScreenPos,
                                lightWidth,
                                pedestrianWidth,
                                zoom,
                                lightHeight,
                                hasForwardSegment,
                                hasLeftSegment,
                                segmentLight,
                                hasRightSegment,
                                hoveredSegment);
                            break;
                        }

                        default: {
                            // left arrow light
                            if (hasLeftSegment)
                            {
                                hoveredSegment = LeftArrowLightMode(
                                    segmentId,
                                    lightWidth,
                                    hasRightSegment,
                                    hasForwardSegment,
                                    offsetScreenPos,
                                    pedestrianWidth,
                                    zoom,
                                    lightHeight,
                                    segmentLight,
                                    hoveredSegment);
                            }

                            // forward arrow light
                            if (hasForwardSegment)
                            {
                                hoveredSegment = ForwardArrowLightMode(
                                    segmentId,
                                    lightWidth,
                                    hasRightSegment,
                                    offsetScreenPos,
                                    pedestrianWidth,
                                    zoom,
                                    lightHeight,
                                    segmentLight,
                                    hoveredSegment);
                            }

                            // right arrow light
                            if (hasRightSegment)
                            {
                                hoveredSegment = RightArrowLightMode(
                                    segmentId,
                                    offsetScreenPos,
                                    lightWidth,
                                    pedestrianWidth,
                                    zoom,
                                    lightHeight,
                                    segmentLight,
                                    hoveredSegment);
                            }

                            break;
                        }
                        } // end switch
                    }     // end foreach all vehicle type
                }         // end for all 8 segments
            }             // end if a node is selected

            if (hoveredSegment)
            {
                return;
            }

            hoveredButton[0] = 0;
            hoveredButton[1] = 0;
        }
Ejemplo n.º 24
0
        public void CalculateAutoPedestrianLightState(ref NetNode node, bool propagate = true)
        {
#if DEBUGTTL
            bool debug = DebugSwitch.TimedTrafficLights.Get() && DebugSettings.NodeId == NodeId;
#endif

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

            IExtSegmentManager    segMan    = Constants.ManagerFactory.ExtSegmentManager;
            IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager;
            ExtSegment            seg       = segMan.ExtSegments[SegmentId];
            ExtSegmentEnd         segEnd    = segEndMan.ExtSegmentEnds[segEndMan.GetIndex(SegmentId, StartNode)];

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

            if (propagate)
            {
                for (int i = 0; i < 8; ++i)
                {
                    ushort otherSegmentId = node.GetSegment(i);
                    if (otherSegmentId == 0 || otherSegmentId == SegmentId)
                    {
                        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(ref node, 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

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

            RoadBaseAI.TrafficLightState autoPedestrianLightState = RoadBaseAI.TrafficLightState.Green;
            bool lhd = Constants.ServiceFactory.SimulationService.LeftHandDrive;
            if (!(segEnd.incoming && seg.oneWay))
            {
                for (int i = 0; i < 8; ++i)
                {
                    ushort otherSegmentId = node.GetSegment(i);
                    if (otherSegmentId == 0 || otherSegmentId == SegmentId)
                    {
                        continue;
                    }

                    //ExtSegment otherSeg = segMan.ExtSegments[otherSegmentId];

                    if (!segEndMan.ExtSegmentEnds[segEndMan.GetIndex(otherSegmentId, (bool)Constants.ServiceFactory.NetService.IsStartNode(otherSegmentId, NodeId))].incoming)
                    {
                        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;
                    }

                    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;
                    }

                    ArrowDirection dir = segEndMan.GetDirection(ref segEnd, otherSegmentId);
                    if (dir == ArrowDirection.Forward)
                    {
                        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;
                        }
                    }
                    else if ((dir == ArrowDirection.Left && lhd) || (dir == ArrowDirection.Right && !lhd))
                    {
                        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
        }