private bool drawSpeedLimitHandles(ushort segmentId, ref NetSegment segment, bool viewOnly, ref Vector3 camPos)
        {
            if (viewOnly && !Options.speedLimitsOverlay)
            {
                return(false);
            }

            Vector3    center     = segment.m_bounds.center;
            NetManager netManager = Singleton <NetManager> .instance;

            bool   hovered         = false;
            ushort speedLimitToSet = viewOnly ? (ushort)0 : SpeedLimitManager.Instance.AvailableSpeedLimits[curSpeedLimitIndex];

            bool showPerLane = showLimitsPerLane;

            if (!viewOnly)
            {
                showPerLane = showLimitsPerLane ^ (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl));
            }
            if (showPerLane)
            {
                // show individual speed limit handle per lane
                int numDirections;
                int numLanes = TrafficManagerTool.GetSegmentNumVehicleLanes(segmentId, null, out numDirections, SpeedLimitManager.VEHICLE_TYPES);

                NetInfo segmentInfo = segment.Info;
                Vector3 yu          = (segment.m_endDirection - segment.m_startDirection).normalized;
                Vector3 xu          = Vector3.Cross(yu, new Vector3(0, 1f, 0)).normalized;

                /*if ((segment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) {
                 *      xu = -xu;
                 * }*/
                float   f    = viewOnly ? 4f : 7f;            // reserved sign size in game coordinates
                Vector3 zero = center - 0.5f * (float)(numLanes - 1 + numDirections - 1) * f * xu;

                uint            x                 = 0;
                var             guiColor          = GUI.color;
                IList <LanePos> sortedLanes       = Constants.ServiceFactory.NetService.GetSortedLanes(segmentId, ref segment, null, SpeedLimitManager.LANE_TYPES, SpeedLimitManager.VEHICLE_TYPES);
                bool            onlyMonorailLanes = sortedLanes.Count > 0;
                if (!viewOnly)
                {
                    foreach (LanePos laneData in sortedLanes)
                    {
                        byte         laneIndex = laneData.laneIndex;
                        NetInfo.Lane laneInfo  = segmentInfo.m_lanes[laneIndex];

                        if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Monorail) == VehicleInfo.VehicleType.None)
                        {
                            onlyMonorailLanes = false;
                            break;
                        }
                    }
                }

                HashSet <NetInfo.Direction> directions = new HashSet <NetInfo.Direction>();
                int sortedLaneIndex = -1;
                foreach (LanePos laneData in sortedLanes)
                {
                    ++sortedLaneIndex;
                    uint laneId    = laneData.laneId;
                    byte laneIndex = laneData.laneIndex;

                    NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex];
                    if (!directions.Contains(laneInfo.m_finalDirection))
                    {
                        if (directions.Count > 0)
                        {
                            ++x;                             // space between different directions
                        }
                        directions.Add(laneInfo.m_finalDirection);
                    }

                    bool hoveredHandle = MainTool.DrawGenericSquareOverlayGridTexture(TextureResources.SpeedLimitTextures[SpeedLimitManager.Instance.GetCustomSpeedLimit(laneId)], camPos, zero, f, xu, yu, x, 0, speedLimitSignSize, !viewOnly, 0.5f, 0.8f);
                    if (!viewOnly && !onlyMonorailLanes && (laneInfo.m_vehicleType & VehicleInfo.VehicleType.Monorail) != VehicleInfo.VehicleType.None)
                    {
                        MainTool.DrawStaticSquareOverlayGridTexture(TextureResources.VehicleInfoSignTextures[ExtVehicleType.PassengerTrain], camPos, zero, f, xu, yu, x, 1, speedLimitSignSize, 0.5f);
                    }
                    if (hoveredHandle)
                    {
                        hovered = true;
                    }

                    if (hoveredHandle && Input.GetMouseButton(0) && !IsCursorInPanel())
                    {
                        SpeedLimitManager.Instance.SetSpeedLimit(segmentId, laneIndex, laneInfo, laneId, speedLimitToSet);

                        if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
                        {
                            SegmentLaneTraverser.Traverse(segmentId, SegmentTraverser.TraverseDirection.AnyDirection, SegmentTraverser.TraverseSide.AnySide, SegmentLaneTraverser.LaneStopCriterion.LaneCount, SegmentTraverser.SegmentStopCriterion.Junction, SpeedLimitManager.LANE_TYPES, SpeedLimitManager.VEHICLE_TYPES, delegate(SegmentLaneVisitData data) {
                                if (data.segVisitData.initial)
                                {
                                    return(true);
                                }

                                if (sortedLaneIndex != data.sortedLaneIndex)
                                {
                                    return(true);
                                }

                                Constants.ServiceFactory.NetService.ProcessSegment(data.segVisitData.curGeo.SegmentId, delegate(ushort curSegmentId, ref NetSegment curSegment) {
                                    NetInfo.Lane curLaneInfo = curSegment.Info.m_lanes[data.curLanePos.laneIndex];
                                    SpeedLimitManager.Instance.SetSpeedLimit(curSegmentId, data.curLanePos.laneIndex, curLaneInfo, data.curLanePos.laneId, speedLimitToSet);
                                    return(true);
                                });

                                return(true);
                            });
                        }
                    }

                    ++x;
                }
            }
            else
            {
                // draw speedlimits over mean middle points of lane beziers
                Dictionary <NetInfo.Direction, Vector3> segCenter;
                if (!segmentCenterByDir.TryGetValue(segmentId, out segCenter))
                {
                    segCenter = new Dictionary <NetInfo.Direction, Vector3>();
                    segmentCenterByDir.Add(segmentId, segCenter);
                    TrafficManagerTool.CalculateSegmentCenterByDir(segmentId, segCenter);
                }

                foreach (KeyValuePair <NetInfo.Direction, Vector3> e in segCenter)
                {
                    Vector3 screenPos;
                    bool    visible = MainTool.WorldToScreenPoint(e.Value, out screenPos);

                    if (!visible)
                    {
                        continue;
                    }

                    float zoom          = 1.0f / (e.Value - camPos).magnitude * 100f * MainTool.GetBaseZoom();
                    float size          = (viewOnly ? 0.8f : 1f) * speedLimitSignSize * zoom;
                    Color guiColor      = GUI.color;
                    Rect  boundingBox   = new Rect(screenPos.x - size / 2, screenPos.y - size / 2, size, size);
                    bool  hoveredHandle = !viewOnly && TrafficManagerTool.IsMouseOver(boundingBox);

                    if (hoveredHandle)
                    {
                        // mouse hovering over sign
                        hovered    = true;
                        guiColor.a = 0.8f;
                    }
                    else
                    {
                        guiColor.a = 0.5f;
                    }

                    GUI.color = guiColor;
                    GUI.DrawTexture(boundingBox, TextureResources.SpeedLimitTextures[SpeedLimitManager.Instance.GetCustomSpeedLimit(segmentId, e.Key)]);

                    if (hoveredHandle && Input.GetMouseButton(0) && !IsCursorInPanel())
                    {
                        // change the speed limit to the selected one
                        //Log._Debug($"Setting speed limit of segment {segmentId}, dir {e.Key.ToString()} to {speedLimitToSet}");
                        SpeedLimitManager.Instance.SetSpeedLimit(segmentId, e.Key, speedLimitToSet);

                        if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
                        {
                            NetInfo.Direction normDir = e.Key;
                            if ((netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
                            {
                                normDir = NetInfo.InvertDirection(normDir);
                            }

                            SegmentLaneTraverser.Traverse(segmentId, SegmentTraverser.TraverseDirection.AnyDirection, SegmentTraverser.TraverseSide.AnySide, SegmentLaneTraverser.LaneStopCriterion.LaneCount, SegmentTraverser.SegmentStopCriterion.Junction, SpeedLimitManager.LANE_TYPES, SpeedLimitManager.VEHICLE_TYPES, delegate(SegmentLaneVisitData data) {
                                if (data.segVisitData.initial)
                                {
                                    return(true);
                                }
                                bool reverse = data.segVisitData.viaStartNode == data.segVisitData.viaInitialStartNode;

                                ushort otherSegmentId    = data.segVisitData.curGeo.SegmentId;
                                NetInfo otherSegmentInfo = netManager.m_segments.m_buffer[otherSegmentId].Info;
                                uint laneId           = data.curLanePos.laneId;
                                byte laneIndex        = data.curLanePos.laneIndex;
                                NetInfo.Lane laneInfo = otherSegmentInfo.m_lanes[laneIndex];

                                NetInfo.Direction otherNormDir = laneInfo.m_finalDirection;
                                if ((netManager.m_segments.m_buffer[otherSegmentId].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None ^
                                    reverse)
                                {
                                    otherNormDir = NetInfo.InvertDirection(otherNormDir);
                                }

                                if (otherNormDir == normDir)
                                {
                                    SpeedLimitManager.Instance.SetSpeedLimit(otherSegmentId, laneInfo.m_finalDirection, speedLimitToSet);
                                }

                                return(true);
                            });
                        }
                    }

                    guiColor.a = 1f;
                    GUI.color  = guiColor;
                }
            }
            return(hovered);
        }
Esempio n. 2
0
        private bool DrawVehicleRestrictionHandles(ushort segmentId,
                                                   ref NetSegment segment,
                                                   bool viewOnly,
                                                   out bool stateUpdated)
        {
            stateUpdated = false;

            if (viewOnly && !Options.vehicleRestrictionsOverlay &&
                MainTool.GetToolMode() != ToolMode.VehicleRestrictions)
            {
                return(false);
            }

            Vector3 center = segment.m_bounds.center;

            bool visible = GeometryUtil.WorldToScreenPoint(center, out Vector3 _);

            if (!visible)
            {
                return(false);
            }

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

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

            int numLanes = GeometryUtil.GetSegmentNumVehicleLanes(
                segmentId,
                null,
                out int numDirections,
                VehicleRestrictionsManager.VEHICLE_TYPES);

            // draw vehicle restrictions over each lane
            NetInfo segmentInfo = segment.Info;
            Vector3 yu          = (segment.m_endDirection - segment.m_startDirection).normalized;

            // if ((segment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None)
            //        yu = -yu;
            Vector3 xu          = Vector3.Cross(yu, new Vector3(0, 1f, 0)).normalized;
            float   f           = viewOnly ? 4f : 7f; // reserved sign size in game coordinates
            int     maxNumSigns = 0;

            if (VehicleRestrictionsManager.Instance.IsRoadSegment(segmentInfo))
            {
                maxNumSigns = RoadVehicleTypes.Length;
            }
            else if (VehicleRestrictionsManager.Instance.IsRailSegment(segmentInfo))
            {
                maxNumSigns = RailVehicleTypes.Length;
            }

            // Vector3 zero = center - 0.5f * (float)(numLanes + numDirections - 1) * f * (xu + yu); // "bottom left"
            Vector3 zero = center - (0.5f * (numLanes - 1 + numDirections - 1) * f * xu)
                           - (0.5f * maxNumSigns * f * yu);        // "bottom left"

            // if (!viewOnly)
            //     Log._Debug($"xu: {xu.ToString()} yu: {yu.ToString()} center: {center.ToString()}
            //     zero: {zero.ToString()} numLanes: {numLanes} numDirections: {numDirections}");*/

            uint            x           = 0;
            Color           guiColor    = GUI.color;
            IList <LanePos> sortedLanes = Constants.ServiceFactory.NetService.GetSortedLanes(
                segmentId,
                ref segment,
                null,
                VehicleRestrictionsManager.LANE_TYPES,
                VehicleRestrictionsManager.VEHICLE_TYPES);
            bool hovered = false;
            HashSet <NetInfo.Direction> directions = new HashSet <NetInfo.Direction>();
            int sortedLaneIndex = -1;

            foreach (LanePos laneData in sortedLanes)
            {
                ++sortedLaneIndex;
                uint laneId    = laneData.laneId;
                byte laneIndex = laneData.laneIndex;

                NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex];

                if (!directions.Contains(laneInfo.m_finalDirection))
                {
                    if (directions.Count > 0)
                    {
                        ++x; // space between different directions
                    }

                    directions.Add(laneInfo.m_finalDirection);
                }

                ExtVehicleType[] possibleVehicleTypes;

                if (VehicleRestrictionsManager.Instance.IsRoadLane(laneInfo))
                {
                    possibleVehicleTypes = RoadVehicleTypes;
                }
                else if (VehicleRestrictionsManager.Instance.IsRailLane(laneInfo))
                {
                    possibleVehicleTypes = RailVehicleTypes;
                }
                else
                {
                    ++x;
                    continue;
                }

                ExtVehicleType allowedTypes =
                    VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(
                        segmentId,
                        segmentInfo,
                        laneIndex,
                        laneInfo,
                        VehicleRestrictionsMode.Configured);

                uint y = 0;
#if DEBUG_disabled_xxx
                Vector3 labelCenter = zero + f * (float)x * xu + f * (float)y * yu; // in game coordinates

                Vector3 labelScreenPos;
                bool    visible = GeometryUtil.WorldToScreenPoint(labelCenter, out labelScreenPos);
                // BUGBUG: Using screen.height might be wrong, consider U.UIScaler.ScreenHeight (from UIView.fixedHeight)
                labelScreenPos.y = Screen.height - labelScreenPos.y;
                diff             = labelCenter - camPos;

                var labelZoom = 1.0f / diff.magnitude * 100f;
                _counterStyle.fontSize         = (int)(11f * labelZoom);
                _counterStyle.normal.textColor = new Color(1f, 1f, 0f);

                string  labelStr  = $"Idx {laneIndex}";
                Vector2 dim       = _counterStyle.CalcSize(new GUIContent(labelStr));
                Rect    labelRect = new Rect(labelScreenPos.x - dim.x / 2f, labelScreenPos.y, dim.x, dim.y);
                GUI.Label(labelRect, labelStr, _counterStyle);

                ++y;
#endif
                Color guiColor2 = GUI.color;
                GUI.color = GUI.color.WithAlpha(TrafficManagerTool.OverlayAlpha);
                foreach (ExtVehicleType vehicleType in possibleVehicleTypes)
                {
                    bool allowed = VehicleRestrictionsManager.Instance.IsAllowed(allowedTypes, vehicleType);

                    if (allowed && viewOnly)
                    {
                        continue; // do not draw allowed vehicles in view-only mode
                    }


                    bool hoveredHandle = MainTool.DrawGenericSquareOverlayGridTexture(
                        RoadUI.VehicleRestrictionTextures[vehicleType][allowed],
                        camPos,
                        zero,
                        f,
                        xu,
                        yu,
                        x,
                        y,
                        vehicleRestrictionsSignSize,
                        !viewOnly);

                    if (hoveredHandle)
                    {
                        hovered = true;
                        renderData_.segmentId       = segmentId;
                        renderData_.laneId          = laneId;
                        renderData_.laneIndex       = laneIndex;
                        renderData_.laneInfo        = laneInfo;
                        renderData_.SortedLaneIndex = sortedLaneIndex;
                    }

                    if (hoveredHandle && MainTool.CheckClicked())
                    {
                        // toggle vehicle restrictions
                        // Log._Debug($"Setting vehicle restrictions of segment {segmentId}, lane
                        //     idx {laneIndex}, {vehicleType.ToString()} to {!allowed}");
                        VehicleRestrictionsManager.Instance.ToggleAllowedType(
                            segmentId,
                            segmentInfo,
                            laneIndex,
                            laneId,
                            laneInfo,
                            vehicleType,
                            !allowed);
                        stateUpdated = true;
                        RefreshCurrentRestrictedSegmentIds(segmentId);
                        if (RoadMode)
                        {
                            ApplyRestrictionsToAllSegments(sortedLaneIndex, vehicleType);
                        }
                    }

                    ++y;
                }

                GUI.color = guiColor2;

                ++x;
            }

            guiColor.a = 1f;
            GUI.color  = guiColor;

            return(hovered);
        }
        private bool drawVehicleRestrictionHandles(ushort segmentId, ref NetSegment segment, bool viewOnly, out bool stateUpdated)
        {
            stateUpdated = false;

            if (viewOnly && !Options.vehicleRestrictionsOverlay && MainTool.GetToolMode() != ToolMode.VehicleRestrictions)
            {
                return(false);
            }

            Vector3 center = segment.m_bounds.center;

            var screenPos = Camera.main.WorldToScreenPoint(center);

            screenPos.y = Screen.height - screenPos.y;
            if (screenPos.z < 0)
            {
                return(false);
            }
            var camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position;
            var diff   = center - camPos;

            if (diff.magnitude > TrafficManagerTool.MaxOverlayDistance)
            {
                return(false);                // do not draw if too distant
            }
            int numDirections;
            int numLanes = TrafficManagerTool.GetSegmentNumVehicleLanes(segmentId, null, out numDirections, VehicleRestrictionsManager.VEHICLE_TYPES);

            // draw vehicle restrictions over each lane
            NetInfo segmentInfo = segment.Info;
            Vector3 yu          = (segment.m_endDirection - segment.m_startDirection).normalized;

            /*if ((segment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None)
             *      yu = -yu;*/
            Vector3 xu          = Vector3.Cross(yu, new Vector3(0, 1f, 0)).normalized;
            float   f           = viewOnly ? 4f : 7f; // reserved sign size in game coordinates
            int     maxNumSigns = 0;

            if (VehicleRestrictionsManager.Instance.IsRoadSegment(segmentInfo))
            {
                maxNumSigns = roadVehicleTypes.Length;
            }
            else if (VehicleRestrictionsManager.Instance.IsRailSegment(segmentInfo))
            {
                maxNumSigns = railVehicleTypes.Length;
            }
            //Vector3 zero = center - 0.5f * (float)(numLanes + numDirections - 1) * f * (xu + yu); // "bottom left"
            Vector3 zero = center - 0.5f * (float)(numLanes - 1 + numDirections - 1) * f * xu - 0.5f * (float)maxNumSigns * f * yu;             // "bottom left"

            /*if (!viewOnly)
             *      Log._Debug($"xu: {xu.ToString()} yu: {yu.ToString()} center: {center.ToString()} zero: {zero.ToString()} numLanes: {numLanes} numDirections: {numDirections}");*/

            uint                        x               = 0;
            var                         guiColor        = GUI.color;
            IList <LanePos>             sortedLanes     = Constants.ServiceFactory.NetService.GetSortedLanes(segmentId, ref segment, null, VehicleRestrictionsManager.LANE_TYPES, VehicleRestrictionsManager.VEHICLE_TYPES);
            bool                        hovered         = false;
            HashSet <NetInfo.Direction> directions      = new HashSet <NetInfo.Direction>();
            int                         sortedLaneIndex = -1;

            foreach (LanePos laneData in sortedLanes)
            {
                ++sortedLaneIndex;
                uint laneId    = laneData.laneId;
                byte laneIndex = laneData.laneIndex;

                NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex];
                if (!directions.Contains(laneInfo.m_finalDirection))
                {
                    if (directions.Count > 0)
                    {
                        ++x;                         // space between different directions
                    }
                    directions.Add(laneInfo.m_finalDirection);
                }

                ExtVehicleType[] possibleVehicleTypes = null;
                if (VehicleRestrictionsManager.Instance.IsRoadLane(laneInfo))
                {
                    possibleVehicleTypes = roadVehicleTypes;
                }
                else if (VehicleRestrictionsManager.Instance.IsRailLane(laneInfo))
                {
                    possibleVehicleTypes = railVehicleTypes;
                }
                else
                {
                    ++x;
                    continue;
                }

                ExtVehicleType allowedTypes = VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, VehicleRestrictionsMode.Configured);

                uint y = 0;
#if DEBUGx
                Vector3 labelCenter = zero + f * (float)x * xu + f * (float)y * yu;                 // in game coordinates

                var labelScreenPos = Camera.main.WorldToScreenPoint(labelCenter);
                labelScreenPos.y = Screen.height - labelScreenPos.y;
                diff             = labelCenter - camPos;

                var labelZoom = 1.0f / diff.magnitude * 100f;
                _counterStyle.fontSize         = (int)(11f * labelZoom);
                _counterStyle.normal.textColor = new Color(1f, 1f, 0f);

                string  labelStr  = $"Idx {laneIndex}";
                Vector2 dim       = _counterStyle.CalcSize(new GUIContent(labelStr));
                Rect    labelRect = new Rect(labelScreenPos.x - dim.x / 2f, labelScreenPos.y, dim.x, dim.y);
                GUI.Label(labelRect, labelStr, _counterStyle);

                ++y;
#endif
                foreach (ExtVehicleType vehicleType in possibleVehicleTypes)
                {
                    bool allowed = VehicleRestrictionsManager.Instance.IsAllowed(allowedTypes, vehicleType);
                    if (allowed && viewOnly)
                    {
                        continue;                         // do not draw allowed vehicles in view-only mode
                    }
                    bool hoveredHandle = MainTool.DrawGenericSquareOverlayGridTexture(TextureResources.VehicleRestrictionTextures[vehicleType][allowed], ref camPos, ref zero, f, ref xu, ref yu, x, y, vehicleRestrictionsSignSize, !viewOnly, 0.5f, 0.8f);
                    if (hoveredHandle)
                    {
                        hovered = true;
                    }

                    if (hoveredHandle && MainTool.CheckClicked())
                    {
                        // toggle vehicle restrictions
                        //Log._Debug($"Setting vehicle restrictions of segment {segmentId}, lane idx {laneIndex}, {vehicleType.ToString()} to {!allowed}");
                        VehicleRestrictionsManager.Instance.ToggleAllowedType(segmentId, segmentInfo, laneIndex, laneId, laneInfo, vehicleType, !allowed);
                        stateUpdated = true;

                        if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
                        {
                            ApplyRestrictionsToAllSegments(sortedLaneIndex);
                        }
                    }

                    ++y;
                }

                ++x;
            }

            guiColor.a = 1f;
            GUI.color  = guiColor;

            return(hovered);
        }