/// <summary> /// Performs a Depth-First traversal over the cached segment geometry structure. At each traversed segment, the given `visitor` is notified. It then can update the current `state`. /// </summary> /// <param name="initialSegmentGeometry">Specifies the segment at which the traversal should start.</param> /// <param name="nextNodeIsStartNode">Specifies if the next node to traverse is the start node of the initial segment.</param> /// <param name="direction">Specifies if traffic should be able to flow towards the initial segment (Incoming) or should be able to flow from the initial segment (Outgoing) or in both directions (Both).</param> /// <param name="maximumDepth">Specifies the maximum depth to explore. At a depth of 0, no segment will be traversed (event the initial segment will be omitted).</param> /// <param name="visitor">Specifies the stateful visitor that should be notified as soon as a traversable segment (which has not been traversed before) is found.</param> public static void Traverse(ushort initialSegmentId, TraverseDirection direction, TraverseSide side, SegmentStopCriterion stopCrit, SegmentVisitor visitor) { ExtSegment initialSeg = Constants.ManagerFactory.ExtSegmentManager.ExtSegments[initialSegmentId]; if (!initialSeg.valid) { return; } //Log._Debug($"SegmentTraverser: Traversing initial segment {initialSegmentId}"); if (visitor(new SegmentVisitData(ref initialSeg, ref initialSeg, false, false, true))) { HashSet <ushort> visitedSegmentIds = new HashSet <ushort>(); visitedSegmentIds.Add(initialSegmentId); IExtSegmentEndManager extSegEndMan = Constants.ManagerFactory.ExtSegmentEndManager; ushort startNodeId = Constants.ServiceFactory.NetService.GetSegmentNodeId(initialSegmentId, true); Constants.ServiceFactory.NetService.ProcessNode(startNodeId, delegate(ushort nId, ref NetNode node) { TraverseRec(ref initialSeg, ref extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(initialSegmentId, true)], ref node, true, direction, side, stopCrit, visitor, visitedSegmentIds); return(true); }); ushort endNodeId = Constants.ServiceFactory.NetService.GetSegmentNodeId(initialSegmentId, false); Constants.ServiceFactory.NetService.ProcessNode(endNodeId, delegate(ushort nId, ref NetNode node) { TraverseRec(ref initialSeg, ref extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(initialSegmentId, false)], ref node, false, direction, side, stopCrit, visitor, visitedSegmentIds); return(true); }); } //Log._Debug($"SegmentTraverser: Traversal finished."); }
protected void UpdateSegment(ref ExtSegment seg) { #if DEBUG if (DebugSwitch.TurnOnRed.Get()) { Log._Debug($"TurnOnRedManager.UpdateSegment({seg.segmentId}) called."); } #endif ResetSegment(seg.segmentId); IExtSegmentEndManager extSegmentEndManager = Constants.ManagerFactory.ExtSegmentEndManager; ushort startNodeId = Services.NetService.GetSegmentNodeId(seg.segmentId, true); if (startNodeId != 0) { int index0 = extSegmentEndManager.GetIndex(seg.segmentId, true); UpdateSegmentEnd( ref seg, ref extSegmentEndManager.ExtSegmentEnds[index0]); } ushort endNodeId = Services.NetService.GetSegmentNodeId(seg.segmentId, false); if (endNodeId != 0) { int index1 = extSegmentEndManager.GetIndex(seg.segmentId, false); UpdateSegmentEnd( ref seg, ref extSegmentEndManager.ExtSegmentEnds[index1]); } }
/// <summary> /// Performs a Depth-First traversal over the cached segment geometry structure. At each /// traversed segment, the given `visitor` is notified. It then can update the current `state`. /// </summary> /// <param name="initialSegmentGeometry">Specifies the segment at which the traversal /// should start.</param> /// <param name="nextNodeIsStartNode">Specifies if the next node to traverse is the start /// node of the initial segment.</param> /// <param name="direction">Specifies if traffic should be able to flow towards the initial /// segment (Incoming) or should be able to flow from the initial segment (Outgoing) or /// in both directions (Both).</param> /// <param name="maximumDepth">Specifies the maximum depth to explore. At a depth of 0, no /// segment will be traversed (event the initial segment will be omitted).</param> /// <param name="visitorFun">Specifies the stateful visitor that should be notified as soon as /// a traversable segment (which has not been traversed before) is found.</param> public static IEnumerable <ushort> Traverse(ushort initialSegmentId, TraverseDirection direction, TraverseSide side, SegmentStopCriterion stopCrit, SegmentVisitor visitorFun) { ExtSegment initialSeg = Constants.ManagerFactory.ExtSegmentManager.ExtSegments[initialSegmentId]; if (!initialSeg.valid) { return(null); } // Log._Debug($"SegmentTraverser: Traversing initial segment {initialSegmentId}"); if (!visitorFun( new SegmentVisitData( ref initialSeg, ref initialSeg, false, false, true))) { return(null); } HashSet <ushort> visitedSegmentIds = new HashSet <ushort>(); visitedSegmentIds.Add(initialSegmentId); IExtSegmentEndManager extSegEndMan = Constants.ManagerFactory.ExtSegmentEndManager; ref NetSegment initialSegment = ref initialSegmentId.ToSegment();
/// <summary> /// Performs a Depth-First traversal over the cached segment geometry structure. At each /// traversed segment, the given `visitor` is notified. It then can update the current `state`. /// </summary> /// <param name="initialSegmentGeometry">Specifies the segment at which the traversal /// should start.</param> /// <param name="nextNodeIsStartNode">Specifies if the next node to traverse is the start /// node of the initial segment.</param> /// <param name="direction">Specifies if traffic should be able to flow towards the initial /// segment (Incoming) or should be able to flow from the initial segment (Outgoing) or /// in both directions (Both).</param> /// <param name="maximumDepth">Specifies the maximum depth to explore. At a depth of 0, no /// segment will be traversed (event the initial segment will be omitted).</param> /// <param name="visitorFun">Specifies the stateful visitor that should be notified as soon as /// a traversable segment (which has not been traversed before) is found.</param> public static IEnumerable <ushort> Traverse(ushort initialSegmentId, TraverseDirection direction, TraverseSide side, SegmentStopCriterion stopCrit, SegmentVisitor visitorFun) { ExtSegment initialSeg = Constants.ManagerFactory.ExtSegmentManager.ExtSegments[initialSegmentId]; if (!initialSeg.valid) { return(null); } // Log._Debug($"SegmentTraverser: Traversing initial segment {initialSegmentId}"); if (!visitorFun( new SegmentVisitData( ref initialSeg, ref initialSeg, false, false, true))) { return(null); } HashSet <ushort> visitedSegmentIds = new HashSet <ushort>(); visitedSegmentIds.Add(initialSegmentId); IExtSegmentEndManager extSegEndMan = Constants.ManagerFactory.ExtSegmentEndManager; ushort startNodeId = Constants.ServiceFactory.NetService.GetSegmentNodeId(initialSegmentId, true); TraverseRec( ref initialSeg, ref extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(initialSegmentId, true)], ref startNodeId.ToNode(), true, direction, side, stopCrit, visitorFun, visitedSegmentIds); ushort endNodeId = Constants.ServiceFactory.NetService.GetSegmentNodeId(initialSegmentId, false); TraverseRec( ref initialSeg, ref extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(initialSegmentId, false)], ref endNodeId.ToNode(), false, direction, side, stopCrit, visitorFun, visitedSegmentIds); // Log._Debug($"SegmentTraverser: Traversal finished."); return(visitedSegmentIds); }
public void MarkAsUpdated(ref ExtSegment seg, bool updateNodes = true) { #if DEBUG if (DebugSwitch.GeometryDebug.Get()) { Log._Debug( $"GeometryManager.MarkAsUpdated(segment {seg.segmentId}): Marking segment as updated"); } #endif lock (updateLock) { updatedSegmentBuckets[seg.segmentId >> 6] |= 1uL << (seg.segmentId & 63); stateUpdated = true; if (updateNodes) { MarkAsUpdated( Constants.ServiceFactory.NetService.GetSegmentNodeId(seg.segmentId, true)); MarkAsUpdated( Constants.ServiceFactory.NetService.GetSegmentNodeId(seg.segmentId, false)); } if (!seg.valid) { SimulationStep(true); } } }
protected override void HandleValidSegment(ref ExtSegment seg) { if (!MayHaveParkingRestriction(seg.segmentId)) { parkingAllowed[seg.segmentId][0] = true; parkingAllowed[seg.segmentId][1] = true; } }
public SegmentVisitData(ref ExtSegment prevSeg, ref ExtSegment curSeg, bool viaInitialStartNode, bool viaStartNode, bool initial) { this.prevSeg = prevSeg; this.curSeg = curSeg; this.viaInitialStartNode = viaInitialStartNode; this.viaStartNode = viaStartNode; this.initial = initial; }
public void OnUpdate(GeometryUpdate update) { #if DEBUG bool logGeometry = DebugSwitch.GeometryDebug.Get(); #else const bool logGeometry = false; #endif if (update.segment != null) { // Handle a segment update ExtSegment seg = (ExtSegment)update.segment; if (!seg.valid) { if (logGeometry) { Log._Debug($"{GetType().Name}.HandleInvalidSegment({seg.segmentId})"); } HandleInvalidSegment(ref seg); } else { if (logGeometry) { Log._Debug($"{GetType().Name}.HandleValidSegment({seg.segmentId})"); } HandleValidSegment(ref seg); } } else if (update.nodeId != null) { // Handle a node update ushort nodeId = update.nodeId.Value; ref NetNode node = ref nodeId.ToNode(); if ((node.m_flags & (NetNode.Flags.Created | NetNode.Flags.Deleted)) == NetNode.Flags.Created) { if (logGeometry) { Log._Debug($"{GetType().Name}.HandleValidNode({nodeId})"); } HandleValidNode(nodeId, ref node); } else { if (logGeometry) { Log._Debug($"{GetType().Name}.HandleInvalidNode({nodeId})"); } HandleInvalidNode(nodeId, ref node); } }
private ExtSegmentManager() { ExtSegments = new ExtSegment[NetManager.MAX_SEGMENT_COUNT]; for (uint i = 0; i < ExtSegments.Length; ++i) { ExtSegments[i] = new ExtSegment((ushort)i); } }
private void Recalculate(ref ExtSegment extSegment) { IExtSegmentEndManager extSegEndMan = Constants.ManagerFactory.ExtSegmentEndManager; ushort segmentId = extSegment.segmentId; #if DEBUG bool logGeometry = DebugSwitch.GeometryDebug.Get(); #else const bool logGeometry = false; #endif if (logGeometry) { Log._Debug($">>> ExtSegmentManager.Recalculate({segmentId}) called."); } if (!IsValid(segmentId)) { if (extSegment.valid) { Reset(ref extSegment); extSegment.valid = false; extSegEndMan.Recalculate(segmentId); Constants.ManagerFactory.GeometryManager.OnUpdateSegment(ref extSegment); } return; } if (logGeometry) { Log.Info($"Recalculating geometries of segment {segmentId} STARTED"); } Reset(ref extSegment); extSegment.valid = true; extSegment.oneWay = CalculateIsOneWay(segmentId); extSegment.highway = CalculateIsHighway(segmentId); extSegment.buslane = CalculateHasBusLane(segmentId); extSegEndMan.Recalculate(segmentId); if (logGeometry) { NetSegment[] segmentsBuffer = Singleton <NetManager> .instance.m_segments.m_buffer; Log.Info( $"Recalculated ext. segment {segmentId} (flags={segmentsBuffer[segmentId].m_flags}): " + $"{extSegment}"); } Constants.ManagerFactory.GeometryManager.OnUpdateSegment(ref extSegment); }
public SegmentVisitData(ref ExtSegment prevSeg, ref ExtSegment curSeg, bool viaInitialStartNode, bool viaStartNode, bool initial) { PrevSeg = prevSeg; CurSeg = curSeg; ViaInitialStartNode = viaInitialStartNode; ViaStartNode = viaStartNode; Initial = initial; }
protected void UpdateSegmentEnd(ref ExtSegment seg, ref ExtSegmentEnd end) { #if DEBUG bool logTurnOnRed = DebugSwitch.TurnOnRed.Get(); #else const bool logTurnOnRed = false; #endif if (logTurnOnRed) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}) called."); } IExtSegmentManager segmentManager = Constants.ManagerFactory.ExtSegmentManager; IExtSegmentEndManager segmentEndManager = Constants.ManagerFactory.ExtSegmentEndManager; ushort segmentId = seg.segmentId; ushort nodeId = end.nodeId; bool hasOutgoingSegment = false; Services.NetService.IterateNodeSegments( end.nodeId, (ushort otherSegId, ref NetSegment otherSeg) => { int index0 = segmentEndManager.GetIndex(otherSegId, otherSeg.m_startNode == nodeId); if (otherSegId != segmentId && segmentEndManager.ExtSegmentEnds[index0].outgoing) { hasOutgoingSegment = true; return(false); } return(true); }); // check if traffic can flow to the node and that there is at least one left segment if (!end.incoming || !hasOutgoingSegment) { if (logTurnOnRed) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}): " + "outgoing one-way or insufficient number of outgoing segments."); } return; } bool lht = Services.SimulationService.TrafficDrivesOnLeft; // check node // note that we must not check for the `TrafficLights` flag here because the flag might not be loaded yet ref NetNode node = ref nodeId.ToNode();
protected override void HandleInvalidSegment(ref ExtSegment seg) { #if DEBUG bool logLaneConnections = DebugSwitch.LaneConnections.Get(); #else const bool logLaneConnections = false; #endif if (logLaneConnections) { Log._Debug($"LaneConnectionManager.HandleInvalidSegment({seg.segmentId}): " + "Segment has become invalid. Removing lane connections."); } RemoveLaneConnectionsFromSegment(seg.segmentId, false, false); RemoveLaneConnectionsFromSegment(seg.segmentId, true); }
protected void UpdateSegmentEnd(ref ExtSegment seg, ref ExtSegmentEnd end) { #if DEBUG bool logTurnOnRed = DebugSwitch.TurnOnRed.Get(); #else const bool logTurnOnRed = false; #endif if (logTurnOnRed) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({end.segmentId}, {end.startNode}) called."); } IExtSegmentManager segmentManager = Constants.ManagerFactory.ExtSegmentManager; IExtSegmentEndManager segmentEndManager = Constants.ManagerFactory.ExtSegmentEndManager; ushort segmentId = seg.segmentId; ushort nodeId = end.nodeId; bool hasOutgoingSegment = false; ref NetNode endNode = ref end.nodeId.ToNode();
protected override void HandleInvalidSegment(ref ExtSegment seg) { Flags.ResetSegmentArrowFlags(seg.segmentId); }
public GeometryUpdate(ref ExtSegment segment) { this.segment = segment; nodeId = null; replacement = default(SegmentEndReplacement); }
public void SimulationStep(bool onlyFirstPass = false) { #if DEBUG bool logGeometry = DebugSwitch.GeometryDebug.Get(); #else const bool logGeometry = false; #endif if (!stateUpdated) { return; } NetManager netManager = Singleton <NetManager> .instance; if (!onlyFirstPass && (netManager.m_segmentsUpdated || netManager.m_nodesUpdated)) { // TODO maybe refactor NetManager use (however this could influence performance) if (logGeometry) { Log._Debug( $"GeometryManager.SimulationStep(): Skipping! stateUpdated={stateUpdated}, " + $"m_segmentsUpdated={netManager.m_segmentsUpdated}, " + $"m_nodesUpdated={netManager.m_nodesUpdated}"); } return; } lock (updateLock) { bool updatesMissing = onlyFirstPass; for (var pass = 0; pass < (onlyFirstPass ? 1 : 2); ++pass) { bool firstPass = pass == 0; int len = updatedSegmentBuckets.Length; for (var i = 0; i < len; i++) { ulong segMask = updatedSegmentBuckets[i]; if (segMask == 0uL) { continue; } for (var m = 0; m < 64; m++) { if ((segMask & 1uL << m) == 0uL) { continue; } ushort segmentId = (ushort)(i << 6 | m); ExtSegment seg = Constants.ManagerFactory.ExtSegmentManager.ExtSegments[segmentId]; if (firstPass ^ !seg.valid) { if (!firstPass) { updatesMissing = true; if (logGeometry) { Log.Warning( "GeometryManager.SimulationStep(): Detected invalid " + $"segment {segmentId} in second pass"); } } continue; } if (logGeometry) { Log._Debug( $"GeometryManager.SimulationStep(): Notifying observers about " + $"segment {segmentId}. Valid? {seg.valid} First pass? {firstPass}"); } NotifyObservers(new GeometryUpdate(ref seg)); updatedSegmentBuckets[i] &= ~(1uL << m); } } len = updatedNodeBuckets.Length; for (var i = 0; i < len; i++) { ulong nodeMask = updatedNodeBuckets[i]; if (nodeMask == 0uL) { continue; } for (var m = 0; m < 64; m++) { if ((nodeMask & 1uL << m) == 0uL) { continue; } ushort nodeId = (ushort)(i << 6 | m); bool valid = Services.NetService.IsNodeValid(nodeId); if (firstPass ^ !valid) { if (!firstPass) { updatesMissing = true; if (logGeometry) { Log.Warning( "GeometryManager.SimulationStep(): Detected invalid " + $"node {nodeId} in second pass"); } } continue; } if (logGeometry) { Log._Debug( "GeometryManager.SimulationStep(): Notifying observers about " + $"node {nodeId}. Valid? {valid} First pass? {firstPass}"); } NotifyObservers(new GeometryUpdate(nodeId)); updatedNodeBuckets[i] &= ~(1uL << m); } } } if (updatesMissing) { return; } while (segmentReplacements.Count > 0) { SegmentEndReplacement replacement = segmentReplacements.Dequeue(); if (logGeometry) { Log._Debug( "GeometryManager.SimulationStep(): Notifying observers about " + $"segment end replacement {replacement}"); } NotifyObservers(new GeometryUpdate(replacement)); } stateUpdated = false; } }
public void OnUpdateSegment(ref ExtSegment seg) { MarkAsUpdated(ref seg); }
protected override void HandleInvalidSegment(ref ExtSegment seg) { Flags.resetSegmentVehicleRestrictions(seg.segmentId); ClearCache(seg.segmentId); }
protected override void HandleInvalidSegment(ref ExtSegment seg) { ResetSegment(seg.segmentId); }
public void OnUpdate(GeometryUpdate update) { #if DEBUG bool logGeometry = DebugSwitch.GeometryDebug.Get(); #else const bool logGeometry = false; #endif if (update.segment != null) { // Handle a segment update ExtSegment seg = (ExtSegment)update.segment; if (!seg.valid) { if (logGeometry) { Log._Debug($"{GetType().Name}.HandleInvalidSegment({seg.segmentId})"); } HandleInvalidSegment(ref seg); } else { if (logGeometry) { Log._Debug($"{GetType().Name}.HandleValidSegment({seg.segmentId})"); } HandleValidSegment(ref seg); } } else if (update.nodeId != null) { // Handle a node update ushort nodeId = (ushort)update.nodeId; Services.NetService.ProcessNode( nodeId, (ushort nId, ref NetNode node) => { if ((node.m_flags & (NetNode.Flags.Created | NetNode.Flags.Deleted)) == NetNode.Flags.Created) { if (logGeometry) { Log._Debug($"{GetType().Name}.HandleValidNode({nodeId})"); } HandleValidNode(nodeId, ref node); } else { if (logGeometry) { Log._Debug($"{GetType().Name}.HandleInvalidNode({nodeId})"); } HandleInvalidNode(nodeId, ref node); } return(true); }); } else { // Handle a segment end replacement IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager; if (logGeometry) { Log._Debug( $"{GetType().Name}.HandleSegmentReplacement({update.replacement.oldSegmentEndId} " + $"-> {update.replacement.newSegmentEndId})"); } int index0 = segEndMan.GetIndex( update.replacement.newSegmentEndId.SegmentId, update.replacement.newSegmentEndId.StartNode); HandleSegmentEndReplacement( update.replacement, ref segEndMan.ExtSegmentEnds[index0]); } }
/// <summary> /// Handles a valid segment /// </summary> /// <param name="geometry">segment geometry</param> protected virtual void HandleValidSegment(ref ExtSegment seg) { }
private void Reset(ref ExtSegment extSegment) { extSegment.Reset(); }
protected override void HandleValidSegment(ref ExtSegment seg) { UpdateSegment(ref seg); }
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; }
protected override void HandleInvalidSegment(ref ExtSegment seg) { RemoveSegmentLights(seg.segmentId); }
public void ShowGUI(bool viewOnly) { try { IExtSegmentManager segMan = Constants.ManagerFactory.ExtSegmentManager; IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager; TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; TrafficPriorityManager prioMan = TrafficPriorityManager.Instance; TrafficLightManager tlm = TrafficLightManager.Instance; Vector3 camPos = Constants.ServiceFactory.SimulationService.CameraPosition; bool clicked = !viewOnly?MainTool.CheckClicked() : false; ushort removedNodeId = 0; bool showRemoveButton = false; foreach (ushort nodeId in currentPriorityNodeIds) { if (!Constants.ServiceFactory.NetService.IsNodeValid(nodeId)) { continue; } if (!MainTool.IsNodeWithinViewDistance(nodeId)) { continue; } Vector3 nodePos = default(Vector3); Constants.ServiceFactory.NetService.ProcessNode(nodeId, delegate(ushort nId, ref NetNode node) { nodePos = node.m_position; return(true); }); for (int i = 0; i < 8; ++i) { ushort segmentId = 0; Constants.ServiceFactory.NetService.ProcessNode(nodeId, delegate(ushort nId, ref NetNode node) { segmentId = node.GetSegment(i); return(true); }); if (segmentId == 0) { continue; } bool startNode = (bool)Constants.ServiceFactory.NetService.IsStartNode(segmentId, nodeId); ExtSegment seg = segMan.ExtSegments[segmentId]; ExtSegmentEnd segEnd = segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, startNode)]; if (seg.oneWay && segEnd.outgoing) { continue; } // calculate sign position Vector3 signPos = nodePos; Constants.ServiceFactory.NetService.ProcessSegment(segmentId, delegate(ushort sId, ref NetSegment segment) { signPos += 10f * (startNode ? segment.m_startDirection : segment.m_endDirection); return(true); }); Vector3 signScreenPos; if (!MainTool.WorldToScreenPoint(signPos, out signScreenPos)) { continue; } // draw sign and handle input PriorityType sign = prioMan.GetPrioritySign(segmentId, startNode); if (viewOnly && sign == PriorityType.None) { continue; } if (!viewOnly && sign != PriorityType.None) { showRemoveButton = true; } if (MainTool.DrawGenericSquareOverlayTexture(TextureResources.PrioritySignTextures[sign], camPos, signPos, 90f, !viewOnly) && clicked) { PriorityType?newSign = null; switch (sign) { case PriorityType.Main: newSign = PriorityType.Yield; break; case PriorityType.Yield: newSign = PriorityType.Stop; break; case PriorityType.Stop: newSign = PriorityType.Main; break; case PriorityType.None: default: newSign = prioMan.CountPrioritySignsAtNode(nodeId, PriorityType.Main) >= 2 ? PriorityType.Yield : PriorityType.Main; break; } if (newSign != null) { SetPrioritySign(segmentId, startNode, (PriorityType)newSign); } } // draw sign } // foreach segment end if (viewOnly) { continue; } // draw remove button and handle click if (showRemoveButton && MainTool.DrawHoverableSquareOverlayTexture(TextureResources.SignRemoveTexture2D, camPos, nodePos, 90f) && clicked) { prioMan.RemovePrioritySignsFromNode(nodeId); Log._Debug($"PrioritySignsTool.ShowGUI: Removed priority signs from node {nodeId}"); removedNodeId = nodeId; } } // foreach node if (removedNodeId != 0) { currentPriorityNodeIds.Remove(removedNodeId); SelectedNodeId = 0; } } catch (Exception e) { Log.Error(e.ToString()); } }
protected override void HandleInvalidSegment(ref ExtSegment seg) { parkingAllowed[seg.segmentId][0] = true; parkingAllowed[seg.segmentId][1] = true; }
protected override void HandleValidSegment(ref ExtSegment seg) { }
private static void TraverseRec(ref ExtSegment prevSeg, ref ExtSegmentEnd prevSegEnd, ref NetNode node, bool viaInitialStartNode, TraverseDirection direction, TraverseSide side, SegmentStopCriterion stopCrit, SegmentVisitor visitorFun, HashSet <ushort> visitedSegmentIds) { // Log._Debug($"SegmentTraverser: Traversing segment {prevSegEnd.segmentId}"); // collect next segment ids to traverse if (direction == TraverseDirection.None) { throw new ArgumentException($"Invalid direction {direction} given."); } if (side == TraverseSide.None) { throw new ArgumentException($"Invalid side {side} given."); } IExtSegmentManager extSegMan = Constants.ManagerFactory.ExtSegmentManager; IExtSegmentEndManager extSegEndMan = Constants.ManagerFactory.ExtSegmentEndManager; HashSet <ushort> nextSegmentIds = new HashSet <ushort>(); for (int i = 0; i < 8; ++i) { ushort nextSegmentId = node.GetSegment(i); if (nextSegmentId == 0 || nextSegmentId == prevSegEnd.segmentId) { continue; } bool nextIsStartNode = (bool)Constants.ServiceFactory.NetService.IsStartNode( nextSegmentId, prevSegEnd.nodeId); ExtSegmentEnd nextSegEnd = extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(nextSegmentId, nextIsStartNode)]; if (direction == TraverseDirection.AnyDirection || (direction == TraverseDirection.Incoming && nextSegEnd.incoming) || (direction == TraverseDirection.Outgoing && nextSegEnd.outgoing)) { if (side == TraverseSide.AnySide) { nextSegmentIds.Add(nextSegmentId); } else { ArrowDirection dir = extSegEndMan.GetDirection( ref prevSegEnd, nextSegmentId); if (((side & TraverseSide.Left) != TraverseSide.None && dir == ArrowDirection.Left) || ((side & TraverseSide.Straight) != TraverseSide.None && dir == ArrowDirection.Forward) || ((side & TraverseSide.Right) != TraverseSide.None && dir == ArrowDirection.Right)) { nextSegmentIds.Add(nextSegmentId); } } } } nextSegmentIds.Remove(0); // Log._Debug($"SegmentTraverser: Fetched next segments to traverse: // {nextSegmentIds.CollectionToString()}"); if (nextSegmentIds.Count >= 2 && (stopCrit & SegmentStopCriterion.Junction) != SegmentStopCriterion.None) { // Log._Debug($"SegmentTraverser: Stop criterion reached @ {prevSegEnd.segmentId}: // {nextSegmentIds.Count} connected segments"); return; } // explore next segments foreach (ushort nextSegmentId in nextSegmentIds) { if (visitedSegmentIds.Contains(nextSegmentId)) { continue; } visitedSegmentIds.Add(nextSegmentId); // Log._Debug($"SegmentTraverser: Traversing segment {nextSegmentId}"); ushort nextStartNodeId = Constants.ServiceFactory.NetService.GetSegmentNodeId(nextSegmentId, true); if (!visitorFun( new SegmentVisitData( ref prevSeg, ref extSegMan.ExtSegments[nextSegmentId], viaInitialStartNode, prevSegEnd.nodeId == nextStartNodeId, false))) { continue; } bool nextNodeIsStartNode = nextStartNodeId != prevSegEnd.nodeId; ExtSegmentEnd nextSegEnd = extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(nextSegmentId, nextNodeIsStartNode)]; Constants.ServiceFactory.NetService.ProcessNode( nextSegEnd.nodeId, (ushort nId, ref NetNode nextNode) => { TraverseRec( ref extSegMan.ExtSegments[nextSegmentId], ref nextSegEnd, ref nextNode, viaInitialStartNode, direction, side, stopCrit, visitorFun, visitedSegmentIds); return(true); }); } // end foreach }