/// <summary> /// The window for setting the defaullt speeds per road type /// </summary> /// <param name="num"></param> private void _guiDefaultsWindow(int num) { List <NetInfo> mainNetInfos = SpeedLimitManager.Instance.GetCustomizableNetInfos(); if (mainNetInfos == null || mainNetInfos.Count <= 0) { Log._Debug($"mainNetInfos={mainNetInfos?.Count}"); DragWindow(ref defaultsWindowRect); return; } bool updateRoadTex = false; if (currentInfoIndex < 0 || currentInfoIndex >= mainNetInfos.Count) { currentInfoIndex = 0; updateRoadTex = true; Log._Debug($"set currentInfoIndex to 0"); } NetInfo info = mainNetInfos[currentInfoIndex]; if (updateRoadTex) { UpdateRoadTex(info); } if (currentSpeedLimit.GameUnits < 0f) { currentSpeedLimit = new SpeedValue( SpeedLimitManager.Instance.GetCustomNetInfoSpeedLimit(info)); Log._Debug($"set currentSpeedLimit to {currentSpeedLimit}"); } // Log._Debug($"currentInfoIndex={currentInfoIndex} currentSpeedLimitIndex={currentSpeedLimitIndex}"); // Road type label GUILayout.BeginVertical(); GUILayout.Space(10); GUILayout.Label(Translation.GetString("Road_type") + ":"); GUILayout.EndVertical(); // switch between NetInfos GUILayout.BeginHorizontal(); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); if (GUILayout.Button("←", GUILayout.Width(50))) { currentInfoIndex = (currentInfoIndex + mainNetInfos.Count - 1) % mainNetInfos.Count; info = mainNetInfos[currentInfoIndex]; currentSpeedLimit = new SpeedValue( SpeedLimitManager.Instance.GetCustomNetInfoSpeedLimit(info)); UpdateRoadTex(info); } GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.FlexibleSpace(); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); // NetInfo thumbnail GUILayout.Box(RoadTexture, GUILayout.Height(GUI_SPEED_SIGN_SIZE)); GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.FlexibleSpace(); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); if (GUILayout.Button("→", GUILayout.Width(50))) { currentInfoIndex = (currentInfoIndex + 1) % mainNetInfos.Count; info = mainNetInfos[currentInfoIndex]; currentSpeedLimit = new SpeedValue( SpeedLimitManager.Instance.GetCustomNetInfoSpeedLimit(info)); UpdateRoadTex(info); } GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); var centeredTextStyle = new GUIStyle("label") { alignment = TextAnchor.MiddleCenter }; // NetInfo name GUILayout.Label(info.name, centeredTextStyle); // Default speed limit label GUILayout.BeginVertical(); GUILayout.Space(10); GUILayout.Label(Translation.GetString("Default_speed_limit") + ":"); GUILayout.EndVertical(); // switch between speed limits GUILayout.BeginHorizontal(); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); if (GUILayout.Button("←", GUILayout.Width(50))) { // currentSpeedLimit = (currentSpeedLimitIndex + // SpeedLimitManager.Instance.AvailableSpeedLimits.Count - 1) // % SpeedLimitManager.Instance.AvailableSpeedLimits.Count; currentSpeedLimit = GetPrevious(currentSpeedLimit); } GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.FlexibleSpace(); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); // speed limit sign GUILayout.Box(SpeedLimitTextures.GetSpeedLimitTexture(currentSpeedLimit), GUILayout.Width(GUI_SPEED_SIGN_SIZE), GUILayout.Height(GUI_SPEED_SIGN_SIZE)); GUILayout.Label(GlobalConfig.Instance.Main.DisplaySpeedLimitsMph ? Translation.GetString("Miles_per_hour") : Translation.GetString("Kilometers_per_hour")); GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.FlexibleSpace(); GUILayout.BeginVertical(); GUILayout.FlexibleSpace(); if (GUILayout.Button("→", GUILayout.Width(50))) { // currentSpeedLimitIndex = (currentSpeedLimitIndex + 1) % // SpeedLimitManager.Instance.AvailableSpeedLimits.Count; currentSpeedLimit = GetNext(currentSpeedLimit); } GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); // Save & Apply GUILayout.BeginVertical(); GUILayout.Space(10); GUILayout.BeginHorizontal(); // Close button. TODO: Make more visible or obey 'Esc' pressed or something GUILayout.FlexibleSpace(); if (GUILayout.Button("X", GUILayout.Width(80))) { defaultsWindowVisible = false; } GUILayout.FlexibleSpace(); if (GUILayout.Button(Translation.GetString("Save"), GUILayout.Width(70))) { SpeedLimitManager.Instance.FixCurrentSpeedLimits(info); SpeedLimitManager.Instance.SetCustomNetInfoSpeedLimit(info, currentSpeedLimit.GameUnits); } GUILayout.FlexibleSpace(); if (GUILayout.Button( Translation.GetString("Save") + " & " + Translation.GetString("Apply"), GUILayout.Width(160))) { SpeedLimitManager.Instance.SetCustomNetInfoSpeedLimit(info, currentSpeedLimit.GameUnits); SpeedLimitManager.Instance.ClearCurrentSpeedLimits(info); } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.EndVertical(); DragWindow(ref defaultsWindowRect); }
private void DrawSpeedLimitHandles(ushort segmentId, ref NetSegment segment, bool viewOnly, ref Vector3 camPos) { if (viewOnly && !Options.speedLimitsOverlay) { return; } Vector3 center = segment.m_bounds.center; NetManager netManager = Singleton <NetManager> .instance; SpeedValue speedLimitToSet = viewOnly ? new SpeedValue(-1f) : currentPaletteSpeedLimit; bool showPerLane = showLimitsPerLane; if (!viewOnly) { showPerLane = showLimitsPerLane ^ (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)); } // US signs are rectangular, all other are round float speedLimitSignVerticalScale = GetVerticalTextureScale(); if (showPerLane) { // show individual speed limit handle per lane int numLanes = TrafficManagerTool.GetSegmentNumVehicleLanes( segmentId, null, out int 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 * (((numLanes - 1) + numDirections) - 1) * f * xu); uint x = 0; 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; } } } var 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); } SpeedValue laneSpeedLimit = new SpeedValue( SpeedLimitManager.Instance.GetCustomSpeedLimit(laneId)); bool hoveredHandle = MainTool.DrawGenericOverlayGridTexture( SpeedLimitTextures.GetSpeedLimitTexture(laneSpeedLimit), camPos, zero, f, f, xu, yu, x, 0, speedLimitSignSize, speedLimitSignSize * speedLimitSignVerticalScale, !viewOnly); if (!viewOnly && !onlyMonorailLanes && ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Monorail) != VehicleInfo.VehicleType.None)) { Texture2D tex1 = RoadUI.VehicleInfoSignTextures[ LegacyExtVehicleType.ToNew(ExtVehicleType.PassengerTrain)]; MainTool.DrawStaticSquareOverlayGridTexture( tex1, camPos, zero, f, xu, yu, x, 1, speedLimitSignSize); } if (hoveredHandle) { } if (hoveredHandle && Input.GetMouseButton(0) && !IsCursorInPanel()) { SpeedLimitManager.Instance.SetSpeedLimit( segmentId, laneIndex, laneInfo, laneId, speedLimitToSet.GameUnits); if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) { int slIndexCopy = sortedLaneIndex; SegmentLaneTraverser.Traverse( segmentId, SegmentTraverser.TraverseDirection.AnyDirection, SegmentTraverser.TraverseSide.AnySide, SegmentLaneTraverser.LaneStopCriterion.LaneCount, SegmentTraverser.SegmentStopCriterion.Junction, SpeedLimitManager.LANE_TYPES, SpeedLimitManager.VEHICLE_TYPES, data => { if (data.SegVisitData.Initial) { return(true); } if (slIndexCopy != data.SortedLaneIndex) { return(true); } Constants.ServiceFactory.NetService.ProcessSegment( data.SegVisitData.CurSeg.segmentId, (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.GameUnits); return(true); }); return(true); }); } } ++x; } } else { // draw speedlimits over mean middle points of lane beziers if (!segmentCenterByDir.TryGetValue( segmentId, out Dictionary <NetInfo.Direction, Vector3> segCenter)) { segCenter = new Dictionary <NetInfo.Direction, Vector3>(); segmentCenterByDir.Add(segmentId, segCenter); TrafficManagerTool.CalculateSegmentCenterByDir( segmentId, segCenter, speedLimitSignSize * TrafficManagerTool.MAX_ZOOM); } foreach (KeyValuePair <NetInfo.Direction, Vector3> e in segCenter) { bool visible = MainTool.WorldToScreenPoint(e.Value, out Vector3 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; var boundingBox = new Rect(screenPos.x - (size / 2), screenPos.y - (size / 2), size, size * speedLimitSignVerticalScale); bool hoveredHandle = !viewOnly && TrafficManagerTool.IsMouseOver(boundingBox); guiColor.a = TrafficManagerTool.GetHandleAlpha(hoveredHandle); if (hoveredHandle) { // mouse hovering over sign } // Draw something right here, the road sign texture GUI.color = guiColor; SpeedValue displayLimit = new SpeedValue( SpeedLimitManager.Instance.GetCustomSpeedLimit(segmentId, e.Key)); Texture2D tex = SpeedLimitTextures.GetSpeedLimitTexture(displayLimit); GUI.DrawTexture(boundingBox, tex); 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, currentPaletteSpeedLimit.GameUnits); 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, data => { if (data.SegVisitData.Initial) { return(true); } bool reverse = data.SegVisitData.ViaStartNode == data.SegVisitData.ViaInitialStartNode; ushort otherSegmentId = data.SegVisitData.CurSeg.segmentId; NetInfo otherSegmentInfo = netManager.m_segments.m_buffer[otherSegmentId].Info; 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.GameUnits); } return(true); }); } } guiColor.a = 1f; GUI.color = guiColor; } } }