public bool SetSegmentLights(ushort nodeId, ushort segmentId, ICustomSegmentLights lights) { bool?startNode = Services.NetService.IsStartNode(segmentId, nodeId); if (startNode == null) { return(false); } CustomSegment customSegment = customSegments_[segmentId]; if (customSegment == null) { customSegment = new CustomSegment(); customSegments_[segmentId] = customSegment; } if ((bool)startNode) { customSegment.StartNodeLights = lights; } else { customSegment.EndNodeLights = lights; } return(true); }
public void SetLightMode(ushort segmentId, bool startNode, ExtVehicleType vehicleType, LightMode mode) { ICustomSegmentLights liveLights = GetSegmentLights(segmentId, startNode); if (liveLights == null) { Log.Warning( $"CustomSegmentLightsManager.SetLightMode({segmentId}, {startNode}, " + $"{vehicleType}, {mode}): Could not retrieve segment lights."); return; } ICustomSegmentLight liveLight = liveLights.GetCustomLight(vehicleType); if (liveLight == null) { Log.Error( $"CustomSegmentLightsManager.SetLightMode: Cannot change light mode on seg. " + $"{segmentId} @ {startNode} for vehicle type {vehicleType} to {mode}: Vehicle light not found"); return; } liveLight.CurrentMode = mode; }
public bool ApplyLightModes(ushort segmentId, bool startNode, ICustomSegmentLights otherLights) { ICustomSegmentLights sourceLights = GetSegmentLights(segmentId, startNode); if (sourceLights == null) { Log.Warning( $"CustomSegmentLightsManager.ApplyLightModes({segmentId}, {startNode}, " + $"{otherLights}): Could not retrieve segment lights."); return(false); } foreach (KeyValuePair <ExtVehicleType, ICustomSegmentLight> e in sourceLights.CustomLights) { ExtVehicleType vehicleType = e.Key; ICustomSegmentLight targetLight = e.Value; if (otherLights.CustomLights.TryGetValue(vehicleType, out ICustomSegmentLight sourceLight)) { targetLight.CurrentMode = sourceLight.CurrentMode; } } return(true); }
private bool IsPedestrianLightHovered(Rect myRect3, int segmentId, bool hoveredSegment, ICustomSegmentLights segmentLights) { if (!myRect3.Contains(Event.current.mousePosition)) { return(hoveredSegment); } if (segmentLights.PedestrianLightState == null) { return(false); } hoveredButton[0] = segmentId; hoveredButton[1] = 2; if (!MainTool.CheckClicked()) { return(true); } if (!segmentLights.ManualPedestrianMode) { segmentLights.ManualPedestrianMode = true; } else { segmentLights.ChangeLightPedestrian(); } return(true); }
public bool SetSegmentLights(ushort nodeId, ushort segmentId, ICustomSegmentLights lights) { SegmentEndGeometry endGeo = SegmentGeometry.Get(segmentId)?.GetEnd(nodeId); if (endGeo == null) { return(false); } CustomSegment customSegment = CustomSegments[segmentId]; if (customSegment == null) { customSegment = new CustomSegment(); CustomSegments[segmentId] = customSegment; } if (endGeo.StartNode) { customSegment.StartNodeLights = lights; } else { customSegment.EndNodeLights = lights; } return(true); }
private bool RenderCounter(int segmentId, Vector3 screenPos, float modeWidth, float modeHeight, float zoom, ICustomSegmentLights segmentLights, bool hoveredSegment) { SetAlpha(segmentId, 0); var myRectCounter = new Rect(screenPos.x - modeWidth / 2, screenPos.y - modeHeight / 2 - 6f * zoom, modeWidth, modeHeight); GUI.DrawTexture(myRectCounter, TextureResources.LightCounterTexture2D); var counterSize = 20f * zoom; var counter = segmentLights.LastChange(); var myRectCounterNum = new Rect(screenPos.x - counterSize + 15f * zoom + (counter >= 10 ? -5 * zoom : 0f), screenPos.y - counterSize + 11f * zoom, counterSize, counterSize); _counterStyle.fontSize = (int)(18f * zoom); _counterStyle.normal.textColor = new Color(1f, 1f, 1f); GUI.Label(myRectCounterNum, counter.ToString(), _counterStyle); if (!myRectCounter.Contains(Event.current.mousePosition)) { return(hoveredSegment); } _hoveredButton[0] = segmentId; _hoveredButton[1] = 0; return(true); }
/// <summary> /// Configures traffic light for and for all lane types at input segmentId, nodeId, and step. /// </summary> /// <param name="step"></param> /// <param name="nodeId"></param> /// <param name="segmentId"></param> /// <param name="m">Determines which directions are green</param> private static void SetupHelper(ITimedTrafficLightsStep step, ushort nodeId, ushort segmentId, GreenDir m) { bool startNode = (bool)netService.IsStartNode(segmentId, nodeId); //get step data for side seg ICustomSegmentLights liveSegmentLights = customTrafficLightsManager.GetSegmentLights(segmentId, startNode); //for each lane type foreach (ExtVehicleType vehicleType in liveSegmentLights.VehicleTypes) { //set light mode ICustomSegmentLight liveSegmentLight = liveSegmentLights.GetCustomLight(vehicleType); liveSegmentLight.CurrentMode = LightMode.All; TimedLight(nodeId).ChangeLightMode( segmentId, vehicleType, liveSegmentLight.CurrentMode); // set light states var green = RoadBaseAI.TrafficLightState.Green; var red = RoadBaseAI.TrafficLightState.Red; switch (m) { case GreenDir.AllRed: liveSegmentLight.SetStates(red, red, red); break; case GreenDir.AllGreen: liveSegmentLight.SetStates(green, green, green); break; case GreenDir.ShortOnly: { // calculate directions ref ExtSegmentEnd segEnd = ref segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, nodeId)]; ref NetNode node = ref Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId]; segEndMan.CalculateOutgoingLeftStraightRightSegments(ref segEnd, ref node, out bool bLeft, out bool bForward, out bool bRight); bool bShort = RHT ? bRight : bLeft; bool bLong = RHT ? bLeft : bRight; if (bShort) { SetStates(liveSegmentLight, red, red, green); } else if (bLong) { // go forward instead of short SetStates(liveSegmentLight, green, red, red); } else { Debug.LogAssertion("Unreachable code."); liveSegmentLight.SetStates(green, green, green); } break; }
AddSegmentLights(ushort segmentId, bool startNode, RoadBaseAI.TrafficLightState lightState = RoadBaseAI.TrafficLightState.Red) { #if DEBUG Log._Trace($"CustomTrafficLights.AddSegmentLights: Adding segment light: {segmentId} @ startNode={startNode}"); #endif if (!Services.NetService.IsSegmentValid(segmentId)) { return(null); } CustomSegment customSegment = customSegments_[segmentId]; if (customSegment == null) { customSegment = new CustomSegment(); customSegments_[segmentId] = customSegment; } else { ICustomSegmentLights existingLights = startNode ? customSegment.StartNodeLights : customSegment.EndNodeLights; if (existingLights != null) { existingLights.SetLights(lightState); return(existingLights); } } if (startNode) { customSegment.StartNodeLights = new CustomSegmentLights( this, segmentId, startNode, false); customSegment.StartNodeLights.SetLights(lightState); return(customSegment.StartNodeLights); } else { customSegment.EndNodeLights = new CustomSegmentLights( this, segmentId, startNode, false); customSegment.EndNodeLights.SetLights(lightState); return(customSegment.EndNodeLights); } }
/// <summary> /// Adds custom traffic lights at the specified node and segment. /// Light stats are set to the given light state, or to "Red" if no light state is given. /// </summary> /// <param name="segmentId"></param> /// <param name="startNode"></param> /// <param name="lightState">(optional) light state to set</param> public ICustomSegmentLights AddSegmentLights(ushort segmentId, bool startNode, RoadBaseAI.TrafficLightState lightState = RoadBaseAI.TrafficLightState.Red) { #if DEBUG Log._Debug($"CustomTrafficLights.AddSegmentLights: Adding segment light: {segmentId} @ startNode={startNode}"); #endif SegmentGeometry segGeometry = SegmentGeometry.Get(segmentId); if (segGeometry == null) { Log.Error($"CustomTrafficLightsManager.AddSegmentLights: Segment {segmentId} is invalid."); return(null); } SegmentEndGeometry endGeometry = segGeometry.GetEnd(startNode); if (endGeometry == null) { Log.Error($"CustomTrafficLightsManager.AddSegmentLights: Segment {segmentId} is not connected to a node @ start {startNode}"); return(null); } CustomSegment customSegment = CustomSegments[segmentId]; if (customSegment == null) { customSegment = new CustomSegment(); CustomSegments[segmentId] = customSegment; } else { ICustomSegmentLights existingLights = startNode ? customSegment.StartNodeLights : customSegment.EndNodeLights; if (existingLights != null) { existingLights.SetLights(lightState); return(existingLights); } } SubscribeToSegmentGeometry(segmentId); if (startNode) { customSegment.StartNodeLights = new CustomSegmentLights(this, segmentId, startNode, false); customSegment.StartNodeLights.SetLights(lightState); return(customSegment.StartNodeLights); } else { customSegment.EndNodeLights = new CustomSegmentLights(this, segmentId, startNode, false); customSegment.EndNodeLights.SetLights(lightState); return(customSegment.EndNodeLights); } }
private bool RenderManualPedestrianLightSwitch(float zoom, int segmentId, Vector3 screenPos, float lightWidth, ICustomSegmentLights segmentLights, bool hoveredSegment) { if (segmentLights.PedestrianLightState == null) { return(false); } Color guiColor = GUI.color; float manualPedestrianWidth = 36f * zoom; float manualPedestrianHeight = 35f * zoom; guiColor.a = TrafficManagerTool.GetHandleAlpha( hoveredButton[0] == segmentId && (hoveredButton[1] == 1 || hoveredButton[1] == 2)); GUI.color = guiColor; var myRect2 = new Rect( screenPos.x - (manualPedestrianWidth / 2) - lightWidth + (5f * zoom), screenPos.y - (manualPedestrianHeight / 2) - (9f * zoom), manualPedestrianWidth, manualPedestrianHeight); GUI.DrawTexture( myRect2, segmentLights.ManualPedestrianMode ? TrafficLightTextures.PedestrianModeManual : TrafficLightTextures.PedestrianModeAutomatic); if (!myRect2.Contains(Event.current.mousePosition)) { return(hoveredSegment); } hoveredButton[0] = segmentId; hoveredButton[1] = 1; if (!MainTool.CheckClicked()) { return(true); } segmentLights.ManualPedestrianMode = !segmentLights.ManualPedestrianMode; return(true); }
private static void GetCustomTrafficLightState(ushort nodeId, ushort fromSegmentId, byte fromLaneIndex, ushort toSegmentId, out RoadBaseAI.TrafficLightState vehicleLightState, out RoadBaseAI.TrafficLightState pedestrianLightState, ref TrafficLightSimulation nodeSim) { SegmentGeometry segmentGeometry = SegmentGeometry.Get(fromSegmentId, false); if (segmentGeometry == null) { //Log.Error(string.Format("GetTrafficLightState: No geometry information @ node {0}, segment {1}.", nodeId, fromSegmentId)); vehicleLightState = RoadBaseAI.TrafficLightState.Green; pedestrianLightState = RoadBaseAI.TrafficLightState.Green; return; } bool startNode = segmentGeometry.StartNodeId() == nodeId; ICustomSegmentLights segmentLights = CustomSegmentLightsManager.Instance.GetSegmentLights(fromSegmentId, startNode, false, RoadBaseAI.TrafficLightState.Red); if (segmentLights != null) { pedestrianLightState = (segmentLights.PedestrianLightState.HasValue ? segmentLights.PedestrianLightState.Value : RoadBaseAI.TrafficLightState.Green); } else { pedestrianLightState = RoadBaseAI.TrafficLightState.Green; } ICustomSegmentLight customSegmentLight = (segmentLights == null) ? null : segmentLights.GetCustomLight(fromLaneIndex); if (segmentLights == null || customSegmentLight == null) { vehicleLightState = RoadBaseAI.TrafficLightState.Green; return; } if (toSegmentId == fromSegmentId) { vehicleLightState = (Constants.ServiceFactory.SimulationService.LeftHandDrive ? customSegmentLight.LightRight : customSegmentLight.LightLeft); return; } if (segmentGeometry.IsLeftSegment(toSegmentId, startNode)) { vehicleLightState = customSegmentLight.LightLeft; return; } if (segmentGeometry.IsRightSegment(toSegmentId, startNode)) { vehicleLightState = customSegmentLight.LightRight; return; } vehicleLightState = customSegmentLight.LightMain; }
public void SetLights(ICustomSegmentLights otherLights) { foreach (KeyValuePair <ExtVehicleType, ICustomSegmentLight> e in otherLights.CustomLights) { ICustomSegmentLight ourLight = null; if (!CustomLights.TryGetValue(e.Key, out ourLight)) { continue; } ourLight.SetStates(e.Value.LightMain, e.Value.LightLeft, e.Value.LightRight, false); //ourLight.LightPedestrian = e.Value.LightPedestrian; } InternalPedestrianLightState = otherLights.InternalPedestrianLightState; manualPedestrianMode = otherLights.ManualPedestrianMode; AutoPedestrianLightState = otherLights.AutoPedestrianLightState; }
private bool RenderManualPedestrianLightSwitch(float zoom, int segmentId, Vector3 screenPos, float lightWidth, ICustomSegmentLights segmentLights, bool hoveredSegment) { if (segmentLights.PedestrianLightState == null) { return(false); } var guiColor = GUI.color; var manualPedestrianWidth = 36f * zoom; var manualPedestrianHeight = 35f * zoom; guiColor.a = MainTool.GetHandleAlpha(_hoveredButton[0] == segmentId && (_hoveredButton[1] == 1 || _hoveredButton[1] == 2)); GUI.color = guiColor; var myRect2 = new Rect(screenPos.x - manualPedestrianWidth / 2 - lightWidth + 5f * zoom, screenPos.y - manualPedestrianHeight / 2 - 9f * zoom, manualPedestrianWidth, manualPedestrianHeight); GUI.DrawTexture(myRect2, segmentLights.ManualPedestrianMode ? TextureResources.PedestrianModeManualTexture2D : TextureResources.PedestrianModeAutomaticTexture2D); if (!myRect2.Contains(Event.current.mousePosition)) { return(hoveredSegment); } _hoveredButton[0] = segmentId; _hoveredButton[1] = 1; if (!MainTool.CheckClicked()) { return(true); } segmentLights.ManualPedestrianMode = !segmentLights.ManualPedestrianMode; return(true); }
public bool CustomCheckTrafficLights(ushort node, ushort segment) { var netManager = Singleton <NetManager> .instance; var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; var num = (uint)((node << 8) / 32768); var stepWaitTime = currentFrameIndex - num & 255u; // NON-STOCK CODE START // var nodeSimulation = Options.timedLightsEnabled ? TrafficLightSimulationManager.Instance.GetNodeSimulation(node) : null; RoadBaseAI.TrafficLightState pedestrianLightState; bool startNode = netManager.m_segments.m_buffer[segment].m_startNode == node; ICustomSegmentLights lights = null; if (nodeSimulation != null && nodeSimulation.IsSimulationActive()) { lights = CustomSegmentLightsManager.Instance.GetSegmentLights(segment, startNode, false); } if (lights == null) { // NON-STOCK CODE END // RoadBaseAI.TrafficLightState vehicleLightState; bool vehicles; bool pedestrians; RoadBaseAI.GetTrafficLightState(node, ref netManager.m_segments.m_buffer[segment], currentFrameIndex - num, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians); if ((pedestrianLightState == RoadBaseAI.TrafficLightState.GreenToRed || pedestrianLightState == RoadBaseAI.TrafficLightState.Red) && !pedestrians && stepWaitTime >= 196u) { RoadBaseAI.SetTrafficLightState(node, ref netManager.m_segments.m_buffer[segment], currentFrameIndex - num, vehicleLightState, pedestrianLightState, vehicles, true); return(true); } // NON-STOCK CODE START // } else { if (lights.InvalidPedestrianLight) { pedestrianLightState = RoadBaseAI.TrafficLightState.Green; } else { pedestrianLightState = (RoadBaseAI.TrafficLightState)lights.PedestrianLightState; } } // NON-STOCK CODE END // switch (pedestrianLightState) { case RoadBaseAI.TrafficLightState.RedToGreen: if (stepWaitTime < 60u) { return(false); } break; case RoadBaseAI.TrafficLightState.Red: case RoadBaseAI.TrafficLightState.GreenToRed: return(false); } return(true); }
public void CalculateAutoPedestrianLightState(bool propagate = true) { #if DEBUGTTL bool debug = GlobalConfig.Instance.Debug.Switches[7] && GlobalConfig.Instance.Debug.NodeId == NodeId; #endif #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Calculating pedestrian light state of seg. {SegmentId} @ node {NodeId}"); } #endif SegmentEndGeometry segmentEndGeometry = SegmentGeometry.Get(SegmentId)?.GetEnd(StartNode); if (segmentEndGeometry == null) { Log._Debug($"Could not get SegmentEndGeometry for segment {SegmentId} @ {NodeId}."); AutoPedestrianLightState = RoadBaseAI.TrafficLightState.Green; return; } ushort nodeId = segmentEndGeometry.NodeId(); if (nodeId != NodeId) { Log.Warning($"CustomSegmentLights.CalculateAutoPedestrianLightState: Node id mismatch! segment end node is {nodeId} but we are node {NodeId}. segmentEndGeometry={segmentEndGeometry} this={this}"); return; } if (propagate) { foreach (ushort otherSegmentId in segmentEndGeometry.ConnectedSegments) { if (otherSegmentId == 0) { continue; } ICustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId); if (otherLights == null) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Expected other (propagate) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}"); } #endif continue; } otherLights.CalculateAutoPedestrianLightState(false); } } if (IsAnyGreen()) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Any green at seg. {SegmentId} @ {NodeId}"); } #endif AutoPedestrianLightState = RoadBaseAI.TrafficLightState.Red; return; } #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Querying incoming segments at seg. {SegmentId} @ {NodeId}"); } #endif RoadBaseAI.TrafficLightState autoPedestrianLightState = RoadBaseAI.TrafficLightState.Green; ItemClass prevConnectionClass = null; Constants.ServiceFactory.NetService.ProcessSegment(SegmentId, delegate(ushort prevSegId, ref NetSegment segment) { prevConnectionClass = segment.Info.GetConnectionClass(); return(true); }); if (!segmentEndGeometry.IncomingOneWay) { // query straight segments foreach (ushort otherSegmentId in segmentEndGeometry.IncomingStraightSegments) { if (otherSegmentId == 0) { continue; } #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Checking incoming straight segment {otherSegmentId} at seg. {SegmentId} @ {NodeId}"); } #endif ICustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId); if (otherLights == null) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Expected other (straight) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}"); } #endif continue; } SegmentGeometry otherGeo = SegmentGeometry.Get(otherSegmentId); if (otherGeo == null) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Expected other (straight) segment geometry at segment {otherSegmentId} @ {NodeId} (startNode={otherLights.StartNode}) but there was none. Original segment id: {SegmentId}"); } #endif continue; } ItemClass nextConnectionClass = null; Constants.ServiceFactory.NetService.ProcessSegment(otherSegmentId, delegate(ushort otherSegId, ref NetSegment segment) { nextConnectionClass = segment.Info.GetConnectionClass(); return(true); }); if (nextConnectionClass.m_service != prevConnectionClass.m_service) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Other (straight) segment {otherSegmentId} @ {NodeId} has different connection service than segment {SegmentId} ({nextConnectionClass.m_service} vs. {prevConnectionClass.m_service}). Ignoring traffic light state."); } #endif continue; } if (!otherLights.IsAllMainRed()) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Not all main red at {otherSegmentId} at seg. {SegmentId} @ {NodeId}"); } #endif autoPedestrianLightState = RoadBaseAI.TrafficLightState.Red; break; } } // query left/right segments if (autoPedestrianLightState == RoadBaseAI.TrafficLightState.Green) { bool lhd = Constants.ServiceFactory.SimulationService.LeftHandDrive; foreach (ushort otherSegmentId in lhd ? segmentEndGeometry.IncomingLeftSegments : segmentEndGeometry.IncomingRightSegments) { if (otherSegmentId == 0) { continue; } #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Checking left/right segment {otherSegmentId} at seg. {SegmentId} @ {NodeId}"); } #endif ICustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId); if (otherLights == null) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Expected other (left/right) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}"); } #endif continue; } ItemClass nextConnectionClass = null; Constants.ServiceFactory.NetService.ProcessSegment(otherSegmentId, delegate(ushort otherSegId, ref NetSegment segment) { nextConnectionClass = segment.Info.GetConnectionClass(); return(true); }); if (nextConnectionClass.m_service != prevConnectionClass.m_service) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Other (left/right) segment {otherSegmentId} @ {NodeId} has different connection service than segment {SegmentId} ({nextConnectionClass.m_service} vs. {prevConnectionClass.m_service}). Ignoring traffic light state."); } #endif continue; } if ((lhd && !otherLights.IsAllRightRed()) || (!lhd && !otherLights.IsAllLeftRed())) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Not all left red at {otherSegmentId} at seg. {SegmentId} @ {NodeId}"); } #endif autoPedestrianLightState = RoadBaseAI.TrafficLightState.Red; break; } } } } AutoPedestrianLightState = autoPedestrianLightState; #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Calculated AutoPedestrianLightState for segment {SegmentId} @ {NodeId}: {AutoPedestrianLightState}"); } #endif }
public bool CustomCheckTrafficLights(ushort nodeId, ushort segmentId) { #if DEBUGTTL bool debug = GlobalConfig.Instance.Debug.Switches[7] && GlobalConfig.Instance.Debug.NodeId == nodeId; #endif var netManager = Singleton <NetManager> .instance; var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; var num = (uint)(((int)nodeId << 8) / 32768); var stepWaitTime = currentFrameIndex - num & 255u; // NON-STOCK CODE START // bool customSim = false; #if BENCHMARK using (var bm = new Benchmark(null, "GetNodeSimulation")) { #endif customSim = Options.timedLightsEnabled && TrafficLightSimulationManager.Instance.HasActiveSimulation(nodeId); #if BENCHMARK } #endif RoadBaseAI.TrafficLightState pedestrianLightState; bool startNode = netManager.m_segments.m_buffer[segmentId].m_startNode == nodeId; ICustomSegmentLights lights = null; #if BENCHMARK using (var bm = new Benchmark(null, "GetSegmentLights")) { #endif if (customSim) { lights = CustomSegmentLightsManager.Instance.GetSegmentLights(segmentId, startNode, false); } #if BENCHMARK } #endif if (lights == null) { // NON-STOCK CODE END // RoadBaseAI.TrafficLightState vehicleLightState; bool vehicles; bool pedestrians; #if DEBUGTTL if (debug) { Log._Debug($"CustomHumanAI.CustomCheckTrafficLights({nodeId}, {segmentId}): No custom simulation!"); } #endif RoadBaseAI.GetTrafficLightState(nodeId, ref netManager.m_segments.m_buffer[segmentId], currentFrameIndex - num, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians); if (pedestrianLightState == RoadBaseAI.TrafficLightState.GreenToRed || pedestrianLightState == RoadBaseAI.TrafficLightState.Red) { if (!pedestrians && stepWaitTime >= 196u) { RoadBaseAI.SetTrafficLightState(nodeId, ref netManager.m_segments.m_buffer[segmentId], currentFrameIndex - num, vehicleLightState, pedestrianLightState, vehicles, true); } return(false); } // NON-STOCK CODE START // } else { if (lights.InvalidPedestrianLight) { pedestrianLightState = RoadBaseAI.TrafficLightState.Green; } else { pedestrianLightState = (RoadBaseAI.TrafficLightState)lights.PedestrianLightState; } #if DEBUGTTL if (debug) { Log._Debug($"CustomHumanAI.CustomCheckTrafficLights({nodeId}, {segmentId}): Custom simulation! pedestrianLightState={pedestrianLightState}, lights.InvalidPedestrianLight={lights.InvalidPedestrianLight}"); } #endif } // NON-STOCK CODE END // switch (pedestrianLightState) { case RoadBaseAI.TrafficLightState.RedToGreen: if (stepWaitTime < 60u) { return(false); } break; case RoadBaseAI.TrafficLightState.Red: case RoadBaseAI.TrafficLightState.GreenToRed: return(false); } return(true); }
public List <Configuration.TimedTrafficLights> SaveData(ref bool success) { var ret = new List <Configuration.TimedTrafficLights>(); for (uint nodeId = 0; nodeId < NetManager.MAX_NODE_COUNT; ++nodeId) { try { if (!TrafficLightSimulations[nodeId].IsTimedLight()) { continue; } #if DEBUGSAVE Log._Debug($"Going to save timed light at node {nodeId}."); #endif ITimedTrafficLights timedNode = TrafficLightSimulations[nodeId].timedLight; timedNode.OnGeometryUpdate(); var cnfTimedLights = new Configuration.TimedTrafficLights { nodeId = timedNode.NodeId, nodeGroup = new List <ushort>(timedNode.NodeGroup), started = timedNode.IsStarted() }; ret.Add(cnfTimedLights); int stepIndex = timedNode.CurrentStep; if (timedNode.IsStarted() && timedNode.GetStep(timedNode.CurrentStep).IsInEndTransition()) { // if in end transition save the next step stepIndex = (stepIndex + 1) % timedNode.NumSteps(); } cnfTimedLights.currentStep = stepIndex; cnfTimedLights.timedSteps = new List <Configuration.TimedTrafficLightsStep>(); for (var j = 0; j < timedNode.NumSteps(); j++) { #if DEBUGSAVE Log._Debug($"Saving timed light step {j} at node {nodeId}."); #endif ITimedTrafficLightsStep timedStep = timedNode.GetStep(j); var cnfTimedStep = new Configuration.TimedTrafficLightsStep { minTime = timedStep.MinTime, maxTime = timedStep.MaxTime, changeMetric = (int)timedStep.ChangeMetric, waitFlowBalance = timedStep.WaitFlowBalance, segmentLights = new Dictionary <ushort, Configuration.CustomSegmentLights>() }; cnfTimedLights.timedSteps.Add(cnfTimedStep); foreach (KeyValuePair <ushort, ICustomSegmentLights> e in timedStep.CustomSegmentLights) { #if DEBUGSAVE Log._Debug($"Saving timed light step {j}, segment {e.Key} at node {nodeId}."); #endif ICustomSegmentLights segLights = e.Value; ushort lightsNodeId = segLights.NodeId; var cnfSegLights = new Configuration.CustomSegmentLights { nodeId = lightsNodeId, // TODO not needed segmentId = segLights.SegmentId, // TODO not needed customLights = new Dictionary <ExtVehicleType, Configuration.CustomSegmentLight>(), pedestrianLightState = segLights.PedestrianLightState, manualPedestrianMode = segLights.ManualPedestrianMode }; if (lightsNodeId == 0 || lightsNodeId != timedNode.NodeId) { Log.Warning( "Inconsistency detected: Timed traffic light @ node " + $"{timedNode.NodeId} contains custom traffic lights for the invalid " + $"segment ({segLights.SegmentId}) at step {j}: nId={lightsNodeId}"); continue; } cnfTimedStep.segmentLights.Add(e.Key, cnfSegLights); #if DEBUGSAVE Log._Debug($"Saving pedestrian light @ seg. {e.Key}, step {j}: " + $"{cnfSegLights.pedestrianLightState} {cnfSegLights.manualPedestrianMode}"); #endif foreach (KeyValuePair <API.Traffic.Enums.ExtVehicleType, ICustomSegmentLight> e2 in segLights.CustomLights) { #if DEBUGSAVE Log._Debug($"Saving timed light step {j}, segment {e.Key}, vehicleType " + $"{e2.Key} at node {nodeId}."); #endif ICustomSegmentLight segLight = e2.Value; var cnfSegLight = new Configuration.CustomSegmentLight { nodeId = lightsNodeId, // TODO not needed segmentId = segLights.SegmentId, // TODO not needed currentMode = (int)segLight.CurrentMode, leftLight = segLight.LightLeft, mainLight = segLight.LightMain, rightLight = segLight.LightRight }; cnfSegLights.customLights.Add( LegacyExtVehicleType.ToOld(e2.Key), cnfSegLight); } } } } catch (Exception e) { Log.Error( $"Exception occurred while saving timed traffic light @ {nodeId}: {e}"); success = false; } } return(ret); }
public bool LoadData(List <Configuration.TimedTrafficLights> data) { bool success = true; Log.Info($"Loading {data.Count} timed traffic lights (new method)"); var nodesWithSimulation = new HashSet <ushort>(); foreach (Configuration.TimedTrafficLights cnfTimedLights in data) { nodesWithSimulation.Add(cnfTimedLights.nodeId); } var masterNodeIdBySlaveNodeId = new Dictionary <ushort, ushort>(); var nodeGroupByMasterNodeId = new Dictionary <ushort, List <ushort> >(); foreach (Configuration.TimedTrafficLights cnfTimedLights in data) { try { // TODO most of this should not be necessary at all if the classes around TimedTrafficLights class were properly designed // enforce uniqueness of node ids List <ushort> currentNodeGroup = cnfTimedLights.nodeGroup.Distinct().ToList(); if (!currentNodeGroup.Contains(cnfTimedLights.nodeId)) { currentNodeGroup.Add(cnfTimedLights.nodeId); } // remove any nodes that are not configured to have a simulation currentNodeGroup = new List <ushort>( currentNodeGroup.Intersect(nodesWithSimulation)); // remove invalid nodes from the group; find if any of the nodes in the group is already a master node ushort masterNodeId = 0; int foundMasterNodes = 0; for (int i = 0; i < currentNodeGroup.Count;) { ushort nodeId = currentNodeGroup[i]; if (!Services.NetService.IsNodeValid(currentNodeGroup[i])) { currentNodeGroup.RemoveAt(i); continue; } if (nodeGroupByMasterNodeId.ContainsKey(nodeId)) { // this is a known master node if (foundMasterNodes > 0) { // we already found another master node. ignore this node. currentNodeGroup.RemoveAt(i); continue; } // we found the first master node masterNodeId = nodeId; ++foundMasterNodes; } ++i; } if (masterNodeId == 0) { // no master node defined yet, set the first node as a master node masterNodeId = currentNodeGroup[0]; } // ensure the master node is the first node in the list (TimedTrafficLights // depends on this at the moment...) currentNodeGroup.Remove(masterNodeId); currentNodeGroup.Insert(0, masterNodeId); // update the saved node group and master-slave info nodeGroupByMasterNodeId[masterNodeId] = currentNodeGroup; foreach (ushort nodeId in currentNodeGroup) { masterNodeIdBySlaveNodeId[nodeId] = masterNodeId; } } catch (Exception e) { Log.WarningFormat( "Error building timed traffic light group for TimedNode {0} (NodeGroup: {1}): {2}", cnfTimedLights.nodeId, string.Join(", ", cnfTimedLights.nodeGroup.Select(x => x.ToString()).ToArray()), e); success = false; } } foreach (Configuration.TimedTrafficLights cnfTimedLights in data) { try { if (!masterNodeIdBySlaveNodeId.ContainsKey(cnfTimedLights.nodeId)) { continue; } ushort masterNodeId = masterNodeIdBySlaveNodeId[cnfTimedLights.nodeId]; List <ushort> nodeGroup = nodeGroupByMasterNodeId[masterNodeId]; #if DEBUGLOAD Log._Debug($"Adding timed light at node {cnfTimedLights.nodeId}. NodeGroup: " + $"{string.Join(", ", nodeGroup.Select(x => x.ToString()).ToArray())}"); #endif SetUpTimedTrafficLight(cnfTimedLights.nodeId, nodeGroup); int j = 0; foreach (Configuration.TimedTrafficLightsStep cnfTimedStep in cnfTimedLights.timedSteps) { #if DEBUGLOAD Log._Debug($"Loading timed step {j} at node {cnfTimedLights.nodeId}"); #endif ITimedTrafficLightsStep step = TrafficLightSimulations[cnfTimedLights.nodeId].timedLight.AddStep( cnfTimedStep.minTime, cnfTimedStep.maxTime, (StepChangeMetric)cnfTimedStep.changeMetric, cnfTimedStep.waitFlowBalance); foreach (KeyValuePair <ushort, Configuration.CustomSegmentLights> e in cnfTimedStep.segmentLights) { if (!Services.NetService.IsSegmentValid(e.Key)) { continue; } e.Value.nodeId = cnfTimedLights.nodeId; #if DEBUGLOAD Log._Debug($"Loading timed step {j}, segment {e.Key} at node {cnfTimedLights.nodeId}"); #endif ICustomSegmentLights lights = null; if (!step.CustomSegmentLights.TryGetValue(e.Key, out lights)) { #if DEBUGLOAD Log._Debug($"No segment lights found at timed step {j} for segment " + $"{e.Key}, node {cnfTimedLights.nodeId}"); #endif continue; } Configuration.CustomSegmentLights cnfLights = e.Value; #if DEBUGLOAD Log._Debug($"Loading pedestrian light @ seg. {e.Key}, step {j}: " + $"{cnfLights.pedestrianLightState} {cnfLights.manualPedestrianMode}"); #endif lights.ManualPedestrianMode = cnfLights.manualPedestrianMode; lights.PedestrianLightState = cnfLights.pedestrianLightState; bool first = true; // v1.10.2 transitional code foreach (KeyValuePair <ExtVehicleType, Configuration.CustomSegmentLight> e2 in cnfLights.customLights) { #if DEBUGLOAD Log._Debug($"Loading timed step {j}, segment {e.Key}, vehicleType " + $"{e2.Key} at node {cnfTimedLights.nodeId}"); #endif if (!lights.CustomLights.TryGetValue( LegacyExtVehicleType.ToNew(e2.Key), out ICustomSegmentLight light)) { #if DEBUGLOAD Log._Debug($"No segment light found for timed step {j}, segment " + $"{e.Key}, vehicleType {e2.Key} at node {cnfTimedLights.nodeId}"); #endif // v1.10.2 transitional code START if (first) { first = false; if (!lights.CustomLights.TryGetValue( CustomSegmentLights .DEFAULT_MAIN_VEHICLETYPE, out light)) { #if DEBUGLOAD Log._Debug($"No segment light found for timed step {j}, " + $"segment {e.Key}, DEFAULT vehicleType {CustomSegmentLights.DEFAULT_MAIN_VEHICLETYPE} " + $"at node {cnfTimedLights.nodeId}"); #endif continue; } } else { // v1.10.2 transitional code END continue; // v1.10.2 transitional code START } // v1.10.2 transitional code END } Configuration.CustomSegmentLight cnfLight = e2.Value; light.InternalCurrentMode = (LightMode)cnfLight.currentMode; // TODO improve & remove light.SetStates( cnfLight.mainLight, cnfLight.leftLight, cnfLight.rightLight, false); } } ++j; } } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning($"Error loading data from TimedNode (new method): {e}"); success = false; } } foreach (Configuration.TimedTrafficLights cnfTimedLights in data) { try { ITimedTrafficLights timedNode = TrafficLightSimulations[cnfTimedLights.nodeId].timedLight; timedNode.Housekeeping(); if (cnfTimedLights.started) { timedNode.Start(cnfTimedLights.currentStep); } } catch (Exception e) { Log.Warning($"Error starting timed light @ {cnfTimedLights.nodeId}: {e}"); success = false; } } return(success); }
// TODO this should be optimized protected void GetCustomTrafficLightState( #if DEBUG ushort vehicleId, ref Vehicle vehicleData, #endif ushort nodeId, ushort fromSegmentId, byte fromLaneIndex, ushort toSegmentId, out TrafficLightState vehicleLightState, out TrafficLightState pedestrianLightState, ref TrafficLightSimulation nodeSim) { // get responsible traffic light // Log._Debug($"GetTrafficLightState: Getting custom light for vehicle {vehicleId} @ // node {nodeId}, segment {fromSegmentId}, lane {fromLaneIndex}."); // SegmentGeometry geometry = SegmentGeometry.Get(fromSegmentId); // if (geometry == null) { // Log.Error($"GetTrafficLightState: No geometry information @ node {nodeId}, segment {fromSegmentId}."); // vehicleLightState = TrafficLightState.Green; // pedestrianLightState = TrafficLightState.Green; // return; // } // determine node position at `fromSegment` (start/end) // bool isStartNode = geometry.StartNodeId == nodeId; bool?isStartNode = Services.NetService.IsStartNode(fromSegmentId, nodeId); if (isStartNode == null) { Log.Error($"GetTrafficLightState: Invalid node {nodeId} for segment {fromSegmentId}."); vehicleLightState = TrafficLightState.Green; pedestrianLightState = TrafficLightState.Green; return; } ICustomSegmentLights lights = CustomSegmentLightsManager.Instance.GetSegmentLights( fromSegmentId, (bool)isStartNode, false); if (lights != null) { // get traffic lights state for pedestrians pedestrianLightState = lights.PedestrianLightState ?? TrafficLightState.Green; } else { pedestrianLightState = TrafficLightState.Green; Log._Debug($"GetTrafficLightState: No pedestrian light @ node {nodeId}, " + $"segment {fromSegmentId} found."); } ICustomSegmentLight light = lights == null ? null : lights.GetCustomLight(fromLaneIndex); if (lights == null || light == null) { // Log.Warning($"GetTrafficLightState: No custom light for vehicle {vehicleId} @ node // {nodeId}, segment {fromSegmentId}, lane {fromLaneIndex} found. lights null? // {lights == null} light null? {light == null}"); vehicleLightState = TrafficLightState.Green; return; } // get traffic light state from responsible traffic light vehicleLightState = light.GetLightState(toSegmentId); #if DEBUG // Log._Debug($"GetTrafficLightState: Getting light for vehicle {vehicleId} @ node {nodeId}, // segment {fromSegmentId}, lane {fromLaneIndex}. vehicleLightState={vehicleLightState}, // pedestrianLightState={pedestrianLightState}"); #endif }
public List <Configuration.TimedTrafficLights> SaveData(ref bool success) { List <Configuration.TimedTrafficLights> ret = new List <Configuration.TimedTrafficLights>(); for (uint nodeId = 0; nodeId < NetManager.MAX_NODE_COUNT; ++nodeId) { try { ITrafficLightSimulation sim = GetNodeSimulation((ushort)nodeId); if (sim == null || !sim.IsTimedLight()) { continue; } Log._Debug($"Going to save timed light at node {nodeId}."); var timedNode = sim.TimedLight; timedNode.OnGeometryUpdate(); Configuration.TimedTrafficLights cnfTimedLights = new Configuration.TimedTrafficLights(); ret.Add(cnfTimedLights); cnfTimedLights.nodeId = timedNode.NodeId; cnfTimedLights.nodeGroup = new List <ushort>(timedNode.NodeGroup); cnfTimedLights.started = timedNode.IsStarted(); int stepIndex = timedNode.CurrentStep; if (timedNode.IsStarted() && timedNode.GetStep(timedNode.CurrentStep).IsInEndTransition()) { // if in end transition save the next step stepIndex = (stepIndex + 1) % timedNode.NumSteps(); } cnfTimedLights.currentStep = stepIndex; cnfTimedLights.timedSteps = new List <Configuration.TimedTrafficLightsStep>(); for (var j = 0; j < timedNode.NumSteps(); j++) { Log._Debug($"Saving timed light step {j} at node {nodeId}."); ITimedTrafficLightsStep timedStep = timedNode.GetStep(j); Configuration.TimedTrafficLightsStep cnfTimedStep = new Configuration.TimedTrafficLightsStep(); cnfTimedLights.timedSteps.Add(cnfTimedStep); cnfTimedStep.minTime = timedStep.MinTime; cnfTimedStep.maxTime = timedStep.MaxTime; cnfTimedStep.changeMetric = (int)timedStep.ChangeMetric; cnfTimedStep.waitFlowBalance = timedStep.WaitFlowBalance; cnfTimedStep.segmentLights = new Dictionary <ushort, Configuration.CustomSegmentLights>(); foreach (KeyValuePair <ushort, ICustomSegmentLights> e in timedStep.CustomSegmentLights) { Log._Debug($"Saving timed light step {j}, segment {e.Key} at node {nodeId}."); ICustomSegmentLights segLights = e.Value; Configuration.CustomSegmentLights cnfSegLights = new Configuration.CustomSegmentLights(); ushort lightsNodeId = segLights.NodeId; if (lightsNodeId == 0 || lightsNodeId != timedNode.NodeId) { Log.Warning($"Inconsistency detected: Timed traffic light @ node {timedNode.NodeId} contains custom traffic lights for the invalid segment ({segLights.SegmentId}) at step {j}: nId={lightsNodeId}"); continue; } cnfSegLights.nodeId = lightsNodeId; // TODO not needed cnfSegLights.segmentId = segLights.SegmentId; // TODO not needed cnfSegLights.customLights = new Dictionary <ExtVehicleType, Configuration.CustomSegmentLight>(); cnfSegLights.pedestrianLightState = segLights.PedestrianLightState; cnfSegLights.manualPedestrianMode = segLights.ManualPedestrianMode; cnfTimedStep.segmentLights.Add(e.Key, cnfSegLights); Log._Debug($"Saving pedestrian light @ seg. {e.Key}, step {j}: {cnfSegLights.pedestrianLightState} {cnfSegLights.manualPedestrianMode}"); foreach (KeyValuePair <ExtVehicleType, ICustomSegmentLight> e2 in segLights.CustomLights) { Log._Debug($"Saving timed light step {j}, segment {e.Key}, vehicleType {e2.Key} at node {nodeId}."); ICustomSegmentLight segLight = e2.Value; Configuration.CustomSegmentLight cnfSegLight = new Configuration.CustomSegmentLight(); cnfSegLights.customLights.Add(e2.Key, cnfSegLight); cnfSegLight.nodeId = lightsNodeId; // TODO not needed cnfSegLight.segmentId = segLights.SegmentId; // TODO not needed cnfSegLight.currentMode = (int)segLight.CurrentMode; cnfSegLight.leftLight = segLight.LightLeft; cnfSegLight.mainLight = segLight.LightMain; cnfSegLight.rightLight = segLight.LightRight; } } } } catch (Exception e) { Log.Error($"Exception occurred while saving timed traffic light @ {nodeId}: {e.ToString()}"); success = false; } } return(ret); }
public bool CustomCheckTrafficLights(ushort nodeId, ushort segmentId) { #if DEBUG bool logTimedLights = DebugSwitch.TimedTrafficLights.Get() && DebugSettings.NodeId == nodeId; #endif NetManager netManager = Singleton <NetManager> .instance; uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; uint simGroup = (uint)nodeId >> 7; uint stepWaitTime = currentFrameIndex - simGroup & 255u; // NON-STOCK CODE START bool customSim = Options.timedLightsEnabled && TrafficLightSimulationManager.Instance.HasActiveSimulation(nodeId); RoadBaseAI.TrafficLightState pedestrianLightState; NetSegment[] segmentsBuffer = netManager.m_segments.m_buffer; bool startNode = segmentsBuffer[segmentId].m_startNode == nodeId; ICustomSegmentLights lights = null; using (var bm = Benchmark.MaybeCreateBenchmark(null, "GetSegmentLights")) { if (customSim) { lights = CustomSegmentLightsManager.Instance.GetSegmentLights( segmentId, startNode, false); } } if (lights == null) { // NON-STOCK CODE END #if DEBUG Log._DebugIf( logTimedLights, () => $"CustomHumanAI.CustomCheckTrafficLights({nodeId}, " + $"{segmentId}): No custom simulation!"); #endif RoadBaseAI.GetTrafficLightState( nodeId, ref segmentsBuffer[segmentId], currentFrameIndex - simGroup, out RoadBaseAI.TrafficLightState vehicleLightState, out pedestrianLightState, out bool vehicles, out bool pedestrians); if (pedestrianLightState == RoadBaseAI.TrafficLightState.GreenToRed || pedestrianLightState == RoadBaseAI.TrafficLightState.Red) { if (!pedestrians && stepWaitTime >= 196u) { RoadBaseAI.SetTrafficLightState( nodeId, ref segmentsBuffer[segmentId], currentFrameIndex - simGroup, vehicleLightState, pedestrianLightState, vehicles, true); } return(false); } // NON-STOCK CODE START } else { if (lights.InvalidPedestrianLight) { pedestrianLightState = RoadBaseAI.TrafficLightState.Green; } else { pedestrianLightState = (RoadBaseAI.TrafficLightState)lights.PedestrianLightState; } #if DEBUG Log._DebugIf( logTimedLights, () => $"CustomHumanAI.CustomCheckTrafficLights({nodeId}, {segmentId}): " + $"Custom simulation! pedestrianLightState={pedestrianLightState}, " + $"lights.InvalidPedestrianLight={lights.InvalidPedestrianLight}"); #endif } // NON-STOCK CODE END switch (pedestrianLightState) { case RoadBaseAI.TrafficLightState.RedToGreen: if (stepWaitTime < 60u) { return(false); } break; case RoadBaseAI.TrafficLightState.Red: case RoadBaseAI.TrafficLightState.GreenToRed: return(false); } return(true); }
public void OnUpdate(NodeGeometry nodeGeometry) { #if DEBUG Log._Debug($"TrafficLightSimulation: OnUpdate @ node {NodeId} ({nodeGeometry.NodeId})"); #endif if (!IsManualLight() && !IsTimedLight()) { return; } if (!nodeGeometry.IsValid()) { // node has become invalid. Remove manual/timed traffic light and destroy custom lights Constants.ManagerFactory.TrafficLightSimulationManager.RemoveNodeFromSimulation(NodeId, false, false); return; } if (!Flags.mayHaveTrafficLight(NodeId)) { Log._Debug($"Housekeeping: Node {NodeId} has traffic light simulation but must not have a traffic light!"); Constants.ManagerFactory.TrafficLightSimulationManager.RemoveNodeFromSimulation(NodeId, false, true); return; } ICustomSegmentLightsManager customTrafficLightsManager = Constants.ManagerFactory.CustomSegmentLightsManager; foreach (SegmentEndGeometry end in nodeGeometry.SegmentEndGeometries) { if (end == null) { continue; } #if DEBUG Log._Debug($"TrafficLightSimulation: OnUpdate @ node {NodeId}: Adding live traffic lights to segment {end.SegmentId}"); #endif // add custom lights /*if (!customTrafficLightsManager.IsSegmentLight(end.SegmentId, end.StartNode)) { * customTrafficLightsManager.AddSegmentLights(end.SegmentId, end.StartNode); * }*/ // housekeep timed light ICustomSegmentLights lights = customTrafficLightsManager.GetSegmentLights(end.SegmentId, end.StartNode); if (lights == null) { Log.Warning($"TrafficLightSimulation.OnUpdate() @ node {NodeId}: Could not retrieve live segment lights for segment {end.SegmentId} @ start {end.StartNode}."); continue; } lights.Housekeeping(true, true); } // ensure there is a physical traffic light Constants.ServiceFactory.NetService.ProcessNode(NodeId, delegate(ushort nodeId, ref NetNode node) { Constants.ManagerFactory.TrafficLightManager.AddTrafficLight(NodeId, ref node); return(true); }); TimedLight?.OnGeometryUpdate(); TimedLight?.Housekeeping(); }
public override void OnToolGUI(Event e) { IExtSegmentManager segMan = Constants.ManagerFactory.ExtSegmentManager; IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager; var hoveredSegment = false; if (SelectedNodeId != 0) { CustomSegmentLightsManager customTrafficLightsManager = CustomSegmentLightsManager.Instance; TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; JunctionRestrictionsManager junctionRestrictionsManager = JunctionRestrictionsManager.Instance; if (!tlsMan.HasManualSimulation(SelectedNodeId)) { return; } tlsMan.TrafficLightSimulations[SelectedNodeId].Housekeeping(); // TODO check // if (Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode].CountSegments() == 2) { // _guiManualTrafficLightsCrosswalk( // ref Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode]); // return; // } NetNode[] nodesBuffer = Singleton <NetManager> .instance.m_nodes.m_buffer; NetSegment[] segmentsBuffer = Singleton <NetManager> .instance.m_segments.m_buffer; for (int i = 0; i < 8; ++i) { ushort segmentId = nodesBuffer[SelectedNodeId].GetSegment(i); if (segmentId == 0) { continue; } bool startNode = (bool)Constants.ServiceFactory.NetService.IsStartNode( segmentId, SelectedNodeId); Vector3 position = CalculateNodePositionForSegment( nodesBuffer[SelectedNodeId], ref segmentsBuffer[segmentId]); ICustomSegmentLights segmentLights = customTrafficLightsManager.GetSegmentLights(segmentId, startNode, false); if (segmentLights == null) { continue; } bool showPedLight = segmentLights.PedestrianLightState != null && junctionRestrictionsManager.IsPedestrianCrossingAllowed( segmentLights.SegmentId, segmentLights.StartNode); bool visible = MainTool.WorldToScreenPoint(position, out Vector3 screenPos); if (!visible) { continue; } Vector3 diff = position - Camera.main.transform.position; float zoom = 1.0f / diff.magnitude * 100f; // original / 2.5 float lightWidth = 41f * zoom; float lightHeight = 97f * zoom; float pedestrianWidth = 36f * zoom; float pedestrianHeight = 61f * zoom; // SWITCH MODE BUTTON float modeWidth = 41f * zoom; float modeHeight = 38f * zoom; Color guiColor = GUI.color; if (showPedLight) { // pedestrian light // SWITCH MANUAL PEDESTRIAN LIGHT BUTTON hoveredSegment = RenderManualPedestrianLightSwitch( zoom, segmentId, screenPos, lightWidth, segmentLights, hoveredSegment); // SWITCH PEDESTRIAN LIGHT guiColor.a = TrafficManagerTool.GetHandleAlpha( hoveredButton[0] == segmentId && hoveredButton[1] == 2 && segmentLights.ManualPedestrianMode); GUI.color = guiColor; var myRect3 = new Rect( screenPos.x - pedestrianWidth / 2 - lightWidth + 5f * zoom, screenPos.y - pedestrianHeight / 2 + 22f * zoom, pedestrianWidth, pedestrianHeight); switch (segmentLights.PedestrianLightState) { case RoadBaseAI.TrafficLightState.Green: { GUI.DrawTexture( myRect3, TrafficLightTextures.PedestrianGreenLight); break; } // also: case RoadBaseAI.TrafficLightState.Red: default: { GUI.DrawTexture( myRect3, TrafficLightTextures.PedestrianRedLight); break; } } hoveredSegment = IsPedestrianLightHovered( myRect3, segmentId, hoveredSegment, segmentLights); } int lightOffset = -1; foreach (ExtVehicleType vehicleType in segmentLights.VehicleTypes) { ++lightOffset; ICustomSegmentLight segmentLight = segmentLights.GetCustomLight(vehicleType); Vector3 offsetScreenPos = screenPos; offsetScreenPos.y -= (lightHeight + 10f * zoom) * lightOffset; SetAlpha(segmentId, -1); var myRect1 = new Rect( offsetScreenPos.x - modeWidth / 2, offsetScreenPos.y - modeHeight / 2 + modeHeight - 7f * zoom, modeWidth, modeHeight); GUI.DrawTexture(myRect1, TrafficLightTextures.LightMode); hoveredSegment = GetHoveredSegment( myRect1, segmentId, hoveredSegment, segmentLight); // COUNTER hoveredSegment = RenderCounter( segmentId, offsetScreenPos, modeWidth, modeHeight, zoom, segmentLights, hoveredSegment); if (vehicleType != ExtVehicleType.None) { // Info sign float infoWidth = 56.125f * zoom; float infoHeight = 51.375f * zoom; int numInfos = 0; for (int k = 0; k < TrafficManagerTool.InfoSignsToDisplay.Length; ++k) { if ((TrafficManagerTool.InfoSignsToDisplay[k] & vehicleType) == ExtVehicleType.None) { continue; } var infoRect = new Rect( offsetScreenPos.x + modeWidth / 2f + (7f * zoom * (float)(numInfos + 1)) + (infoWidth * (float)numInfos), offsetScreenPos.y - (infoHeight / 2f), infoWidth, infoHeight); guiColor.a = TrafficManagerTool.GetHandleAlpha(false); GUI.DrawTexture( infoRect, RoadUITextures.VehicleInfoSignTextures[TrafficManagerTool.InfoSignsToDisplay[k]]); ++numInfos; } } ExtSegment seg = segMan.ExtSegments[segmentId]; ExtSegmentEnd segEnd = segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, startNode)]; if (seg.oneWay && segEnd.outgoing) { continue; } segEndMan.CalculateOutgoingLeftStraightRightSegments( ref segEnd, ref nodesBuffer[segmentId], out bool hasLeftSegment, out bool hasForwardSegment, out bool hasRightSegment); switch (segmentLight.CurrentMode) { case LightMode.Simple: { hoveredSegment = SimpleManualSegmentLightMode( segmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment); break; } case LightMode.SingleLeft: { hoveredSegment = LeftForwardRManualSegmentLightMode( hasLeftSegment, segmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment, hasForwardSegment, hasRightSegment); break; } case LightMode.SingleRight: { hoveredSegment = RightForwardLSegmentLightMode( segmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, hasForwardSegment, hasLeftSegment, segmentLight, hasRightSegment, hoveredSegment); break; } default: { // left arrow light if (hasLeftSegment) { hoveredSegment = LeftArrowLightMode( segmentId, lightWidth, hasRightSegment, hasForwardSegment, offsetScreenPos, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment); } // forward arrow light if (hasForwardSegment) { hoveredSegment = ForwardArrowLightMode( segmentId, lightWidth, hasRightSegment, offsetScreenPos, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment); } // right arrow light if (hasRightSegment) { hoveredSegment = RightArrowLightMode( segmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment); } break; } } // end switch } // end foreach all vehicle type } // end for all 8 segments } // end if a node is selected if (hoveredSegment) { return; } hoveredButton[0] = 0; hoveredButton[1] = 0; }
public void CalculateAutoPedestrianLightState(ref NetNode node, bool propagate = true) { #if DEBUGTTL bool debug = DebugSwitch.TimedTrafficLights.Get() && DebugSettings.NodeId == NodeId; #endif #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Calculating pedestrian light state of seg. {SegmentId} @ node {NodeId}"); } #endif IExtSegmentManager segMan = Constants.ManagerFactory.ExtSegmentManager; IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager; ExtSegment seg = segMan.ExtSegments[SegmentId]; ExtSegmentEnd segEnd = segEndMan.ExtSegmentEnds[segEndMan.GetIndex(SegmentId, StartNode)]; ushort nodeId = segEnd.nodeId; if (nodeId != NodeId) { Log.Warning($"CustomSegmentLights.CalculateAutoPedestrianLightState: Node id mismatch! segment end node is {nodeId} but we are node {NodeId}. segEnd={segEnd} this={this}"); return; } if (propagate) { for (int i = 0; i < 8; ++i) { ushort otherSegmentId = node.GetSegment(i); if (otherSegmentId == 0 || otherSegmentId == SegmentId) { continue; } ICustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId); if (otherLights == null) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Expected other (propagate) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}"); } #endif continue; } otherLights.CalculateAutoPedestrianLightState(ref node, false); } } if (IsAnyGreen()) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Any green at seg. {SegmentId} @ {NodeId}"); } #endif AutoPedestrianLightState = RoadBaseAI.TrafficLightState.Red; return; } #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Querying incoming segments at seg. {SegmentId} @ {NodeId}"); } #endif ItemClass prevConnectionClass = null; Constants.ServiceFactory.NetService.ProcessSegment(SegmentId, delegate(ushort prevSegId, ref NetSegment segment) { prevConnectionClass = segment.Info.GetConnectionClass(); return(true); }); RoadBaseAI.TrafficLightState autoPedestrianLightState = RoadBaseAI.TrafficLightState.Green; bool lhd = Constants.ServiceFactory.SimulationService.LeftHandDrive; if (!(segEnd.incoming && seg.oneWay)) { for (int i = 0; i < 8; ++i) { ushort otherSegmentId = node.GetSegment(i); if (otherSegmentId == 0 || otherSegmentId == SegmentId) { continue; } //ExtSegment otherSeg = segMan.ExtSegments[otherSegmentId]; if (!segEndMan.ExtSegmentEnds[segEndMan.GetIndex(otherSegmentId, (bool)Constants.ServiceFactory.NetService.IsStartNode(otherSegmentId, NodeId))].incoming) { continue; } #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Checking incoming straight segment {otherSegmentId} at seg. {SegmentId} @ {NodeId}"); } #endif ICustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId); if (otherLights == null) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Expected other (straight) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}"); } #endif continue; } ItemClass nextConnectionClass = null; Constants.ServiceFactory.NetService.ProcessSegment(otherSegmentId, delegate(ushort otherSegId, ref NetSegment segment) { nextConnectionClass = segment.Info.GetConnectionClass(); return(true); }); if (nextConnectionClass.m_service != prevConnectionClass.m_service) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Other (straight) segment {otherSegmentId} @ {NodeId} has different connection service than segment {SegmentId} ({nextConnectionClass.m_service} vs. {prevConnectionClass.m_service}). Ignoring traffic light state."); } #endif continue; } ArrowDirection dir = segEndMan.GetDirection(ref segEnd, otherSegmentId); if (dir == ArrowDirection.Forward) { if (!otherLights.IsAllMainRed()) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Not all main red at {otherSegmentId} at seg. {SegmentId} @ {NodeId}"); } #endif autoPedestrianLightState = RoadBaseAI.TrafficLightState.Red; break; } } else if ((dir == ArrowDirection.Left && lhd) || (dir == ArrowDirection.Right && !lhd)) { if ((lhd && !otherLights.IsAllRightRed()) || (!lhd && !otherLights.IsAllLeftRed())) { #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Not all left red at {otherSegmentId} at seg. {SegmentId} @ {NodeId}"); } #endif autoPedestrianLightState = RoadBaseAI.TrafficLightState.Red; break; } } } } AutoPedestrianLightState = autoPedestrianLightState; #if DEBUGTTL if (debug) { Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Calculated AutoPedestrianLightState for segment {SegmentId} @ {NodeId}: {AutoPedestrianLightState}"); } #endif }