Exemple #1
0
        private void ToggleMode(ref ExtSegmentEnd segEnd, ref NetNode node)
        {
            IExtSegmentManager    extSegMan    = Constants.ManagerFactory.ExtSegmentManager;
            IExtSegmentEndManager extSegEndMan = Constants.ManagerFactory.ExtSegmentEndManager;
            bool startNode = lights.StartNode;

            bool hasLeftSegment;
            bool hasForwardSegment;
            bool hasRightSegment;

            extSegEndMan.CalculateOutgoingLeftStraightRightSegments(ref segEnd, ref node, out hasLeftSegment, out hasForwardSegment, out hasRightSegment);

#if DEBUG
            Log._Debug($"ChangeMode. segment {SegmentId} @ node {NodeId}, hasLeftSegment={hasLeftSegment}, hasForwardSegment={hasForwardSegment}, hasRightSegment={hasRightSegment}");
#endif

            LightMode newMode = LightMode.Simple;
            if (CurrentMode == LightMode.Simple)
            {
                if (!hasLeftSegment)
                {
                    newMode = LightMode.SingleRight;
                }
                else
                {
                    newMode = LightMode.SingleLeft;
                }
            }
            else if (CurrentMode == LightMode.SingleLeft)
            {
                if (!hasForwardSegment || !hasRightSegment)
                {
                    newMode = LightMode.Simple;
                }
                else
                {
                    newMode = LightMode.SingleRight;
                }
            }
            else if (CurrentMode == LightMode.SingleRight)
            {
                if (!hasLeftSegment)
                {
                    newMode = LightMode.Simple;
                }
                else
                {
                    newMode = LightMode.All;
                }
            }
            else
            {
                newMode = LightMode.Simple;
            }

            CurrentMode = newMode;
        }
Exemple #2
0
        /// <summary>
        /// Are all segments at nodeId highways?
        /// </summary>
        /// <param name="nodeId"></param>
        /// <returns></returns>
        public static bool JunctionHasOnlyHighwayRoads(ushort nodeId)
        {
            IExtSegmentManager segMan = Constants.ManagerFactory.ExtSegmentManager;
            bool ret = true;

            Constants.ServiceFactory.NetService.IterateNodeSegments(
                nodeId,
                (ushort segmentId, ref NetSegment segment) => {
                ret &= segMan.CalculateIsHighway(segmentId);
                return(ret);
            });
            return(ret);
        }
Exemple #3
0
        protected void UpdateSegmentEnd(ref ExtSegment seg, ref ExtSegmentEnd end)
        {
#if DEBUG
            bool logTurnOnRed = DebugSwitch.TurnOnRed.Get();
#else
            const bool logTurnOnRed = false;
#endif
            if (logTurnOnRed)
            {
                Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}) called.");
            }

            IExtSegmentManager    segmentManager    = Constants.ManagerFactory.ExtSegmentManager;
            IExtSegmentEndManager segmentEndManager = Constants.ManagerFactory.ExtSegmentEndManager;

            ushort segmentId          = seg.segmentId;
            ushort nodeId             = end.nodeId;
            bool   hasOutgoingSegment = false;

            Services.NetService.IterateNodeSegments(
                end.nodeId,
                (ushort otherSegId, ref NetSegment otherSeg) => {
                int index0 = segmentEndManager.GetIndex(otherSegId, otherSeg.m_startNode == nodeId);

                if (otherSegId != segmentId &&
                    segmentEndManager.ExtSegmentEnds[index0].outgoing)
                {
                    hasOutgoingSegment = true;
                    return(false);
                }

                return(true);
            });

            // check if traffic can flow to the node and that there is at least one left segment
            if (!end.incoming || !hasOutgoingSegment)
            {
                if (logTurnOnRed)
                {
                    Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}): " +
                               "outgoing one-way or insufficient number of outgoing segments.");
                }

                return;
            }

            bool lht = Services.SimulationService.TrafficDrivesOnLeft;

            // check node
            // note that we must not check for the `TrafficLights` flag here because the flag might not be loaded yet
            ref NetNode node      = ref nodeId.ToNode();
Exemple #4
0
        protected void UpdateSegmentEnd(ref ExtSegment seg, ref ExtSegmentEnd end)
        {
#if DEBUG
            bool logTurnOnRed = DebugSwitch.TurnOnRed.Get();
#else
            const bool logTurnOnRed = false;
#endif
            if (logTurnOnRed)
            {
                Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}) called.");
            }

            IExtSegmentManager    segmentManager    = Constants.ManagerFactory.ExtSegmentManager;
            IExtSegmentEndManager segmentEndManager = Constants.ManagerFactory.ExtSegmentEndManager;

            ushort segmentId          = seg.segmentId;
            ushort nodeId             = end.nodeId;
            bool   hasOutgoingSegment = false;

            ref NetNode endNode = ref end.nodeId.ToNode();
        public void ShowGUI(bool viewOnly)
        {
            try {
                IExtSegmentManager            segMan    = Constants.ManagerFactory.ExtSegmentManager;
                IExtSegmentEndManager         segEndMan = Constants.ManagerFactory.ExtSegmentEndManager;
                TrafficLightSimulationManager tlsMan    = TrafficLightSimulationManager.Instance;
                TrafficPriorityManager        prioMan   = TrafficPriorityManager.Instance;
                TrafficLightManager           tlm       = TrafficLightManager.Instance;

                Vector3 camPos = Constants.ServiceFactory.SimulationService.CameraPosition;

                bool clicked = !viewOnly?MainTool.CheckClicked() : false;

                ushort removedNodeId    = 0;
                bool   showRemoveButton = false;
                foreach (ushort nodeId in currentPriorityNodeIds)
                {
                    if (!Constants.ServiceFactory.NetService.IsNodeValid(nodeId))
                    {
                        continue;
                    }

                    if (!MainTool.IsNodeWithinViewDistance(nodeId))
                    {
                        continue;
                    }

                    Vector3 nodePos = default(Vector3);
                    Constants.ServiceFactory.NetService.ProcessNode(nodeId, delegate(ushort nId, ref NetNode node) {
                        nodePos = node.m_position;
                        return(true);
                    });

                    for (int i = 0; i < 8; ++i)
                    {
                        ushort segmentId = 0;
                        Constants.ServiceFactory.NetService.ProcessNode(nodeId, delegate(ushort nId, ref NetNode node) {
                            segmentId = node.GetSegment(i);
                            return(true);
                        });

                        if (segmentId == 0)
                        {
                            continue;
                        }

                        bool          startNode = (bool)Constants.ServiceFactory.NetService.IsStartNode(segmentId, nodeId);
                        ExtSegment    seg       = segMan.ExtSegments[segmentId];
                        ExtSegmentEnd segEnd    = segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, startNode)];

                        if (seg.oneWay && segEnd.outgoing)
                        {
                            continue;
                        }

                        // calculate sign position
                        Vector3 signPos = nodePos;

                        Constants.ServiceFactory.NetService.ProcessSegment(segmentId, delegate(ushort sId, ref NetSegment segment) {
                            signPos += 10f * (startNode ? segment.m_startDirection : segment.m_endDirection);
                            return(true);
                        });

                        Vector3 signScreenPos;
                        if (!MainTool.WorldToScreenPoint(signPos, out signScreenPos))
                        {
                            continue;
                        }

                        // draw sign and handle input
                        PriorityType sign = prioMan.GetPrioritySign(segmentId, startNode);
                        if (viewOnly && sign == PriorityType.None)
                        {
                            continue;
                        }
                        if (!viewOnly && sign != PriorityType.None)
                        {
                            showRemoveButton = true;
                        }

                        if (MainTool.DrawGenericSquareOverlayTexture(TextureResources.PrioritySignTextures[sign], camPos, signPos, 90f, !viewOnly) && clicked)
                        {
                            PriorityType?newSign = null;
                            switch (sign)
                            {
                            case PriorityType.Main:
                                newSign = PriorityType.Yield;
                                break;

                            case PriorityType.Yield:
                                newSign = PriorityType.Stop;
                                break;

                            case PriorityType.Stop:
                                newSign = PriorityType.Main;
                                break;

                            case PriorityType.None:
                            default:
                                newSign = prioMan.CountPrioritySignsAtNode(nodeId, PriorityType.Main) >= 2 ? PriorityType.Yield : PriorityType.Main;
                                break;
                            }

                            if (newSign != null)
                            {
                                SetPrioritySign(segmentId, startNode, (PriorityType)newSign);
                            }
                        }                 // draw sign
                    }                     // foreach segment end

                    if (viewOnly)
                    {
                        continue;
                    }

                    // draw remove button and handle click
                    if (showRemoveButton && MainTool.DrawHoverableSquareOverlayTexture(TextureResources.SignRemoveTexture2D, camPos, nodePos, 90f) && clicked)
                    {
                        prioMan.RemovePrioritySignsFromNode(nodeId);
                        Log._Debug($"PrioritySignsTool.ShowGUI: Removed priority signs from node {nodeId}");
                        removedNodeId = nodeId;
                    }
                }                 // foreach node

                if (removedNodeId != 0)
                {
                    currentPriorityNodeIds.Remove(removedNodeId);
                    SelectedNodeId = 0;
                }
            } catch (Exception e) {
                Log.Error(e.ToString());
            }
        }
        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;
        }
Exemple #7
0
        private static void TraverseRec(ref ExtSegment prevSeg,
                                        ref ExtSegmentEnd prevSegEnd,
                                        ref NetNode node,
                                        bool viaInitialStartNode,
                                        TraverseDirection direction,
                                        TraverseSide side,
                                        SegmentStopCriterion stopCrit,
                                        SegmentVisitor visitorFun,
                                        HashSet <ushort> visitedSegmentIds)
        {
            // Log._Debug($"SegmentTraverser: Traversing segment {prevSegEnd.segmentId}");
            // collect next segment ids to traverse
            if (direction == TraverseDirection.None)
            {
                throw new ArgumentException($"Invalid direction {direction} given.");
            }

            if (side == TraverseSide.None)
            {
                throw new ArgumentException($"Invalid side {side} given.");
            }

            IExtSegmentManager    extSegMan    = Constants.ManagerFactory.ExtSegmentManager;
            IExtSegmentEndManager extSegEndMan = Constants.ManagerFactory.ExtSegmentEndManager;

            HashSet <ushort> nextSegmentIds = new HashSet <ushort>();

            for (int i = 0; i < 8; ++i)
            {
                ushort nextSegmentId = node.GetSegment(i);
                if (nextSegmentId == 0 || nextSegmentId == prevSegEnd.segmentId)
                {
                    continue;
                }

                bool nextIsStartNode =
                    (bool)Constants.ServiceFactory.NetService.IsStartNode(
                        nextSegmentId,
                        prevSegEnd.nodeId);
                ExtSegmentEnd nextSegEnd =
                    extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(nextSegmentId, nextIsStartNode)];

                if (direction == TraverseDirection.AnyDirection ||
                    (direction == TraverseDirection.Incoming && nextSegEnd.incoming) ||
                    (direction == TraverseDirection.Outgoing && nextSegEnd.outgoing))
                {
                    if (side == TraverseSide.AnySide)
                    {
                        nextSegmentIds.Add(nextSegmentId);
                    }
                    else
                    {
                        ArrowDirection dir = extSegEndMan.GetDirection(
                            ref prevSegEnd,
                            nextSegmentId);
                        if (((side & TraverseSide.Left) != TraverseSide.None &&
                             dir == ArrowDirection.Left) ||
                            ((side & TraverseSide.Straight) != TraverseSide.None &&
                             dir == ArrowDirection.Forward) ||
                            ((side & TraverseSide.Right) != TraverseSide.None &&
                             dir == ArrowDirection.Right))
                        {
                            nextSegmentIds.Add(nextSegmentId);
                        }
                    }
                }
            }

            nextSegmentIds.Remove(0);
            // Log._Debug($"SegmentTraverser: Fetched next segments to traverse:
            //     {nextSegmentIds.CollectionToString()}");
            if (nextSegmentIds.Count >= 2 && (stopCrit & SegmentStopCriterion.Junction) !=
                SegmentStopCriterion.None)
            {
                // Log._Debug($"SegmentTraverser: Stop criterion reached @ {prevSegEnd.segmentId}:
                //    {nextSegmentIds.Count} connected segments");
                return;
            }

            // explore next segments
            foreach (ushort nextSegmentId in nextSegmentIds)
            {
                if (visitedSegmentIds.Contains(nextSegmentId))
                {
                    continue;
                }

                visitedSegmentIds.Add(nextSegmentId);
                // Log._Debug($"SegmentTraverser: Traversing segment {nextSegmentId}");
                ushort nextStartNodeId =
                    Constants.ServiceFactory.NetService.GetSegmentNodeId(nextSegmentId, true);

                if (!visitorFun(
                        new SegmentVisitData(
                            ref prevSeg,
                            ref extSegMan.ExtSegments[nextSegmentId],
                            viaInitialStartNode,
                            prevSegEnd.nodeId == nextStartNodeId,
                            false)))
                {
                    continue;
                }

                bool nextNodeIsStartNode = nextStartNodeId != prevSegEnd.nodeId;

                ExtSegmentEnd nextSegEnd
                    = extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(nextSegmentId, nextNodeIsStartNode)];

                Constants.ServiceFactory.NetService.ProcessNode(
                    nextSegEnd.nodeId,
                    (ushort nId, ref NetNode nextNode) => {
                    TraverseRec(
                        ref extSegMan.ExtSegments[nextSegmentId],
                        ref nextSegEnd,
                        ref nextNode,
                        viaInitialStartNode,
                        direction,
                        side,
                        stopCrit,
                        visitorFun,
                        visitedSegmentIds);
                    return(true);
                });
            } // end foreach
        }
Exemple #8
0
        protected void UpdateSegmentEnd(ref ExtSegment seg, ref ExtSegmentEnd end)
        {
#if DEBUG
            bool logTurnOnRed = DebugSwitch.TurnOnRed.Get();
#else
            const bool logTurnOnRed = false;
#endif
            if (logTurnOnRed)
            {
                Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}) called.");
            }

            IExtSegmentManager    segmentManager    = Constants.ManagerFactory.ExtSegmentManager;
            IExtSegmentEndManager segmentEndManager = Constants.ManagerFactory.ExtSegmentEndManager;

            ushort segmentId          = seg.segmentId;
            ushort nodeId             = end.nodeId;
            bool   hasOutgoingSegment = false;

            Services.NetService.IterateNodeSegments(
                end.nodeId,
                (ushort otherSegId, ref NetSegment otherSeg) => {
                int index0 = segmentEndManager.GetIndex(otherSegId, otherSeg.m_startNode == nodeId);

                if (otherSegId != segmentId &&
                    segmentEndManager.ExtSegmentEnds[index0].outgoing)
                {
                    hasOutgoingSegment = true;
                    return(false);
                }

                return(true);
            });

            // check if traffic can flow to the node and that there is at least one left segment
            if (!end.incoming || !hasOutgoingSegment)
            {
                if (logTurnOnRed)
                {
                    Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}): " +
                               "outgoing one-way or insufficient number of outgoing segments.");
                }

                return;
            }

            bool lhd = Services.SimulationService.LeftHandDrive;

            // 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,
                (ushort _, 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 (logTurnOnRed)
                {
                    Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}): node invalid");
                }

                return;
            }

            // get left/right segments
            ushort leftSegmentId  = 0;
            ushort rightSegmentId = 0;
            Services.NetService.ProcessSegment(
                end.segmentId,
                (ushort _, ref NetSegment segment) => {
                segment.GetLeftAndRightSegments(
                    nodeId,
                    out leftSegmentId,
                    out rightSegmentId);
                return(true);
            });

            if (logTurnOnRed)
            {
                Log._Debug(
                    $"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}): " +
                    $"got left/right segments: {leftSegmentId}/{rightSegmentId}");
            }

            // validate left/right segments according to geometric properties
            if (leftSegmentId != 0 &&
                segmentEndManager.GetDirection(ref end, leftSegmentId) != ArrowDirection.Left)
            {
                if (logTurnOnRed)
                {
                    Log._Debug(
                        $"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}): " +
                        "left segment is not geometrically left");
                }

                leftSegmentId = 0;
            }

            if (rightSegmentId != 0 &&
                segmentEndManager.GetDirection(ref end, rightSegmentId) != ArrowDirection.Right)
            {
                if (logTurnOnRed)
                {
                    Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}): " +
                               "right segment is not geometrically right");
                }

                rightSegmentId = 0;
            }

            // check for incoming one-ways
            if (leftSegmentId != 0 &&
                !segmentEndManager.ExtSegmentEnds[segmentEndManager.GetIndex(leftSegmentId, nodeId)].outgoing)
            {
                if (logTurnOnRed)
                {
                    Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}): " +
                               "left segment is incoming one-way");
                }

                leftSegmentId = 0;
            }

            if (rightSegmentId != 0 &&
                !segmentEndManager.ExtSegmentEnds[segmentEndManager.GetIndex(rightSegmentId, nodeId)].outgoing)
            {
                if (logTurnOnRed)
                {
                    Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}): " +
                               "right segment is incoming one-way");
                }

                rightSegmentId = 0;
            }

            if (seg.oneWay)
            {
                if ((lhd && rightSegmentId != 0) || (!lhd && leftSegmentId != 0))
                {
                    // special case: one-way to one-way in non-preferred direction
                    if (logTurnOnRed)
                    {
                        Log._Debug(
                            $"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}): " +
                            "source is incoming one-way. checking for one-way in non-preferred direction");
                    }

                    ushort targetSegmentId = lhd ? rightSegmentId : leftSegmentId;

                    if (!segmentManager.ExtSegments[targetSegmentId].oneWay)
                    {
                        // disallow turn in non-preferred direction
                        if (logTurnOnRed)
                        {
                            Log._Debug(
                                $"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}): " +
                                $"turn in non-preferred direction {(lhd ? "right" : "left")} disallowed");
                        }

                        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(end.segmentId, end.startNode);
            TurnOnRedSegments[index].leftSegmentId  = leftSegmentId;
            TurnOnRedSegments[index].rightSegmentId = rightSegmentId;

            if (logTurnOnRed)
            {
                Log._Debug(
                    $"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}): " +
                    $"Finished calculation. leftSegmentId={leftSegmentId}, rightSegmentId={rightSegmentId}");
            }
        }
Exemple #9
0
 /// <summary>
 /// Are all segments at nodeId highways?
 /// </summary>
 /// <param name="nodeId"></param>
 /// <returns></returns>
 public static bool JunctionHasOnlyHighwayRoads(ushort nodeId)
 {
     IExtSegmentManager segMan = Constants.ManagerFactory.ExtSegmentManager;
     ref NetNode        node   = ref nodeId.ToNode();
Exemple #10
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
        }