/// <summary> /// Adds custom traffic lights at the specified node and segment. /// Light states (red, yellow, green) are taken from the "live" state, that is the traffic light's light state right before the custom light takes control. /// </summary> /// <param name="segmentId"></param> /// <param name="startNode"></param> public CustomSegmentLights AddLiveSegmentLights(ushort segmentId, bool startNode) { SegmentGeometry segGeometry = SegmentGeometry.Get(segmentId); SegmentEndGeometry endGeometry = startNode ? segGeometry.StartNodeGeometry : segGeometry.EndNodeGeometry; if (!endGeometry.IsValid()) { Log.Error($"CustomTrafficLightsManager.AddLiveSegmentLights: Segment {segmentId} is not connected to a node. startNode={startNode}"); return(null); } var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; RoadBaseAI.TrafficLightState vehicleLightState; RoadBaseAI.TrafficLightState pedestrianLightState; bool vehicles; bool pedestrians; RoadBaseAI.GetTrafficLightState(endGeometry.NodeId(), ref Singleton <NetManager> .instance.m_segments.m_buffer[segmentId], currentFrameIndex - 256u, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians); return(AddSegmentLights(segmentId, startNode, vehicleLightState == RoadBaseAI.TrafficLightState.Green ? RoadBaseAI.TrafficLightState.Green : RoadBaseAI.TrafficLightState.Red)); }
public bool IsEnteringBlockedJunctionAllowedConfigurable(ushort segmentId, bool startNode, ref NetNode node) { #if DEBUG bool debug = GlobalConfig.Instance.Debug.Switches[11]; #endif SegmentEndGeometry endGeo = SegmentGeometry.Get(segmentId)?.GetEnd(startNode); if (endGeo == null) { Log.Warning($"JunctionRestrictionsManager.IsEnteringBlockedJunctionAllowedConfigurable({segmentId}, {startNode}): Could not get segment end geometry"); return(false); } bool ret = (node.m_flags & NetNode.Flags.Junction) != NetNode.Flags.None && node.Info?.m_class?.m_service != ItemClass.Service.Beautification && !endGeo.OutgoingOneWay; ; #if DEBUG if (debug) { Log._Debug($"JunctionRestrictionsManager.IsEnteringBlockedJunctionAllowedConfigurable({segmentId}, {startNode}): ret={ret}, flags={node.m_flags}, service={node.Info?.m_class?.m_service}, outgoingOneWay={endGeo.OutgoingOneWay}"); } #endif return(ret); }
public ISegmentEnd GetOrAddSegmentEnd(ushort segmentId, bool startNode) { ISegmentEnd end = GetSegmentEnd(segmentId, startNode); if (end != null) { return(end); } SegmentGeometry segGeo = SegmentGeometry.Get(segmentId); if (segGeo == null) { Log.Warning($"SegmentEndManager.GetOrAddSegmentEnd({segmentId}, {startNode}): Refusing to add segment end for invalid segment."); return(null); } SegmentEndGeometry endGeo = segGeo.GetEnd(startNode); if (endGeo == null) { Log.Warning($"SegmentEndManager.GetOrAddSegmentEnd({segmentId}, {startNode}): Refusing to add segment end for invalid segment end."); return(null); } return(SegmentEnds[GetIndex(segmentId, startNode)] = new SegmentEnd(segmentId, startNode)); }
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 defaultPedestrianCrossingAllowed; public void UpdateDefaults(SegmentEndGeometry segmentEndGeometry) { NodeGeometry nodeGeo = NodeGeometry.Get(segmentEndGeometry.NodeId()); bool newDefaultEnterWhenBlockedAllowed = false; bool newDefaultUturnAllowed = false; //NetNode.Flags _nodeFlags = NetNode.Flags.None; Constants.ServiceFactory.NetService.ProcessNode(segmentEndGeometry.NodeId(), delegate(ushort nodeId, ref NetNode node) { //_nodeFlags = node.m_flags; int numOutgoing = 0; int numIncoming = 0; node.CountLanes(nodeId, 0, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, true, ref numOutgoing, ref numIncoming); newDefaultEnterWhenBlockedAllowed = numOutgoing == 1 || numIncoming == 1; if (Options.allowUTurns) { newDefaultUturnAllowed = (node.m_flags & (NetNode.Flags.Junction | NetNode.Flags.Transition | NetNode.Flags.Bend | NetNode.Flags.End | NetNode.Flags.OneWayOut)) != NetNode.Flags.None && node.Info?.m_class?.m_service != ItemClass.Service.Beautification ; } else { newDefaultUturnAllowed = (node.m_flags & (NetNode.Flags.End | NetNode.Flags.OneWayOut)) != NetNode.Flags.None; } return(true); }); defaultEnterWhenBlockedAllowed = newDefaultEnterWhenBlockedAllowed; defaultUturnAllowed = newDefaultUturnAllowed; //Log._Debug($"SegmentEndFlags.UpdateDefaults: this={this} _nodeFlags={_nodeFlags} defaultEnterWhenBlockedAllowed={defaultEnterWhenBlockedAllowed}"); }
public bool IsLaneChangingAllowedWhenGoingStraightConfigurable(ushort segmentId, bool startNode, ref NetNode node) { #if DEBUG bool debug = GlobalConfig.Instance.Debug.Switches[11]; #endif SegmentEndGeometry endGeo = SegmentGeometry.Get(segmentId)?.GetEnd(startNode); if (endGeo == null) { Log.Warning($"JunctionRestrictionsManager.IsLaneChangingAllowedWhenGoingStraightConfigurable({segmentId}, {startNode}): Could not get segment end geometry"); return(false); } bool ret = (node.m_flags & (NetNode.Flags.Junction | NetNode.Flags.Transition)) != NetNode.Flags.None && node.Info?.m_class?.m_service != ItemClass.Service.Beautification && !endGeo.OutgoingOneWay && node.CountSegments() > 2 ; #if DEBUG if (debug) { Log._Debug($"JunctionRestrictionsManager.IsLaneChangingAllowedWhenGoingStraightConfigurable({segmentId}, {startNode}): ret={ret}, flags={node.m_flags}, service={node.Info?.m_class?.m_service}, incomingOneWay={endGeo.IncomingOneWay}, outgoingOneWay={endGeo.OutgoingOneWay}, node.CountSegments()={node.CountSegments()}"); } #endif return(ret); }
public CustomSegmentLights GetSegmentLights(ushort nodeId, ushort segmentId) { SegmentEndGeometry endGeometry = SegmentGeometry.Get(segmentId).GetEnd(nodeId); if (endGeometry == null) { return(null); } return(GetSegmentLights(segmentId, endGeometry.StartNode, false)); }
public short ClockwiseIndexOfSegmentEnd(ISegmentEndId endId) { SegmentEndGeometry endGeo = SegmentGeometry.Get(endId.SegmentId)?.GetEnd(endId.StartNode); if (endGeo == null) { return(0); } return(endGeo.GetClockwiseIndex()); }
/// <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); } }
public bool GetDefaultEnteringBlockedJunctionAllowed(ushort segmentId, bool startNode, ref NetNode node) { #if DEBUG bool debug = GlobalConfig.Instance.Debug.Switches[11]; #endif SegmentEndGeometry endGeo = SegmentGeometry.Get(segmentId)?.GetEnd(startNode); if (endGeo == null) { Log.Warning($"JunctionRestrictionsManager.GetDefaultEnteringBlockedJunctionAllowed({segmentId}, {startNode}): Could not get segment end geometry"); return(false); } if (!IsEnteringBlockedJunctionAllowedConfigurable(segmentId, startNode, ref node)) { bool res = (node.m_flags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) != NetNode.Flags.Junction || node.CountSegments() == 2; #if DEBUG if (debug) { Log._Debug($"JunctionRestrictionsManager.GetDefaultEnteringBlockedJunctionAllowed({segmentId}, {startNode}): Setting is not configurable. res={res}, flags={node.m_flags}, node.CountSegments()={node.CountSegments()}"); } #endif return(res); } bool ret; if (Options.allowEnterBlockedJunctions) { ret = true; } else { int numOutgoing = 0; int numIncoming = 0; node.CountLanes(endGeo.NodeId(), 0, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, true, ref numOutgoing, ref numIncoming); ret = numOutgoing == 1 || numIncoming == 1; } #if DEBUG if (debug) { Log._Debug($"JunctionRestrictionsManager.GetDefaultEnteringBlockedJunctionAllowed({segmentId}, {startNode}): Setting is configurable. ret={ret}"); } #endif return(ret); }
public bool UpdateSegmentEnd(ushort segmentId, bool startNode) { SegmentGeometry segGeo = SegmentGeometry.Get(segmentId); if (segGeo == null) { #if DEBUGGEO Log._Debug($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Segment {segmentId} is invalid. Removing all segment ends."); #endif RemoveSegmentEnds(segmentId); return(false); } SegmentEndGeometry endGeo = segGeo.GetEnd(startNode); if (endGeo == null) { Log._Debug($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Segment end {segmentId} @ {startNode} is invalid. Removing segment end."); RemoveSegmentEnd(segmentId, startNode); return(false); } if (TrafficPriorityManager.Instance.HasSegmentPrioritySign(segmentId, startNode) || TrafficLightSimulationManager.Instance.HasTimedSimulation(endGeo.NodeId())) { Log._Debug($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Segment {segmentId} @ {startNode} has timed light or priority sign. Adding segment end {segmentId} @ {startNode}"); ISegmentEnd end = GetOrAddSegmentEnd(segmentId, startNode); if (end == null) { Log.Warning($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Failed to add segment end."); return(false); } else { Log._Debug($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Added segment end. Updating now."); end.Update(); Log._Debug($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Update of segment end finished."); return(true); } } else { #if DEBUGGEO Log._Debug($"SegmentEndManager.UpdateSegmentEnd({segmentId}, {startNode}): Segment {segmentId} @ {startNode} neither has timed light nor priority sign. Removing segment end {segmentId} @ {startNode}"); #endif RemoveSegmentEnd(segmentId, startNode); return(false); } }
//private bool defaultPedestrianCrossingAllowed; public void UpdateDefaults(SegmentEndGeometry segmentEndGeometry) { NodeGeometry nodeGeo = NodeGeometry.Get(segmentEndGeometry.NodeId()); bool newDefaultEnterWhenBlockedAllowed = false; NetNode.Flags _nodeFlags = NetNode.Flags.None; Constants.ServiceFactory.NetService.ProcessNode(segmentEndGeometry.NodeId(), delegate(ushort nodeId, ref NetNode node) { _nodeFlags = node.m_flags; int numOutgoing = 0; int numIncoming = 0; node.CountLanes(nodeId, 0, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, VehicleInfo.VehicleType.Car, true, ref numOutgoing, ref numIncoming); newDefaultEnterWhenBlockedAllowed = numOutgoing == 1 || numIncoming == 1; return(true); }); defaultEnterWhenBlockedAllowed = newDefaultEnterWhenBlockedAllowed; //Log._Debug($"SegmentEndFlags.UpdateDefaults: this={this} _nodeFlags={_nodeFlags} defaultEnterWhenBlockedAllowed={defaultEnterWhenBlockedAllowed}"); }
protected void UpdateSegment(SegmentGeometry geometry) { #if DEBUG bool debug = GlobalConfig.Instance.Debug.Switches[25]; if (debug) { Log._Debug($"TurnOnRedManager.UpdateSegment({geometry.SegmentId}) called."); } #endif ResetSegment(geometry.SegmentId); SegmentEndGeometry startEndGeo = geometry.GetEnd(true); if (startEndGeo != null) { UpdateSegmentEnd(startEndGeo); } SegmentEndGeometry endEndGeo = geometry.GetEnd(false); if (endEndGeo != null) { UpdateSegmentEnd(endEndGeo); } }
protected void UpdateSegmentEnd(SegmentEndGeometry endGeo) { #if DEBUG bool debug = GlobalConfig.Instance.Debug.Switches[25]; if (debug) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}) called."); } #endif // check if traffic can flow to the node and that there is at least one outgoing segment if (endGeo.OutgoingOneWay || endGeo.NumOutgoingSegments <= 0) { #if DEBUG if (debug) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): outgoing one-way or insufficient number of outgoing segments."); } #endif return; } bool lhd = Services.SimulationService.LeftHandDrive; ushort nodeId = endGeo.NodeId(); // check node // note that we must not check for the `TrafficLights` flag here because the flag might not be loaded yet bool nodeValid = false; Services.NetService.ProcessNode(nodeId, delegate(ushort nId, ref NetNode node) { nodeValid = (node.m_flags & NetNode.Flags.LevelCrossing) == NetNode.Flags.None && node.Info?.m_class?.m_service != ItemClass.Service.Beautification; return(true); }); if (!nodeValid) { #if DEBUG if (debug) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): node invalid"); } #endif return; } // get left/right segments ushort leftSegmentId = 0; ushort rightSegmentId = 0; Services.NetService.ProcessSegment(endGeo.SegmentId, delegate(ushort segId, ref NetSegment seg) { seg.GetLeftAndRightSegments(nodeId, out leftSegmentId, out rightSegmentId); return(true); }); #if DEBUG if (debug) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): got left/right segments: {leftSegmentId}/{rightSegmentId}"); } #endif // validate left/right segments according to geometric properties if (leftSegmentId != 0 && !endGeo.IsLeftSegment(leftSegmentId)) { #if DEBUG if (debug) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): left segment is not geometrically left"); } #endif leftSegmentId = 0; } if (rightSegmentId != 0 && !endGeo.IsRightSegment(rightSegmentId)) { #if DEBUG if (debug) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): right segment is not geometrically right"); } #endif rightSegmentId = 0; } // check for incoming one-ways if (leftSegmentId != 0 && SegmentGeometry.Get(leftSegmentId).GetEnd(nodeId).IncomingOneWay) { #if DEBUG if (debug) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): left segment is incoming one-way"); } #endif leftSegmentId = 0; } if (rightSegmentId != 0 && SegmentGeometry.Get(rightSegmentId).GetEnd(nodeId).IncomingOneWay) { #if DEBUG if (debug) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): right segment is incoming one-way"); } #endif rightSegmentId = 0; } if (endGeo.IncomingOneWay) { if (lhd && rightSegmentId != 0 || !lhd && leftSegmentId != 0) { // special case: one-way to one-way in non-preferred direction #if DEBUG if (debug) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): source is incoming one-way. checking for one-way in non-preferred direction"); } #endif ushort targetSegmentId = lhd ? rightSegmentId : leftSegmentId; SegmentEndGeometry targetEndGeo = SegmentGeometry.Get(targetSegmentId)?.GetEnd(nodeId); if (targetEndGeo == null || !targetEndGeo.OutgoingOneWay) { if (targetEndGeo == null) { Log.Error($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): One-way to one-way: Target segment end geometry not found for segment id {targetSegmentId} @ {nodeId}"); } // disallow turn in non-preferred direction #if DEBUG if (debug) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): turn in non-preferred direction {(lhd ? "right" : "left")} disallowed"); } #endif if (lhd) { rightSegmentId = 0; } else { leftSegmentId = 0; } } } } else if (lhd) { // default case (LHD): turn in preferred direction rightSegmentId = 0; } else { // default case (RHD): turn in preferred direction leftSegmentId = 0; } int index = GetIndex(endGeo.SegmentId, endGeo.StartNode); TurnOnRedSegments[index].leftSegmentId = leftSegmentId; TurnOnRedSegments[index].rightSegmentId = rightSegmentId; #if DEBUG if (debug) { Log._Debug($"TurnOnRedManager.UpdateSegmentEnd({endGeo.SegmentId}, {endGeo.StartNode}): Finished calculation. leftSegmentId={leftSegmentId}, rightSegmentId={rightSegmentId}"); } #endif }
public bool LoadData(List <Configuration.SegmentNodeConf> data) { bool success = true; Log.Info($"Loading junction restrictions. {data.Count} elements"); foreach (Configuration.SegmentNodeConf segNodeConf in data) { try { if (!Services.NetService.IsSegmentValid(segNodeConf.segmentId)) { continue; } Log._Debug($"JunctionRestrictionsManager.LoadData: Loading junction restrictions for segment {segNodeConf.segmentId}: startNodeFlags={segNodeConf.startNodeFlags} endNodeFlags={segNodeConf.endNodeFlags}"); if (segNodeConf.startNodeFlags != null) { SegmentEndGeometry startNodeSegGeo = SegmentGeometry.Get(segNodeConf.segmentId)?.GetEnd(true); if (startNodeSegGeo != null) { Configuration.SegmentNodeFlags flags = segNodeConf.startNodeFlags; Services.NetService.ProcessNode(startNodeSegGeo.NodeId(), delegate(ushort nId, ref NetNode node) { if (flags.uturnAllowed != null && IsUturnAllowedConfigurable(segNodeConf.segmentId, true, ref node)) { SetUturnAllowed(segNodeConf.segmentId, true, (bool)flags.uturnAllowed); } if (flags.turnOnRedAllowed != null && IsNearTurnOnRedAllowedConfigurable(segNodeConf.segmentId, true, ref node)) { SetNearTurnOnRedAllowed(segNodeConf.segmentId, true, (bool)flags.turnOnRedAllowed); } if (flags.farTurnOnRedAllowed != null && IsNearTurnOnRedAllowedConfigurable(segNodeConf.segmentId, true, ref node)) { SetFarTurnOnRedAllowed(segNodeConf.segmentId, true, (bool)flags.farTurnOnRedAllowed); } if (flags.straightLaneChangingAllowed != null && IsLaneChangingAllowedWhenGoingStraightConfigurable(segNodeConf.segmentId, true, ref node)) { SetLaneChangingAllowedWhenGoingStraight(segNodeConf.segmentId, true, (bool)flags.straightLaneChangingAllowed); } if (flags.enterWhenBlockedAllowed != null && IsEnteringBlockedJunctionAllowedConfigurable(segNodeConf.segmentId, true, ref node)) { SetEnteringBlockedJunctionAllowed(segNodeConf.segmentId, true, (bool)flags.enterWhenBlockedAllowed); } if (flags.pedestrianCrossingAllowed != null && IsPedestrianCrossingAllowedConfigurable(segNodeConf.segmentId, true, ref node)) { SetPedestrianCrossingAllowed(segNodeConf.segmentId, true, (bool)flags.pedestrianCrossingAllowed); } return(true); }); } else { Log.Warning($"JunctionRestrictionsManager.LoadData(): Could not get segment end geometry for segment {segNodeConf.segmentId} @ start node"); } } if (segNodeConf.endNodeFlags != null) { SegmentEndGeometry endNodeSegGeo = SegmentGeometry.Get(segNodeConf.segmentId)?.GetEnd(false); if (endNodeSegGeo != null) { Configuration.SegmentNodeFlags flags = segNodeConf.endNodeFlags; Services.NetService.ProcessNode(endNodeSegGeo.NodeId(), delegate(ushort nId, ref NetNode node) { if (flags.uturnAllowed != null && IsUturnAllowedConfigurable(segNodeConf.segmentId, false, ref node)) { SetUturnAllowed(segNodeConf.segmentId, false, (bool)flags.uturnAllowed); } if (flags.straightLaneChangingAllowed != null && IsLaneChangingAllowedWhenGoingStraightConfigurable(segNodeConf.segmentId, false, ref node)) { SetLaneChangingAllowedWhenGoingStraight(segNodeConf.segmentId, false, (bool)flags.straightLaneChangingAllowed); } if (flags.enterWhenBlockedAllowed != null && IsEnteringBlockedJunctionAllowedConfigurable(segNodeConf.segmentId, false, ref node)) { SetEnteringBlockedJunctionAllowed(segNodeConf.segmentId, false, (bool)flags.enterWhenBlockedAllowed); } if (flags.pedestrianCrossingAllowed != null && IsPedestrianCrossingAllowedConfigurable(segNodeConf.segmentId, false, ref node)) { SetPedestrianCrossingAllowed(segNodeConf.segmentId, false, (bool)flags.pedestrianCrossingAllowed); } if (flags.turnOnRedAllowed != null) { SetNearTurnOnRedAllowed(segNodeConf.segmentId, false, (bool)flags.turnOnRedAllowed); } if (flags.farTurnOnRedAllowed != null) { SetFarTurnOnRedAllowed(segNodeConf.segmentId, false, (bool)flags.farTurnOnRedAllowed); } return(true); }); } else { Log.Warning($"JunctionRestrictionsManager.LoadData(): Could not get segment end geometry for segment {segNodeConf.segmentId} @ end node"); } } } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning($"Error loading junction restrictions @ segment {segNodeConf.segmentId}: " + e.ToString()); success = false; } } return(success); }
/// <summary> /// Handles a segment replacement /// </summary> /// <param name="replacement">segment replacement</param> /// <param name="newEndGeo">new segment end geometry</param> protected virtual void HandleSegmentEndReplacement(SegmentEndReplacement replacement, SegmentEndGeometry newEndGeo) { }
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); } } }
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 }
internal void CalculateAutoPedestrianLightState(bool propagate = true) { //Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Calculating pedestrian light state of node {NodeId}"); SegmentGeometry segGeo = SegmentGeometry.Get(SegmentId); SegmentEndGeometry segmentEndGeometry = StartNode ? segGeo.StartNodeGeometry : segGeo.EndNodeGeometry; if (segmentEndGeometry == null) { Log._Debug($"Could not get SegmentEndGeometry for segment {SegmentId} @ {NodeId}."); AutoPedestrianLightState = RoadBaseAI.TrafficLightState.Green; return; } ushort nodeId = segmentEndGeometry.NodeId(); if (propagate) { foreach (ushort otherSegmentId in segmentEndGeometry.ConnectedSegments) { if (otherSegmentId == 0) { continue; } CustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId); if (otherLights == null) { //Log._Debug($"Expected other (propagate) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}"); continue; } otherLights.CalculateAutoPedestrianLightState(false); } } if (IsAnyGreen()) { //Log._Debug($"Any green at seg. {SegmentId} @ {NodeId}"); AutoPedestrianLightState = RoadBaseAI.TrafficLightState.Red; return; } //Log._Debug($"Querying incoming segments at seg. {SegmentId} @ {NodeId}"); RoadBaseAI.TrafficLightState autoPedestrianLightState = RoadBaseAI.TrafficLightState.Green; if (!segmentEndGeometry.IncomingOneWay) { // query straight segments foreach (ushort otherSegmentId in segmentEndGeometry.IncomingStraightSegments) { if (otherSegmentId == 0) { continue; } //Log._Debug($"Checking incoming straight segment {otherSegmentId} at seg. {SegmentId} @ {NodeId}"); CustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId); if (otherLights == null) { //Log._Debug($"Expected other (straight) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}"); continue; } if (!otherLights.IsAllMainRed()) { //Log._Debug($"Not all main red at {otherSegmentId} at seg. {SegmentId} @ {NodeId}"); autoPedestrianLightState = RoadBaseAI.TrafficLightState.Red; break; } } // query left/right segments if (autoPedestrianLightState == RoadBaseAI.TrafficLightState.Green) { bool lhd = TrafficPriorityManager.IsLeftHandDrive(); foreach (ushort otherSegmentId in lhd ? segmentEndGeometry.IncomingLeftSegments : segmentEndGeometry.IncomingRightSegments) { if (otherSegmentId == 0) { continue; } //Log._Debug($"Checking left/right segment {otherSegmentId} at seg. {SegmentId} @ {NodeId}"); CustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId); if (otherLights == null) { //Log._Debug($"Expected other (left/right) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}"); continue; } if ((lhd && !otherLights.IsAllRightRed()) || (!lhd && !otherLights.IsAllLeftRed())) { //Log._Debug($"Not all left red at {otherSegmentId} at seg. {SegmentId} @ {NodeId}"); autoPedestrianLightState = RoadBaseAI.TrafficLightState.Red; break; } } } } AutoPedestrianLightState = autoPedestrianLightState; //Log.Warning($"Calculated AutoPedestrianLightState for segment {SegmentId} @ {NodeId}: {AutoPedestrianLightState}"); }
protected override void HandleSegmentEndReplacement(SegmentEndReplacement replacement, SegmentEndGeometry endGeo) { ISegmentEndId oldSegmentEndId = replacement.oldSegmentEndId; ISegmentEndId newSegmentEndId = replacement.newSegmentEndId; SegmentEndFlags flags; if (oldSegmentEndId.StartNode) { flags = invalidSegmentFlags[oldSegmentEndId.SegmentId].startNodeFlags; invalidSegmentFlags[oldSegmentEndId.SegmentId].startNodeFlags.Reset(); } else { flags = invalidSegmentFlags[oldSegmentEndId.SegmentId].endNodeFlags; invalidSegmentFlags[oldSegmentEndId.SegmentId].endNodeFlags.Reset(); } Services.NetService.ProcessNode(endGeo.NodeId(), delegate(ushort nId, ref NetNode node) { flags.UpdateDefaults(newSegmentEndId.SegmentId, newSegmentEndId.StartNode, ref node); return(true); }); Log._Debug($"JunctionRestrictionsManager.HandleSegmentEndReplacement({replacement}): Segment replacement detected: {oldSegmentEndId.SegmentId} -> {newSegmentEndId.SegmentId} @ {newSegmentEndId.StartNode}"); SetSegmentEndFlags(newSegmentEndId.SegmentId, newSegmentEndId.StartNode, flags); }