From dc98a93900dccd15079decf8db946b648ac767ba Mon Sep 17 00:00:00 2001 From: Craxy Date: Mon, 20 Nov 2017 19:48:23 +0100 Subject: [PATCH] Add option to remove all stop signs --- .../Behaviours/JunctionSettingsBehaviour.cs | 50 ++++++++-- src/ToggleTrafficLights/Mod.cs | 6 +- .../ToggleTrafficLights.csproj | 2 +- src/ToggleTrafficLights/Tools/StopSigns.cs | 92 +++++++++++++++++++ .../Utils/NetNodeHelper.cs | 4 +- 5 files changed, 143 insertions(+), 11 deletions(-) create mode 100644 src/ToggleTrafficLights/Tools/StopSigns.cs diff --git a/src/ToggleTrafficLights/Game/Behaviours/JunctionSettingsBehaviour.cs b/src/ToggleTrafficLights/Game/Behaviours/JunctionSettingsBehaviour.cs index daaf0ba..8affba8 100644 --- a/src/ToggleTrafficLights/Game/Behaviours/JunctionSettingsBehaviour.cs +++ b/src/ToggleTrafficLights/Game/Behaviours/JunctionSettingsBehaviour.cs @@ -66,6 +66,8 @@ private void AddButtons() // register click events for Traffic Lights icons UpdateIcons(_junctionSettings.Find("PanelLights"), Mode.Add); + // register click events for Stop Sign icons + UpdateIcons(_junctionSettings.Find("PanelStopSigns"), Mode.Add); // add buttons under PanelLights panel to change all lights (same behaviour as icons) AddToggleTrafficLightsButtons(_junctionSettings, PanelChangeAllLights); @@ -83,6 +85,8 @@ private void RemoveButtons() // unregister click events for Traffic Lights icons UpdateIcons(_junctionSettings.Find("PanelLights"), Mode.Remove); + // unregister click events for Stop Signs icons + UpdateIcons(_junctionSettings.Find("PanelStopSigns"), Mode.Remove); //move PanelLights to original position UpdateRelativePosition(_junctionSettings.Find("PanelLights"), _originalPanelLightsPosition); @@ -138,6 +142,10 @@ void UpdateClick(UIComponent comp, MouseEventHandler handler) sprite.tooltip = GetTooltip("Ctrl + Left Click: Remove traffic lights from all junctions."); UpdateClick(sprite, RemoveAllTrafficLightsOnControlPressed); break; + case "IconJunctionNoStopSign": + sprite.tooltip = GetTooltip("Ctrl + Left Click: Remove all stop signs."); + UpdateClick(sprite, RemoveAllStopSignsOnControlPressed); + break; default: break; } @@ -326,18 +334,18 @@ private void ResetLights(UIComponent _, UIMouseEventParameter evt) private const float MinTimeBetweenChanges = 0.5f; // in seconds private static void AddAllTrafficLightsOnControlPressed(UIComponent _, UIMouseEventParameter evt) - => HandleClick(evt, TrafficLights.ChangeMode.Add, true); + => HandleChangeTrafficLightsClick(evt, TrafficLights.ChangeMode.Add, true); private static void RemoveAllTrafficLightsOnControlPressed(UIComponent _, UIMouseEventParameter evt) - => HandleClick(evt, TrafficLights.ChangeMode.Remove, true); + => HandleChangeTrafficLightsClick(evt, TrafficLights.ChangeMode.Remove, true); private static void ResetAllTrafficLightsOnControlPressed(UIComponent _, UIMouseEventParameter evt) - => HandleClick(evt, TrafficLights.ChangeMode.Reset, true); + => HandleChangeTrafficLightsClick(evt, TrafficLights.ChangeMode.Reset, true); private static void AddAllTrafficLights(UIComponent _, UIMouseEventParameter evt) - => HandleClick(evt, TrafficLights.ChangeMode.Add, false); + => HandleChangeTrafficLightsClick(evt, TrafficLights.ChangeMode.Add, false); private static void RemoveAllTrafficLights(UIComponent _, UIMouseEventParameter evt) - => HandleClick(evt, TrafficLights.ChangeMode.Remove, false); + => HandleChangeTrafficLightsClick(evt, TrafficLights.ChangeMode.Remove, false); private static void ResetAllTrafficLights(UIComponent _, UIMouseEventParameter evt) - => HandleClick(evt, TrafficLights.ChangeMode.Reset, false); - private static void HandleClick(UIMouseEventParameter evt, TrafficLights.ChangeMode mode, bool requiresControl) + => HandleChangeTrafficLightsClick(evt, TrafficLights.ChangeMode.Reset, false); + private static void HandleChangeTrafficLightsClick(UIMouseEventParameter evt, TrafficLights.ChangeMode mode, bool requiresControl) { if (evt.buttons != UIMouseButton.Left) { @@ -365,6 +373,34 @@ private static void HandleClick(UIMouseEventParameter evt, TrafficLights.ChangeM // var stats = TrafficLights.ChangeAll(mode); //todo: handle stats? } + private static void RemoveAllStopSignsOnControlPressed(UIComponent _, UIMouseEventParameter evt) + => HandleChangeStopSignsClick(evt, StopSigns.ChangeMode.Remove, true); + private static void HandleChangeStopSignsClick(UIMouseEventParameter evt, StopSigns.ChangeMode mode, bool requiresControl) + { + if (evt.buttons != UIMouseButton.Left) + { + return; + } + if (requiresControl && !(Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))) + { + return; + } + + var currentTime = Time.time; + if (currentTime - _lastChangeTime >= MinTimeBetweenChanges) + { + _lastChangeTime = currentTime; + } + else + { + //not enough time passed + DebugLog.Info("Not enough time passed for another update"); + return; + } + + DebugLog.Info($"Change all intersections: {mode} all"); + StopSigns.ChangeAllFast(mode); + } private static void TimeChange(TrafficLights.ChangeMode mode) { diff --git a/src/ToggleTrafficLights/Mod.cs b/src/ToggleTrafficLights/Mod.cs index 4de8986..30fb1a1 100644 --- a/src/ToggleTrafficLights/Mod.cs +++ b/src/ToggleTrafficLights/Mod.cs @@ -30,7 +30,11 @@ static Mod() => Log.Info($"Loaded: {Assembly.GetExecutingAssembly().GetName()})"); public string Name - => "Toggle Traffic Lights"; + => "Toggle Traffic Lights" +#if DEBUG + + " (DEBUG)" +#endif + ; public string Description => "Remove or add traffic lights at junctions."; diff --git a/src/ToggleTrafficLights/ToggleTrafficLights.csproj b/src/ToggleTrafficLights/ToggleTrafficLights.csproj index c233689..947cdde 100644 --- a/src/ToggleTrafficLights/ToggleTrafficLights.csproj +++ b/src/ToggleTrafficLights/ToggleTrafficLights.csproj @@ -10,7 +10,7 @@ true - 0.11.0 + 0.12.0 $(Version) $(Version) Toggle Traffic Lights diff --git a/src/ToggleTrafficLights/Tools/StopSigns.cs b/src/ToggleTrafficLights/Tools/StopSigns.cs new file mode 100644 index 0000000..243f3f1 --- /dev/null +++ b/src/ToggleTrafficLights/Tools/StopSigns.cs @@ -0,0 +1,92 @@ +using System; +using ColossalFramework; +using Craxy.CitiesSkylines.ToggleTrafficLights.Utils; +using UnityEngine; + +namespace Craxy.CitiesSkylines.ToggleTrafficLights.Tools +{ + public static class StopSigns + { + // add is completely useless + // remove and reset are same -> = remove + public enum ChangeMode : byte + { + Remove, + Add, + Reset, + Toggle + } + + public static void ChangeAllFast(ChangeMode mode) + { + var netManager = Singleton.instance; + var nodes = netManager.m_nodes; + for (ushort i = 0; i < nodes.m_size; i++) + { + var node = nodes.m_buffer[i]; + ChangeFast(i, ref node, mode); + nodes.m_buffer[i] = node; + } + } + + public static void ChangeFast(ushort nodeId, ref NetNode node, ChangeMode mode) + { + if (!Node.IsValidIntersection(nodeId, ref node)) + { + return; + } + if (!Node.IsInsideBuildableArea(nodeId, ref node)) + { + return; + } + var ai = node.Info.m_netAI as RoadBaseAI; + if (ai == null) + { + return; + } + + var nm = Singleton.instance; + for(var index = 0; index < 8; index++) + { + var segment = node.GetSegment(index); + if(segment != 0) + { + var info = nm.m_segments.m_buffer[segment].Info; + if ((info.m_vehicleTypes & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None) + { + var flag3 = nm.m_segments.m_buffer[segment].m_startNode == nodeId; + var flag4 = (nm.m_segments.m_buffer[segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None; + if ((flag3 != flag4 ? (info.m_hasBackwardVehicleLanes ? 1 : 0) : (info.m_hasForwardVehicleLanes ? 1 : 0)) != 0) + { + var flags = !flag3 ? NetSegment.Flags.YieldEnd : NetSegment.Flags.YieldStart; + var sign = (nm.m_segments.m_buffer[segment].m_flags & flags) != NetSegment.Flags.None + ? NotificationEvent.Type.YieldOn + : NotificationEvent.Type.YieldOff; + + + var dir = nm.m_segments.m_buffer[segment].m_startNode != nodeId + ? NetSegment.Flags.YieldEnd + : NetSegment.Flags.YieldStart; + + switch(mode) + { + case ChangeMode.Add: + nm.m_segments.m_buffer[segment].m_flags |= dir; + break; + case ChangeMode.Reset: + case ChangeMode.Remove: + nm.m_segments.m_buffer[segment].m_flags &= ~dir; + break; + case ChangeMode.Toggle: + nm.m_segments.m_buffer[segment].m_flags ^= dir; + break; + default: + throw new ArgumentOutOfRangeException(nameof(mode), mode, null); + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/ToggleTrafficLights/Utils/NetNodeHelper.cs b/src/ToggleTrafficLights/Utils/NetNodeHelper.cs index b3f127d..1fd3554 100644 --- a/src/ToggleTrafficLights/Utils/NetNodeHelper.cs +++ b/src/ToggleTrafficLights/Utils/NetNodeHelper.cs @@ -230,10 +230,10 @@ public static void Change(ushort nodeId, ref NetNode node, ushort segmentIndex, break; case Mode.Reset: // default is no sign case Mode.Remove: - Singleton.instance.m_segments.m_buffer[segment].m_flags &= ~yieldDirection; + nm.m_segments.m_buffer[segment].m_flags &= ~yieldDirection; break; case Mode.Toggle: - Singleton.instance.m_segments.m_buffer[segment].m_flags ^= yieldDirection; + nm.m_segments.m_buffer[segment].m_flags ^= yieldDirection; break; default: throw new ArgumentOutOfRangeException(nameof(mode), mode, null);