diff --git a/TLM/TLM/Resources/TurnSigns/ButtonF.png b/TLM/TLM/Resources/TurnSigns/ButtonF.png new file mode 100644 index 000000000..89db7f75c Binary files /dev/null and b/TLM/TLM/Resources/TurnSigns/ButtonF.png differ diff --git a/TLM/TLM/Resources/TurnSigns/ButtonFGray.png b/TLM/TLM/Resources/TurnSigns/ButtonFGray.png new file mode 100644 index 000000000..bacc8b4d2 Binary files /dev/null and b/TLM/TLM/Resources/TurnSigns/ButtonFGray.png differ diff --git a/TLM/TLM/Resources/TurnSigns/ButtonL.png b/TLM/TLM/Resources/TurnSigns/ButtonL.png new file mode 100644 index 000000000..6da0d7df2 Binary files /dev/null and b/TLM/TLM/Resources/TurnSigns/ButtonL.png differ diff --git a/TLM/TLM/Resources/TurnSigns/ButtonLGray.png b/TLM/TLM/Resources/TurnSigns/ButtonLGray.png new file mode 100644 index 000000000..b8b9fe3b0 Binary files /dev/null and b/TLM/TLM/Resources/TurnSigns/ButtonLGray.png differ diff --git a/TLM/TLM/Resources/TurnSigns/ButtonR.png b/TLM/TLM/Resources/TurnSigns/ButtonR.png new file mode 100644 index 000000000..f229f1359 Binary files /dev/null and b/TLM/TLM/Resources/TurnSigns/ButtonR.png differ diff --git a/TLM/TLM/Resources/TurnSigns/ButtonRGray.png b/TLM/TLM/Resources/TurnSigns/ButtonRGray.png new file mode 100644 index 000000000..d630df15d Binary files /dev/null and b/TLM/TLM/Resources/TurnSigns/ButtonRGray.png differ diff --git a/TLM/TLM/TLM.csproj b/TLM/TLM/TLM.csproj index cb126ecb2..151e55a78 100644 --- a/TLM/TLM/TLM.csproj +++ b/TLM/TLM/TLM.csproj @@ -458,6 +458,16 @@ + + + + + + + + + + mkdir "$(LOCALAPPDATA)\Colossal Order\Cities_Skylines\Addons\Mods\$(TargetName)" diff --git a/TLM/TLM/UI/SubTools/LaneArrowTool.cs b/TLM/TLM/UI/SubTools/LaneArrowTool.cs index e9577dbd4..963c1eca4 100644 --- a/TLM/TLM/UI/SubTools/LaneArrowTool.cs +++ b/TLM/TLM/UI/SubTools/LaneArrowTool.cs @@ -19,6 +19,27 @@ namespace TrafficManager.UI.SubTools { public class LaneArrowTool : SubTool { + /// + /// Arrow sign bits are combined together to find index in turn arrow textures + /// located in TextureResources.TurnSignTextures. + /// + public const int SIGN_BIT_LEFT = 1; + public const int SIGN_BIT_FORWARD = 2; + public const int SIGN_BIT_RIGHT = 4; + + /// Size for white turn sign in the GUI + private const float BUTTON_GUI_SCALE = 50f; + + /// + /// Sum of widths of GUI elements for 1 lane. + /// NOTE this also adds spacing between lane columns. + /// + private const float LANE_GUI_WIDTH = BUTTON_GUI_SCALE * 1.33f + LANE_EXTRA_WIDTH; + private const float GUI_HEIGHT = BUTTON_GUI_SCALE * 1.66f; // label size + buttons + + /// Some spacing between lane GUI elements + private const float LANE_EXTRA_WIDTH = 36f; + private bool _cursorInSecondaryPanel; public LaneArrowTool(TrafficManagerTool mainTool) : base(mainTool) { @@ -30,15 +51,20 @@ public class LaneArrowTool : SubTool { } public override void OnPrimaryClickOverlay() { - if (HoveredNodeId == 0 || HoveredSegmentId == 0) return; + if (HoveredNodeId == 0 || HoveredSegmentId == 0) { + return; + } var netFlags = Singleton.instance.m_nodes.m_buffer[HoveredNodeId].m_flags; + if ((netFlags & NetNode.Flags.Junction) == NetNode.Flags.None) { + return; + } - if ((netFlags & NetNode.Flags.Junction) == NetNode.Flags.None) return; - - if (Singleton.instance.m_segments.m_buffer[HoveredSegmentId].m_startNode != HoveredNodeId && - Singleton.instance.m_segments.m_buffer[HoveredSegmentId].m_endNode != HoveredNodeId) + var hoveredSegment = Singleton.instance.m_segments.m_buffer[HoveredSegmentId]; + if (hoveredSegment.m_startNode != HoveredNodeId && + hoveredSegment.m_endNode != HoveredNodeId) { return; + } SelectedSegmentId = HoveredSegmentId; SelectedNodeId = HoveredNodeId; @@ -79,16 +105,19 @@ public class LaneArrowTool : SubTool { if (diff.magnitude > TrafficManagerTool.MaxOverlayDistance) return; // do not draw if too distant - int width = numLanes * 128; - var windowRect3 = new Rect(screenPos.x - width / 2, screenPos.y - 70, width, 50); - GUILayout.Window(250, windowRect3, _guiLaneChangeWindow, "", BorderlessStyle); - _cursorInSecondaryPanel = windowRect3.Contains(Event.current.mousePosition); + int width = numLanes * (int)LANE_GUI_WIDTH; + var proposedWindowRect = new Rect(screenPos.x - width / 2, screenPos.y - 70, width, GUI_HEIGHT); + var actualWindowRect = GUILayout.Window(250, proposedWindowRect, _guiLaneChangeWindow, "", BorderlessStyle); + _cursorInSecondaryPanel = actualWindowRect.Contains(Event.current.mousePosition); } public override void RenderOverlay(RenderManager.CameraInfo cameraInfo) { NetManager netManager = Singleton.instance; //Log._Debug($"LaneArrow Overlay: {HoveredNodeId} {HoveredSegmentId} {SelectedNodeId} {SelectedSegmentId}"); - if (!_cursorInSecondaryPanel && HoveredSegmentId != 0 && HoveredNodeId != 0 && (HoveredSegmentId != SelectedSegmentId || HoveredNodeId != SelectedNodeId)) { + if (!_cursorInSecondaryPanel + && HoveredSegmentId != 0 + && HoveredNodeId != 0 + && (HoveredSegmentId != SelectedSegmentId || HoveredNodeId != SelectedNodeId)) { var nodeFlags = netManager.m_nodes.m_buffer[HoveredNodeId].m_flags; if ((netManager.m_segments.m_buffer[HoveredSegmentId].m_startNode == HoveredNodeId || netManager.m_segments.m_buffer[HoveredSegmentId].m_endNode == HoveredNodeId) && (nodeFlags & NetNode.Flags.Junction) != NetNode.Flags.None) { @@ -118,42 +147,61 @@ public class LaneArrowTool : SubTool { for (var i = 0; i < laneList.Count; i++) { var flags = (NetLane.Flags)Singleton.instance.m_lanes.m_buffer[laneList[i].laneId].m_flags; - var style1 = new GUIStyle("button"); - var style2 = new GUIStyle("button") { - normal = { textColor = new Color32(255, 0, 0, 255) }, - hover = { textColor = new Color32(255, 0, 0, 255) }, - focused = { textColor = new Color32(255, 0, 0, 255) } - }; - var laneStyle = new GUIStyle { contentOffset = new Vector2(12f, 0f) }; - var laneTitleStyle = new GUIStyle { - contentOffset = new Vector2(36f, 2f), - normal = { textColor = new Color(1f, 1f, 1f) } - }; - GUILayout.BeginVertical(laneStyle); - GUILayout.Label(Translation.GetString("Lane") + " " + (i + 1), laneTitleStyle); + + //---------------------- + // Button group + //---------------------- GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); if (!Flags.applyLaneArrowFlags(laneList[i].laneId)) { Flags.removeLaneArrowFlags(laneList[i].laneId); } Flags.LaneArrowChangeResult res = Flags.LaneArrowChangeResult.Invalid; + bool buttonClicked = false; - if (GUILayout.Button("←", ((flags & NetLane.Flags.Left) == NetLane.Flags.Left ? style1 : style2), GUILayout.Width(35), GUILayout.Height(25))) { + var isLeft = (flags & NetLane.Flags.Left) == NetLane.Flags.Left; + var isForward = (flags & NetLane.Flags.Forward) == NetLane.Flags.Forward; + var isRight = (flags & NetLane.Flags.Right) == NetLane.Flags.Right; + + if (GUILayout.Button(isForward ? TextureResources.TurnButtonForward : TextureResources.TurnButtonForwardGray, + GUILayout.Width(BUTTON_GUI_SCALE * 1.33f), + GUILayout.Height(BUTTON_GUI_SCALE * 0.66f))) { buttonClicked = true; - LaneArrowManager.Instance.ToggleLaneArrows(laneList[i].laneId, startNode, Flags.LaneArrows.Left, out res); + LaneArrowManager.Instance.ToggleLaneArrows(laneList[i].laneId, startNode, + Flags.LaneArrows.Forward, out res); } - if (GUILayout.Button("↑", ((flags & NetLane.Flags.Forward) == NetLane.Flags.Forward ? style1 : style2), GUILayout.Width(25), GUILayout.Height(35))) { + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + + //---------------------- + // Arrow sign row + //---------------------- + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button(isLeft ? TextureResources.TurnButtonLeft : TextureResources.TurnButtonLeftGray, + GUILayout.Width(BUTTON_GUI_SCALE * 0.66f), + GUILayout.Height(BUTTON_GUI_SCALE))) { buttonClicked = true; - LaneArrowManager.Instance.ToggleLaneArrows(laneList[i].laneId, startNode, Flags.LaneArrows.Forward, out res); + LaneArrowManager.Instance.ToggleLaneArrows(laneList[i].laneId, startNode, + Flags.LaneArrows.Left, out res); } - if (GUILayout.Button("→", ((flags & NetLane.Flags.Right) == NetLane.Flags.Right ? style1 : style2), GUILayout.Width(35), GUILayout.Height(25))) { + if (GUILayout.Button(isRight ? TextureResources.TurnButtonRight : TextureResources.TurnButtonRightGray, + GUILayout.Width(BUTTON_GUI_SCALE * 0.66f), + GUILayout.Height(BUTTON_GUI_SCALE))) { buttonClicked = true; - LaneArrowManager.Instance.ToggleLaneArrows(laneList[i].laneId, startNode, Flags.LaneArrows.Right, out res); + LaneArrowManager.Instance.ToggleLaneArrows(laneList[i].laneId, startNode, + Flags.LaneArrows.Right, out res); } + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + //---------------------- + // Button click handling + //---------------------- if (buttonClicked) { switch (res) { case Flags.LaneArrowChangeResult.Invalid: @@ -169,7 +217,6 @@ public class LaneArrowTool : SubTool { } } - GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.EndVertical(); } diff --git a/TLM/TLM/UI/TextureResources.cs b/TLM/TLM/UI/TextureResources.cs index 60c2d49b0..ad9085be9 100644 --- a/TLM/TLM/UI/TextureResources.cs +++ b/TLM/TLM/UI/TextureResources.cs @@ -8,6 +8,7 @@ using TrafficManager.Manager.Impl; using TrafficManager.Traffic; using TrafficManager.UI; +using TrafficManager.UI.SubTools; using TrafficManager.Util; using UnityEngine; using static TrafficManager.Traffic.Data.PrioritySegment; @@ -42,6 +43,14 @@ public class TextureResources public static readonly Texture2D PedestrianModeAutomaticTexture2D; public static readonly Texture2D PedestrianModeManualTexture2D; public static readonly IDictionary PrioritySignTextures; + + public static readonly Texture2D TurnButtonLeft; + public static readonly Texture2D TurnButtonRight; + public static readonly Texture2D TurnButtonForward; + public static readonly Texture2D TurnButtonLeftGray; + public static readonly Texture2D TurnButtonRightGray; + public static readonly Texture2D TurnButtonForwardGray; + public static readonly Texture2D SignRemoveTexture2D; public static readonly Texture2D ClockPlayTexture2D; public static readonly Texture2D ClockPauseTexture2D; @@ -123,7 +132,14 @@ static TextureResources() PrioritySignTextures[PriorityType.Main] = LoadDllResource("sign_priority.png", 200, 200); PrioritySignTextures[PriorityType.Stop] = LoadDllResource("sign_stop.png", 200, 200); PrioritySignTextures[PriorityType.Yield] = LoadDllResource("sign_yield.png", 200, 200); - + + TurnButtonLeft = LoadDllResource("TurnSigns.ButtonL.png", 80, 127); + TurnButtonRight = LoadDllResource("TurnSigns.ButtonR.png", 80, 127); + TurnButtonForward = LoadDllResource("TurnSigns.ButtonF.png", 62, 62); + TurnButtonLeftGray = LoadDllResource("TurnSigns.ButtonLGray.png", 80, 127); + TurnButtonRightGray = LoadDllResource("TurnSigns.ButtonRGray.png", 80, 127); + TurnButtonForwardGray = LoadDllResource("TurnSigns.ButtonFGray.png", 62, 62); + // delete priority sign SignRemoveTexture2D = LoadDllResource("remove_signs.png", 256, 256); @@ -264,5 +280,5 @@ static byte[] ReadToEnd(Stream stream) stream.Position = originalPosition; } } - } + } } \ No newline at end of file