Esempio n. 1
0
        public override void RenderOverlay(RenderManager.CameraInfo cameraInfo)
        {
            if (MainTool.GetToolController().IsInsideUI || !Cursor.visible)
            {
                return;
            }

            // For current camera store its position and cast a ray via mouse position
            Vector3 camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position;
            // Ray mouseRay = currentCamera.ScreenPointToRay(Input.mousePosition);

            // Check if camera pos/angle has changed then re-filter the visible nodes
            // Assumption: The states checked in this loop don't change while the tool is active
            var currentCameraState = new CameraTransformValue(InGameUtil.Instance.CachedMainCamera);

            if (!LastCachedCamera.Equals(currentCameraState))
            {
                CachedVisibleNodeIds.Clear();
                LastCachedCamera = currentCameraState;

                FilterVisibleNodes(camPos);
            }

            // Render the current hovered node as blue
            if ((HoveredNodeId != 0) && Flags.MayHaveTrafficLight(HoveredNodeId))
            {
                MainTool.DrawNodeCircle(
                    cameraInfo,
                    HoveredNodeId,
                    Input.GetMouseButton(0),
                    false);
            }
        }
        public LaneConnectorTool(TrafficManagerTool mainTool)
            : base(mainTool)
        {
            // Log._Debug($"LaneConnectorTool: Constructor called");
            currentNodeMarkers = new Dictionary <ushort, List <NodeLaneMarker> >();

            CachedVisibleNodeIds = new GenericArrayCache <uint>(NetManager.MAX_NODE_COUNT);
            LastCachedCamera     = new CameraTransformValue();
        }
 public override void OnActivate()
 {
     LastCachedCamera = new CameraTransformValue();
 }
 public SpeedLimitsTool(TrafficManagerTool mainTool)
     : base(mainTool)
 {
     CachedVisibleSegmentIds = new GenericArrayCache <ushort>(NetManager.MAX_SEGMENT_COUNT);
     LastCachedCamera        = new CameraTransformValue();
 }
        private void ShowSigns(bool viewOnly)
        {
            NetManager        netManager        = Singleton <NetManager> .instance;
            SpeedLimitManager speedLimitManager = SpeedLimitManager.Instance;

            var       currentCamera          = new CameraTransformValue(Camera.main);
            Transform currentCameraTransform = Camera.main.transform;
            Vector3   camPos = currentCameraTransform.position;

            if (!LastCachedCamera.Equals(currentCamera))
            {
                // cache visible segments
                LastCachedCamera = currentCamera;
                CachedVisibleSegmentIds.Clear();

                const float MAX_DIST = TrafficManagerTool.MAX_OVERLAY_DISTANCE *
                                       TrafficManagerTool.MAX_OVERLAY_DISTANCE;

                for (uint segmentId = 1; segmentId < NetManager.MAX_SEGMENT_COUNT; ++segmentId)
                {
                    if (!Constants.ServiceFactory.NetService.IsSegmentValid((ushort)segmentId))
                    {
                        continue;
                    }

                    // if ((netManager.m_segments.m_buffer[segmentId].m_flags &
                    // NetSegment.Flags.Untouchable) != NetSegment.Flags.None) continue;
                    Vector3 distToCamera = netManager.m_segments.m_buffer[segmentId].m_bounds.center - camPos;
                    if (distToCamera.sqrMagnitude > MAX_DIST)
                    {
                        continue; // do not draw if too distant
                    }

                    bool visible = MainTool.WorldToScreenPoint(
                        netManager.m_segments.m_buffer[segmentId].m_bounds.center,
                        out Vector3 _);

                    if (!visible)
                    {
                        continue;
                    }

                    if (!speedLimitManager.MayHaveCustomSpeedLimits(
                            (ushort)segmentId,
                            ref netManager.m_segments.m_buffer[segmentId]))
                    {
                        continue;
                    }

                    CachedVisibleSegmentIds.Add((ushort)segmentId);
                } // end for all segments
            }

            for (int segmentIdIndex = CachedVisibleSegmentIds.Size - 1;
                 segmentIdIndex >= 0;
                 segmentIdIndex--)
            {
                ushort segmentId = CachedVisibleSegmentIds.Values[segmentIdIndex];
                // draw speed limits
                if ((MainTool.GetToolMode() == ToolMode.VehicleRestrictions) &&
                    (segmentId == SelectedSegmentId))
                {
                    continue;
                }

                // no speed limit overlay on selected segment when in vehicle restrictions mode
                DrawSpeedLimitHandles(
                    segmentId,
                    ref netManager.m_segments.m_buffer[segmentId],
                    viewOnly,
                    ref camPos);
            }
        }
Esempio n. 6
0
        private void ShowSigns(bool viewOnly)
        {
            NetManager netManager = Singleton <NetManager> .instance;

            var       currentCamera          = new CameraTransformValue(InGameUtil.Instance.CachedMainCamera);
            Transform currentCameraTransform = InGameUtil.Instance.CachedCameraTransform;
            Vector3   camPos = currentCameraTransform.position;

            if (!LastCachedCamera.Equals(currentCamera))
            {
                // cache visible segments
                LastCachedCamera = currentCamera;
                CachedVisibleSegmentIds.Clear();

                for (uint segmentId = 1; segmentId < NetManager.MAX_SEGMENT_COUNT; ++segmentId)
                {
                    if (!Constants.ServiceFactory.NetService.IsSegmentValid((ushort)segmentId))
                    {
                        continue;
                    }

                    // if ((netManager.m_segments.m_buffer[segmentId].m_flags
                    //     & NetSegment.Flags.Untouchable) != NetSegment.Flags.None)
                    // continue;
                    Vector3 distToCamera = netManager.m_segments.m_buffer[segmentId].m_bounds.center - camPos;
                    if (distToCamera.sqrMagnitude > TrafficManagerTool.MAX_OVERLAY_DISTANCE_SQR)
                    {
                        continue; // do not draw if too distant
                    }

                    bool visible = GeometryUtil.WorldToScreenPoint(
                        netManager.m_segments.m_buffer[segmentId].m_bounds.center,
                        out Vector3 _);

                    if (!visible)
                    {
                        continue;
                    }

                    if (!parkingManager.MayHaveParkingRestriction((ushort)segmentId))
                    {
                        continue;
                    }

                    CachedVisibleSegmentIds.Add((ushort)segmentId);
                } // end for all segments
            }

            bool hovered = false;
            bool clicked = !viewOnly && MainTool.CheckClicked();

            for (int segmentIdIndex = CachedVisibleSegmentIds.Size - 1;
                 segmentIdIndex >= 0;
                 segmentIdIndex--)
            {
                ushort segmentId = CachedVisibleSegmentIds.Values[segmentIdIndex];

                // draw parking restrictions
                if ((MainTool.GetToolMode() == ToolMode.SpeedLimits) ||
                    ((MainTool.GetToolMode() == ToolMode.VehicleRestrictions) &&
                     (segmentId == SelectedSegmentId)))
                {
                    continue;
                }

                // no parking restrictions overlay on selected segment when in vehicle restrictions mode
                var dir = DrawParkingRestrictionHandles(
                    segmentId,
                    clicked,
                    ref netManager.m_segments.m_buffer[segmentId],
                    viewOnly,
                    ref camPos);
                if (dir != NetInfo.Direction.None)
                {
                    renderInfo_.SegmentId      = segmentId;
                    renderInfo_.FinalDirection = dir;
                    hovered = true;
                }
            }
            if (!hovered)
            {
                renderInfo_.SegmentId      = 0;
                renderInfo_.FinalDirection = NetInfo.Direction.None;
            }
        }
        private void ShowOverlay(bool viewOnly, RenderManager.CameraInfo cameraInfo)
        {
            if (viewOnly && !(Options.connectedLanesOverlay ||
                              PrioritySignsTool.MassEditOVerlay.IsActive))
            {
                return;
            }

            NetManager netManager = Singleton <NetManager> .instance;

            Vector3 camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position;

            // Bounds bounds = new Bounds(Vector3.zero, Vector3.one);
            Camera currentCamera = Camera.main;
            Ray    mouseRay      = currentCamera.ScreenPointToRay(Input.mousePosition);

            // Check if camera pos/angle has changed then re-filter the visible nodes
            // Assumption: The states checked in this loop don't change while the tool is active
            var currentCameraState = new CameraTransformValue(currentCamera);

            if (!LastCachedCamera.Equals(currentCameraState))
            {
                CachedVisibleNodeIds.Clear();
                LastCachedCamera = currentCameraState;

                for (uint nodeId = 1; nodeId < NetManager.MAX_NODE_COUNT; ++nodeId)
                {
                    if (!Constants.ServiceFactory.NetService.IsNodeValid((ushort)nodeId))
                    {
                        continue;
                    }

                    //---------------------------
                    // Check the connection class
                    //---------------------------
                    // TODO refactor connection class check
                    ItemClass connectionClass =
                        NetManager.instance.m_nodes.m_buffer[nodeId].Info.GetConnectionClass();

                    if ((connectionClass == null) ||
                        !((connectionClass.m_service == ItemClass.Service.Road) ||
                          ((connectionClass.m_service == ItemClass.Service.PublicTransport) &&
                           ((connectionClass.m_subService == ItemClass.SubService.PublicTransportTrain) ||
                            (connectionClass.m_subService == ItemClass.SubService.PublicTransportMetro) ||
                            (connectionClass.m_subService == ItemClass.SubService.PublicTransportMonorail)))))
                    {
                        continue;
                    }

                    //--------------------------
                    // Check the camera distance
                    //--------------------------
                    Vector3 diff = NetManager.instance.m_nodes.m_buffer[nodeId].m_position - camPos;

                    if (diff.sqrMagnitude > TrafficManagerTool.MAX_OVERLAY_DISTANCE_SQR)
                    {
                        continue; // do not draw if too distant
                    }

                    // Add
                    CachedVisibleNodeIds.Add(nodeId);
                }
            }

            for (int cacheIndex = CachedVisibleNodeIds.Size - 1; cacheIndex >= 0; cacheIndex--)
            {
                var nodeId = CachedVisibleNodeIds.Values[cacheIndex];

                List <NodeLaneMarker> nodeMarkers;
                bool hasMarkers = currentNodeMarkers.TryGetValue((ushort)nodeId, out nodeMarkers);

                if (!viewOnly && (GetMarkerSelectionMode() == MarkerSelectionMode.None))
                {
                    MainTool.DrawNodeCircle(
                        cameraInfo,
                        (ushort)nodeId,
                        DefaultNodeMarkerColor,
                        true);
                }

                if (!hasMarkers)
                {
                    continue;
                }

                foreach (NodeLaneMarker laneMarker in nodeMarkers)
                {
                    if (!Constants.ServiceFactory.NetService.IsLaneValid(laneMarker.LaneId))
                    {
                        continue;
                    }

                    if (laneMarker != selectedMarker)
                    {
                        foreach (NodeLaneMarker targetLaneMarker in laneMarker.ConnectedMarkers)
                        {
                            // render lane connection from laneMarker to targetLaneMarker
                            if (!Constants.ServiceFactory.NetService.IsLaneValid(targetLaneMarker.LaneId))
                            {
                                continue;
                            }

                            DrawLaneCurve(
                                cameraInfo,
                                laneMarker.Position,
                                targetLaneMarker.Position,
                                NetManager.instance.m_nodes.m_buffer[nodeId].m_position,
                                laneMarker.Color,
                                Color.black);
                        }
                    }

                    if (viewOnly || (nodeId != SelectedNodeId))
                    {
                        continue;
                    }

                    // draw source marker in source selection mode,
                    // draw target marker (if segment turning angles are within bounds) and
                    // selected source marker in target selection mode
                    bool drawMarker
                        = ((GetMarkerSelectionMode() == MarkerSelectionMode.SelectSource) &&
                           laneMarker.IsSource) ||
                          ((GetMarkerSelectionMode() == MarkerSelectionMode.SelectTarget) &&
                           ((laneMarker.IsTarget &&
                             ((laneMarker.VehicleType & selectedMarker.VehicleType)
                              != VehicleInfo.VehicleType.None) &&
                             CheckSegmentsTurningAngle(
                                 selectedMarker.SegmentId,
                                 ref netManager.m_segments.m_buffer[selectedMarker.SegmentId],
                                 selectedMarker.StartNode,
                                 laneMarker.SegmentId,
                                 ref netManager.m_segments.m_buffer[laneMarker.SegmentId],
                                 laneMarker.StartNode)) ||
                            (laneMarker == selectedMarker)));

                    // highlight hovered marker and selected marker
                    if (drawMarker)
                    {
                        bool markerIsHovered = false;
                        if (hoveredMarker == null)
                        {
                            float hitH = TrafficManagerTool.GetAccurateHitHeight();
                            markerIsHovered =
                                laneMarker.segmentLaneMarker.IntersectRay(ref mouseRay, hitH);

                            if (markerIsHovered)
                            {
                                hoveredMarker = laneMarker;
                            }
                        }

                        bool isTarget        = selectedMarker != null && laneMarker != selectedMarker;
                        var  color           = isTarget ? Color.white : laneMarker.Color;
                        bool highlightMarker = laneMarker == selectedMarker || markerIsHovered;
                        if (highlightMarker)
                        {
                            laneMarker.segmentLaneMarker.RenderOverlay(cameraInfo, color, enlarge: true);
                        }
                        laneMarker.RenderOverlay(cameraInfo, color, enlarge: highlightMarker);
                    } // if drawMarker

                    if (selectedMarker != null)
                    {
                        // lane curves for selectedMarker will be drawn last to
                        // be on the top of other lane markers.
                        foreach (NodeLaneMarker targetLaneMarker in selectedMarker.ConnectedMarkers)
                        {
                            if (!Constants.ServiceFactory.NetService.IsLaneValid(targetLaneMarker.LaneId))
                            {
                                continue;
                            }

                            DrawLaneCurve(
                                cameraInfo,
                                selectedMarker.Position,
                                targetLaneMarker.Position,
                                NetManager.instance.m_nodes.m_buffer[nodeId].m_position,
                                selectedMarker.Color,
                                Color.grey,
                                size: 0.18f // Embolden
                                );
                        } // end foreach selectedMarker.ConnectedMarkers
                    } // end if selectedMarker != null
                }     // end foreach lanemarker in node markers
            }         // end for node in all nodes
        }
Esempio n. 8
0
 public ToggleTrafficLightsTool(TrafficManagerTool mainTool)
     : base(mainTool)
 {
     CachedVisibleNodeIds = new GenericArrayCache <ushort>(NetManager.MAX_NODE_COUNT);
     LastCachedCamera     = new CameraTransformValue();
 }
Esempio n. 9
0
        private void ShowOverlay(bool viewOnly, RenderManager.CameraInfo cameraInfo)
        {
            if (viewOnly && !(Options.connectedLanesOverlay ||
                              PrioritySignsTool.MassEditOVerlay.IsActive))
            {
                return;
            }

            NetManager netManager = Singleton <NetManager> .instance;

            Vector3 camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position;

            // Bounds bounds = new Bounds(Vector3.zero, Vector3.one);
            Camera currentCamera = Camera.main;

            // Check if camera pos/angle has changed then re-filter the visible nodes
            // Assumption: The states checked in this loop don't change while the tool is active
            var currentCameraState = new CameraTransformValue(currentCamera);

            if (!LastCachedCamera.Equals(currentCameraState))
            {
                CachedVisibleNodeIds.Clear();
                LastCachedCamera = currentCameraState;

                for (uint nodeId = 1; nodeId < NetManager.MAX_NODE_COUNT; ++nodeId)
                {
                    if (!Constants.ServiceFactory.NetService.IsNodeValid((ushort)nodeId))
                    {
                        continue;
                    }

                    //---------------------------
                    // Check the connection class
                    //---------------------------
                    // TODO refactor connection class check
                    ItemClass connectionClass =
                        NetManager.instance.m_nodes.m_buffer[nodeId].Info.GetConnectionClass();

                    if ((connectionClass == null) ||
                        !((connectionClass.m_service == ItemClass.Service.Road) ||
                          ((connectionClass.m_service == ItemClass.Service.PublicTransport) &&
                           ((connectionClass.m_subService == ItemClass.SubService.PublicTransportTrain) ||
                            (connectionClass.m_subService == ItemClass.SubService.PublicTransportMetro) ||
                            (connectionClass.m_subService == ItemClass.SubService.PublicTransportMonorail)))))
                    {
                        continue;
                    }

                    //--------------------------
                    // Check the camera distance
                    //--------------------------
                    Vector3 diff = NetManager.instance.m_nodes.m_buffer[nodeId].m_position - camPos;

                    if (diff.sqrMagnitude > TrafficManagerTool.MAX_OVERLAY_DISTANCE_SQR)
                    {
                        continue; // do not draw if too distant
                    }

                    // Add
                    CachedVisibleNodeIds.Add(nodeId);
                }
            }

            for (int cacheIndex = CachedVisibleNodeIds.Size - 1; cacheIndex >= 0; cacheIndex--)
            {
                var nodeId = CachedVisibleNodeIds.Values[cacheIndex];

                bool hasMarkers = currentLaneEnds.TryGetValue((ushort)nodeId, out List <LaneEnd> laneEnds);
                if (!viewOnly && (GetSelectionMode() == SelectionMode.None))
                {
                    MainTool.DrawNodeCircle(
                        cameraInfo,
                        (ushort)nodeId,
                        DefaultLaneEndColor,
                        true);
                }

                if (!hasMarkers)
                {
                    continue;
                }

                foreach (LaneEnd laneEnd in laneEnds)
                {
                    if (!Constants.ServiceFactory.NetService.IsLaneValid(laneEnd.LaneId))
                    {
                        continue;
                    }

                    if (laneEnd != selectedLaneEnd)
                    {
                        foreach (LaneEnd targetLaneEnd in laneEnd.ConnectedLaneEnds)
                        {
                            // render lane connection from laneEnd to targetLaneEnd
                            if (!Constants.ServiceFactory.NetService.IsLaneValid(targetLaneEnd.LaneId))
                            {
                                continue;
                            }

                            DrawLaneCurve(
                                cameraInfo,
                                laneEnd.NodeMarker.TerrainPosition,
                                targetLaneEnd.NodeMarker.TerrainPosition,
                                NetManager.instance.m_nodes.m_buffer[nodeId].m_position,
                                laneEnd.Color,
                                Color.black);
                        }
                    }

                    if (viewOnly || (nodeId != SelectedNodeId))
                    {
                        continue;
                    }

                    bool drawMarker = false;
                    bool SourceMode = GetSelectionMode() == SelectionMode.SelectSource;
                    bool TargetMode = GetSelectionMode() == SelectionMode.SelectTarget;
                    if (SourceMode & laneEnd.IsSource)
                    {
                        // draw source marker in source selection mode,
                        // make exception for markers that have no target:
                        foreach (var targetLaneEnd in laneEnds)
                        {
                            if (CanConnect(laneEnd, targetLaneEnd))
                            {
                                drawMarker = true;
                                break;
                            }
                        }
                    }
                    else if (TargetMode)
                    {
                        // selected source marker in target selection mode
                        drawMarker =
                            selectedLaneEnd == laneEnd ||
                            CanConnect(selectedLaneEnd, laneEnd);
                    }

                    // highlight hovered marker and selected marker
                    if (drawMarker)
                    {
                        bool markerIsHovered = false;
                        if (hoveredLaneEnd == null)
                        {
                            float hitH = TrafficManagerTool.GetAccurateHitHeight();
                            markerIsHovered =
                                laneEnd.IntersectRay();

                            if (markerIsHovered)
                            {
                                hoveredLaneEnd = laneEnd;
                            }
                        }

                        bool isTarget        = selectedLaneEnd != null && laneEnd != selectedLaneEnd;
                        var  color           = isTarget ? Color.white : laneEnd.Color;
                        bool highlightMarker = laneEnd == selectedLaneEnd || markerIsHovered;
                        laneEnd.RenderOverlay(cameraInfo, color, highlightMarker);
                    } // if drawMarker

                    if (selectedLaneEnd != null)
                    {
                        // lane curves for selectedMarker will be drawn last to
                        // be on the top of other lane markers.
                        foreach (LaneEnd targetLaneEnd in selectedLaneEnd.ConnectedLaneEnds)
                        {
                            if (!Constants.ServiceFactory.NetService.IsLaneValid(targetLaneEnd.LaneId))
                            {
                                continue;
                            }

                            DrawLaneCurve(
                                cameraInfo,
                                selectedLaneEnd.NodeMarker.TerrainPosition,
                                targetLaneEnd.NodeMarker.TerrainPosition,
                                NetManager.instance.m_nodes.m_buffer[nodeId].m_position,
                                selectedLaneEnd.Color,
                                Color.grey,
                                size: 0.18f // Embolden
                                );
                        } // end foreach selectedMarker.ConnectedMarkers
                    } // end if selectedMarker != null
                }     // end foreach lanemarker in node markers
            }         // end for node in all nodes
        }
Esempio n. 10
0
        private void ShowOverlay(bool viewOnly, RenderManager.CameraInfo cameraInfo)
        {
            if (viewOnly && !Options.connectedLanesOverlay)
            {
                return;
            }

            NetManager netManager = Singleton <NetManager> .instance;

            Vector3 camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position;

            // Bounds bounds = new Bounds(Vector3.zero, Vector3.one);
            Camera currentCamera = Camera.main;
            Ray    mouseRay      = currentCamera.ScreenPointToRay(Input.mousePosition);

            // Check if camera pos/angle has changed then re-filter the visible nodes
            // Assumption: The states checked in this loop don't change while the tool is active
            var currentCameraState = new CameraTransformValue(currentCamera);

            if (!LastCachedCamera.Equals(currentCameraState))
            {
                CachedVisibleNodeIds.Clear();
                LastCachedCamera = currentCameraState;

                for (uint nodeId = 1; nodeId < NetManager.MAX_NODE_COUNT; ++nodeId)
                {
                    if (!Constants.ServiceFactory.NetService.IsNodeValid((ushort)nodeId))
                    {
                        continue;
                    }

                    //---------------------------
                    // Check the connection class
                    //---------------------------
                    // TODO refactor connection class check
                    ItemClass connectionClass =
                        NetManager.instance.m_nodes.m_buffer[nodeId].Info.GetConnectionClass();

                    if ((connectionClass == null) ||
                        !((connectionClass.m_service == ItemClass.Service.Road) ||
                          ((connectionClass.m_service == ItemClass.Service.PublicTransport) &&
                           ((connectionClass.m_subService == ItemClass.SubService.PublicTransportTrain) ||
                            (connectionClass.m_subService == ItemClass.SubService.PublicTransportMetro) ||
                            (connectionClass.m_subService == ItemClass.SubService.PublicTransportMonorail)))))
                    {
                        continue;
                    }

                    //--------------------------
                    // Check the camera distance
                    //--------------------------
                    Vector3 diff = NetManager.instance.m_nodes.m_buffer[nodeId].m_position - camPos;

                    if (diff.sqrMagnitude > TrafficManagerTool.MAX_OVERLAY_DISTANCE_SQR)
                    {
                        continue; // do not draw if too distant
                    }

                    // Add
                    CachedVisibleNodeIds.Add(nodeId);
                }
            }

            for (int cacheIndex = CachedVisibleNodeIds.Size - 1; cacheIndex >= 0; cacheIndex--)
            {
                var nodeId = CachedVisibleNodeIds.Values[cacheIndex];

                List <NodeLaneMarker> nodeMarkers;
                bool hasMarkers = currentNodeMarkers.TryGetValue((ushort)nodeId, out nodeMarkers);

                if (!viewOnly && (GetMarkerSelectionMode() == MarkerSelectionMode.None))
                {
                    MainTool.DrawNodeCircle(
                        cameraInfo,
                        (ushort)nodeId,
                        DefaultNodeMarkerColor,
                        true);
                }

                if (!hasMarkers)
                {
                    continue;
                }

                foreach (NodeLaneMarker laneMarker in nodeMarkers)
                {
                    if (!Constants.ServiceFactory.NetService.IsLaneValid(laneMarker.LaneId))
                    {
                        continue;
                    }

                    foreach (NodeLaneMarker targetLaneMarker in laneMarker.ConnectedMarkers)
                    {
                        // render lane connection from laneMarker to targetLaneMarker
                        if (!Constants.ServiceFactory.NetService.IsLaneValid(targetLaneMarker.LaneId))
                        {
                            continue;
                        }

                        DrawLaneCurve(
                            cameraInfo,
                            laneMarker.Position,
                            targetLaneMarker.Position,
                            NetManager.instance.m_nodes.m_buffer[nodeId].m_position,
                            laneMarker.Color,
                            Color.black);
                    }

                    if (viewOnly || (nodeId != SelectedNodeId))
                    {
                        continue;
                    }

                    // bounds.center = laneMarker.position;
                    // bounds.IntersectRay(mouseRay);
                    bool markerIsHovered = IsLaneMarkerHovered(laneMarker, ref mouseRay);

                    // draw source marker in source selection mode,
                    // draw target marker (if segment turning angles are within bounds) and
                    // selected source marker in target selection mode
                    bool drawMarker
                        = ((GetMarkerSelectionMode() == MarkerSelectionMode.SelectSource) &&
                           laneMarker.IsSource) ||
                          ((GetMarkerSelectionMode() == MarkerSelectionMode.SelectTarget) &&
                           ((laneMarker.IsTarget &&
                             ((laneMarker.VehicleType & selectedMarker.VehicleType)
                              != VehicleInfo.VehicleType.None) &&
                             CheckSegmentsTurningAngle(
                                 selectedMarker.SegmentId,
                                 ref netManager.m_segments.m_buffer[selectedMarker.SegmentId],
                                 selectedMarker.StartNode,
                                 laneMarker.SegmentId,
                                 ref netManager.m_segments.m_buffer[laneMarker.SegmentId],
                                 laneMarker.StartNode)) ||
                            (laneMarker == selectedMarker)));

                    // highlight hovered marker and selected marker
                    bool highlightMarker =
                        drawMarker && ((laneMarker == selectedMarker) || markerIsHovered);

                    if (drawMarker)
                    {
                        laneMarker.Radius = highlightMarker ? 2f : 1f;
                    }
                    else
                    {
                        markerIsHovered = false;
                    }

                    if (markerIsHovered)
                    {
                        hoveredMarker = laneMarker;
                    }

                    var circleColor = laneMarker.IsTarget ? Color.white : laneMarker.Color;

                    if (drawMarker)
                    {
                        RenderManager.instance.OverlayEffect.DrawCircle(
                            cameraInfo,
                            circleColor,
                            laneMarker.Position,
                            laneMarker.Radius,
                            laneMarker.Position.y - 100f, // through all the geometry -100..100
                            laneMarker.Position.y + 100f,
                            false,
                            true);
                        RenderManager.instance.OverlayEffect.DrawCircle(
                            cameraInfo,
                            Color.black,
                            laneMarker.Position,
                            laneMarker.Radius * 0.75f,    // inner black
                            laneMarker.Position.y - 100f, // through all the geometry -100..100
                            laneMarker.Position.y + 100f,
                            false,
                            false);
                    }
                } // end foreach lanemarker in node markers
            }     // end for node in all nodes
        }