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);
            }
        }
        private void ShowSigns(bool viewOnly)
        {
            Quaternion camRot = Camera.main.transform.rotation;
            Vector3    camPos = Camera.main.transform.position;

            NetManager        netManager        = Singleton <NetManager> .instance;
            SpeedLimitManager speedLimitManager = SpeedLimitManager.Instance;

            if (lastCamPos == null || lastCamRot == null || !lastCamRot.Equals(camRot) || !lastCamPos.Equals(camPos))
            {
                // cache visible segments
                currentlyVisibleSegmentIds.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;*/

                    if ((netManager.m_segments.m_buffer[segmentId].m_bounds.center - camPos).magnitude > TrafficManagerTool.MaxOverlayDistance)
                    {
                        continue;                         // do not draw if too distant
                    }
                    Vector3 screenPos;
                    bool    visible = MainTool.WorldToScreenPoint(netManager.m_segments.m_buffer[segmentId].m_bounds.center, out screenPos);

                    if (!visible)
                    {
                        continue;
                    }

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

                    currentlyVisibleSegmentIds.Add((ushort)segmentId);
                }

                lastCamPos = camPos;
                lastCamRot = camRot;
            }

            bool handleHovered = false;

            foreach (ushort segmentId in currentlyVisibleSegmentIds)
            {
                Vector3 screenPos;
                bool    visible = MainTool.WorldToScreenPoint(netManager.m_segments.m_buffer[segmentId].m_bounds.center, out screenPos);

                if (!visible)
                {
                    continue;
                }

                NetInfo segmentInfo = netManager.m_segments.m_buffer[segmentId].Info;

                // draw speed limits
                if (MainTool.GetToolMode() != ToolMode.VehicleRestrictions || segmentId != SelectedSegmentId)                   // no speed limit overlay on selected segment when in vehicle restrictions mode
                {
                    if (drawSpeedLimitHandles((ushort)segmentId, ref netManager.m_segments.m_buffer[segmentId], viewOnly, ref camPos))
                    {
                        handleHovered = true;
                    }
                }
            }
            overlayHandleHovered = handleHovered;
        }