public void MarkAsUpdated(NodeGeometry geometry) { #if DEBUGGEO if (GlobalConfig.Instance.Debug.Switches[5]) { Log._Debug($"GeometryManager.MarkAsUpdated(node {geometry.NodeId}): Marking node as updated"); } #endif try { Monitor.Enter(updateLock); ushort nodeId = geometry.NodeId; if (nodeId != 0) { updatedNodeBuckets[nodeId >> 6] |= 1uL << (int)(nodeId & 63); stateUpdated = true; if (!geometry.IsValid()) { SimulationStep(true); } } } finally { Monitor.Exit(updateLock); } }
/// <summary> /// Removes custom traffic lights at the given node /// </summary> /// <param name="nodeId"></param> public void RemoveNodeLights(ushort nodeId) { NodeGeometry nodeGeo = NodeGeometry.Get(nodeId); if (!nodeGeo.IsValid()) { return; } foreach (SegmentEndGeometry endGeo in nodeGeo.SegmentEndGeometries) { if (endGeo == null) { continue; } RemoveSegmentLight(endGeo.SegmentId, endGeo.StartNode); } }
/// <summary> /// Add custom traffic lights at the given node /// </summary> /// <param name="nodeId"></param> public void AddNodeLights(ushort nodeId) { NodeGeometry nodeGeo = NodeGeometry.Get(nodeId); if (!nodeGeo.IsValid()) { return; } foreach (SegmentEndGeometry endGeo in nodeGeo.SegmentEndGeometries) { if (endGeo == null) { continue; } AddSegmentLights(endGeo.SegmentId, endGeo.StartNode); DebugOutputPanel.AddMessage(PluginManager.MessageType.Message, "Adding to Queue: " + nodeId); NetworkInterface.Network.UpdateSelectedIds(nodeId); } }
public void MarkAsUpdated(NodeGeometry geometry, bool updateSegments = false) { #if DEBUGGEO if (GlobalConfig.Instance.Debug.Switches[5]) { Log._Debug($"GeometryManager.MarkAsUpdated(node {geometry.NodeId}): Marking node as updated"); } #endif try { Monitor.Enter(updateLock); ushort nodeId = geometry.NodeId; if (nodeId != 0) { updatedNodeBuckets[nodeId >> 6] |= 1uL << (int)(nodeId & 63); stateUpdated = true; if (updateSegments) { foreach (SegmentEndGeometry segEndGeo in geometry.SegmentEndGeometries) { if (segEndGeo != null) { MarkAsUpdated(segEndGeo.GetSegmentGeometry(), false); } } } if (!geometry.IsValid()) { SimulationStep(true); } } } finally { Monitor.Exit(updateLock); } }
/// <summary> /// Recalculates lane arrows based on present lane connections. /// </summary> /// <param name="laneId"></param> /// <param name="nodeId"></param> private void RecalculateLaneArrows(uint laneId, ushort nodeId, bool startNode) { #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}) called"); #endif if (!Options.laneConnectorEnabled) { return; } if (!Flags.mayHaveLaneArrows(laneId, startNode)) { #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): lane {laneId}, startNode? {startNode} must not have lane arrows"); #endif return; } if (!HasConnections(laneId, startNode)) { #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): lane {laneId} does not have outgoing connections"); #endif return; } if (nodeId == 0) { #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): invalid node"); #endif return; } Flags.LaneArrows arrows = Flags.LaneArrows.None; NetManager netManager = Singleton <NetManager> .instance; ushort segmentId = netManager.m_lanes.m_buffer[laneId].m_segment; if (segmentId == 0) { #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): invalid segment"); #endif return; } #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): startNode? {startNode}"); #endif NodeGeometry nodeGeo = NodeGeometry.Get(nodeId); if (!nodeGeo.IsValid()) { #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): invalid node geometry"); #endif return; } SegmentGeometry segmentGeo = SegmentGeometry.Get(segmentId); if (segmentGeo == null) { #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): invalid segment geometry"); #endif return; } ushort[] connectedSegmentIds = segmentGeo.GetConnectedSegments(startNode); if (connectedSegmentIds == null) { #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): connectedSegmentIds is null"); #endif return; } ushort[] allSegmentIds = new ushort[connectedSegmentIds.Length + 1]; allSegmentIds[0] = segmentId; Array.Copy(connectedSegmentIds, 0, allSegmentIds, 1, connectedSegmentIds.Length); foreach (ushort otherSegmentId in allSegmentIds) { if (otherSegmentId == 0) { continue; } ArrowDirection dir = segmentGeo.GetDirection(otherSegmentId, startNode); #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): processing connected segment {connectedSegmentId}. dir={dir}"); #endif // check if arrow has already been set for this direction switch (dir) { case ArrowDirection.Turn: if (Constants.ServiceFactory.SimulationService.LeftHandDrive) { if ((arrows & Flags.LaneArrows.Right) != Flags.LaneArrows.None) { continue; } } else { if ((arrows & Flags.LaneArrows.Left) != Flags.LaneArrows.None) { continue; } } break; case ArrowDirection.Forward: if ((arrows & Flags.LaneArrows.Forward) != Flags.LaneArrows.None) { continue; } break; case ArrowDirection.Left: if ((arrows & Flags.LaneArrows.Left) != Flags.LaneArrows.None) { continue; } break; case ArrowDirection.Right: if ((arrows & Flags.LaneArrows.Right) != Flags.LaneArrows.None) { continue; } break; default: continue; } #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): processing connected segment {connectedSegmentId}: need to determine arrows"); #endif bool addArrow = false; uint curLaneId = netManager.m_segments.m_buffer[otherSegmentId].m_lanes; while (curLaneId != 0) { #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): processing connected segment {connectedSegmentId}: checking lane {curLaneId}"); #endif if (AreLanesConnected(laneId, curLaneId, startNode)) { #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): processing connected segment {connectedSegmentId}: checking lane {curLaneId}: lanes are connected"); #endif addArrow = true; break; } curLaneId = netManager.m_lanes.m_buffer[curLaneId].m_nextLane; } #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): processing connected segment {connectedSegmentId}: finished processing lanes. addArrow={addArrow} arrows (before)={arrows}"); #endif if (addArrow) { switch (dir) { case ArrowDirection.Turn: if (Constants.ServiceFactory.SimulationService.LeftHandDrive) { arrows |= Flags.LaneArrows.Right; } else { arrows |= Flags.LaneArrows.Left; } break; case ArrowDirection.Forward: arrows |= Flags.LaneArrows.Forward; break; case ArrowDirection.Left: arrows |= Flags.LaneArrows.Left; break; case ArrowDirection.Right: arrows |= Flags.LaneArrows.Right; break; default: continue; } #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): processing connected segment {connectedSegmentId}: arrows={arrows}"); #endif } } #if DEBUGCONN Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): setting lane arrows to {arrows}"); #endif LaneArrowManager.Instance.SetLaneArrows(laneId, arrows, true); }
public void SimulationStep(bool onlyFirstPass = false) { #if DEBUGGEO bool debug = GlobalConfig.Instance.Debug.Switches[5]; #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 DEBUGGEO if (debug) { Log._Debug($"GeometryManager.SimulationStep(): Skipping! stateUpdated={stateUpdated}, m_segmentsUpdated={netManager.m_segmentsUpdated}, m_nodesUpdated={netManager.m_nodesUpdated}"); } #endif return; } try { Monitor.Enter(updateLock); bool updatesMissing = onlyFirstPass; for (int pass = 0; pass < (onlyFirstPass ? 1 : 2); ++pass) { bool firstPass = pass == 0; int len = updatedSegmentBuckets.Length; for (int i = 0; i < len; i++) { ulong segMask = updatedSegmentBuckets[i]; if (segMask != 0uL) { for (int m = 0; m < 64; m++) { if ((segMask & 1uL << m) != 0uL) { ushort segmentId = (ushort)(i << 6 | m); SegmentGeometry segmentGeometry = SegmentGeometry.Get(segmentId, true); if (firstPass ^ !segmentGeometry.IsValid()) { if (!firstPass) { updatesMissing = true; #if DEBUGGEO if (debug) { Log.Warning($"GeometryManager.SimulationStep(): Detected invalid segment {segmentGeometry.SegmentId} in second pass"); } #endif } continue; } #if DEBUGGEO if (debug) { Log._Debug($"GeometryManager.SimulationStep(): Notifying observers about segment {segmentGeometry.SegmentId}. Valid? {segmentGeometry.IsValid()} First pass? {firstPass}"); } #endif NotifyObservers(new GeometryUpdate(segmentGeometry)); updatedSegmentBuckets[i] &= ~(1uL << m); } } } } len = updatedNodeBuckets.Length; for (int i = 0; i < len; i++) { ulong nodeMask = updatedNodeBuckets[i]; if (nodeMask != 0uL) { for (int m = 0; m < 64; m++) { if ((nodeMask & 1uL << m) != 0uL) { ushort nodeId = (ushort)(i << 6 | m); NodeGeometry nodeGeometry = NodeGeometry.Get(nodeId); if (firstPass ^ !nodeGeometry.IsValid()) { if (!firstPass) { updatesMissing = true; #if DEBUGGEO if (debug) { Log.Warning($"GeometryManager.SimulationStep(): Detected invalid node {nodeGeometry.NodeId} in second pass"); } #endif } continue; } #if DEBUGGEO if (debug) { Log._Debug($"GeometryManager.SimulationStep(): Notifying observers about node {nodeGeometry.NodeId}. Valid? {nodeGeometry.IsValid()} First pass? {firstPass}"); } #endif NotifyObservers(new GeometryUpdate(nodeGeometry)); updatedNodeBuckets[i] &= ~(1uL << m); } } } } } if (!updatesMissing) { while (segmentReplacements.Count > 0) { SegmentEndReplacement replacement = segmentReplacements.Dequeue(); #if DEBUGGEO if (debug) { Log._Debug($"GeometryManager.SimulationStep(): Notifying observers about segment end replacement {replacement}"); } #endif NotifyObservers(new GeometryUpdate(replacement)); } stateUpdated = false; } } finally { Monitor.Exit(updateLock); } }
public void OnUpdate(GeometryUpdate update) { if (update.segmentGeometry != null) { // Handle a segment update SegmentGeometry geometry = update.segmentGeometry; if (!geometry.IsValid()) { #if DEBUGGEO if (GlobalConfig.Instance.Debug.Switches[5]) { Log._Debug($"{this.GetType().Name}.HandleInvalidSegment({geometry.SegmentId})"); } #endif HandleInvalidSegment(geometry); } else { #if DEBUGGEO if (GlobalConfig.Instance.Debug.Switches[5]) { Log._Debug($"{this.GetType().Name}.HandleValidSegment({geometry.SegmentId})"); } #endif HandleValidSegment(geometry); } } else if (update.nodeGeometry != null) { // Handle a node update NodeGeometry geometry = update.nodeGeometry; if (!geometry.IsValid()) { #if DEBUGGEO if (GlobalConfig.Instance.Debug.Switches[5]) { Log._Debug($"{this.GetType().Name}.HandleInvalidNode({geometry.NodeId})"); } #endif HandleInvalidNode(geometry); } else { #if DEBUGGEO if (GlobalConfig.Instance.Debug.Switches[5]) { Log._Debug($"{this.GetType().Name}.HandleValidNode({geometry.NodeId})"); } #endif HandleValidNode(geometry); } } else { // Handle a segment end replacement SegmentEndGeometry endGeo = SegmentGeometry.Get(update.replacement.newSegmentEndId.SegmentId)?.GetEnd(update.replacement.newSegmentEndId.StartNode); if (endGeo != null) { #if DEBUGGEO if (GlobalConfig.Instance.Debug.Switches[5]) { Log._Debug($"{this.GetType().Name}.HandleSegmentReplacement({update.replacement.oldSegmentEndId} -> {update.replacement.newSegmentEndId})"); } #endif HandleSegmentEndReplacement(update.replacement, endGeo); } } }