/// <summary> /// Intersects this direction with a line. /// </summary> /// <param name="line">The line to intersect with.</param> /// <param name="closeTo">The point that the intersection should be closest to. /// Specify null if you don't care. In that case, if there are multiple intersections, /// you get the intersection that is closest to one of 3 points: the start of the /// direction line, the start of the line, or the end of the line.</param> /// <param name="xsect">The position of the intersection (if any). Null if not found.</param> /// <param name="closest">The default point that is closest to the intersection. Null if /// intersection wasn't found.</param> /// <returns>True if intersection was found.</returns> internal bool Intersect( LineFeature line , PointFeature closeTo , out IPosition xsect , out PointFeature closest) { // Initialize results xsect = null; closest = null; // Define the length of the direction line as the length // of a diagonal that crosses the map's extent. IWindow mapWin = SpatialController.Current.MapModel.Extent; Debug.Assert(mapWin!=null); // If the window is currently undefined (e.g. during deserialization), // just use a really big distance. // TODO: This is a hack, but hopefully it may be shortlived, because // new logic is in the works for handling updates. double dist = (mapWin.IsEmpty ? 100000.0 : Geom.Distance(mapWin.Min, mapWin.Max)); // Define the position of the direction line. DON'T use the from- // point, because there may be an offset to the direction. IPosition fromPos = this.StartPosition; IPosition toPos = Geom.Polar(fromPos, this.Bearing.Radians, dist); // Construct a corresponding line segment. ITerminal start = new FloatingTerminal(fromPos); ITerminal end = new FloatingTerminal(toPos); SegmentGeometry seg = new SegmentGeometry(start, end); // Intersect the line segment with the other one. IntersectionResult xres = new IntersectionResult(line); uint nx = seg.Intersect(xres); if (nx==0) return false; // Determine which terminal point is the best. Start with the // ends of the intersected line. double mindsq = Double.MaxValue; if (xres.GetCloserPoint(line.StartPoint, ref mindsq, ref xsect)) closest = line.StartPoint; if (xres.GetCloserPoint(line.EndPoint, ref mindsq, ref xsect)) closest = line.EndPoint; // Check whether the direction from-point is any closer (the position may be // different from the start of the direction line, because the direction may // have an offset). if (xres.GetCloserPoint(this.From, ref mindsq, ref xsect)) closest = this.From; // If a close-to point has been specified, that overrides // everything else (however, doing the above has the desired // effect of defining the best of the default points). In // this case, we allow an intersection that coincides with // the line being intersected. // -- actually, we don't, since GetClosest uses a > 0 test if (closeTo != null) { xres.GetClosest(closeTo, out xsect, 0.0); /* IPosition xCloseTo; xres.GetClosest(closeTo, out xCloseTo, 0.0); if (xCloseTo != null) xsect = xCloseTo; */ } return (xsect!=null); }
internal static void OnBeforeLoadData() { if (!initDone) { segmentGeometries = new SegmentGeometry[Singleton<NetManager>.instance.m_segments.m_size]; Log._Debug($"Building {segmentGeometries.Length} segment geometries..."); for (ushort i = 0; i < segmentGeometries.Length; ++i) { segmentGeometries[i] = new SegmentGeometry(i); } Log._Debug($"Calculated segment geometries."); currentLaneTrafficBuffer = new ushort[Singleton<NetManager>.instance.m_lanes.m_size]; currentLaneSpeeds = new uint[Singleton<NetManager>.instance.m_lanes.m_size]; currentLaneDensities = new uint[Singleton<NetManager>.instance.m_lanes.m_size]; laneMeanSpeeds = new byte[Singleton<NetManager>.instance.m_lanes.m_size]; //laneMeanDensities = new byte[Singleton<NetManager>.instance.m_lanes.m_size]; resetTrafficStats(); initDone = true; } }
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 && IsFarTurnOnRedAllowedConfigurable(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 && IsNearTurnOnRedAllowedConfigurable(segNodeConf.segmentId, false, ref node)) { SetNearTurnOnRedAllowed(segNodeConf.segmentId, false, (bool)flags.turnOnRedAllowed); } if (flags.farTurnOnRedAllowed != null && IsFarTurnOnRedAllowedConfigurable(segNodeConf.segmentId, false, ref node)) { 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); }
internal void AddSegment(ushort segmentId, bool startNode, bool propagate) { #if DEBUGGEO if (GlobalConfig.Instance.DebugSwitches[5]) { Log._Debug($"NodeGeometry: Add segment {segmentId}, start? {startNode} @ node {NodeId}"); } #endif if (!IsValid()) { //Log.Error($"NodeGeometry: Trying to add segment {segmentId} @ invalid node {NodeId}"); Recalculate(); return; } for (int i = 0; i < 8; ++i) { if (SegmentEndGeometries[i]?.SegmentId == segmentId) { SegmentEndGeometries[i] = null; } } for (int i = 0; i < 8; ++i) { if (SegmentEndGeometries[i] == null) { SegmentEndGeometries[i] = startNode ? SegmentGeometry.Get(segmentId).StartNodeGeometry : SegmentGeometry.Get(segmentId).EndNodeGeometry; break; } } if (propagate) { NeedsRecalculation = true; try { RecalculateSegments(segmentId); } finally { NeedsRecalculation = false; } } Recalculate(); }
protected override void HandleValidSegment(SegmentGeometry geometry) { }
protected override void HandleValidSegment(SegmentGeometry geometry) { UpdateDefaults(geometry); }
private void _guiLaneChangeWindow(int num) { var info = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info; List <object[]> laneList = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, info, SelectedNodeId); SegmentGeometry geometry = CustomRoadAI.GetSegmentGeometry(SelectedSegmentId); GUILayout.BeginHorizontal(); for (var i = 0; i < laneList.Count; i++) { var flags = (NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[(uint)laneList[i][0]].m_flags; var style1 = new GUIStyle("button"); var style2 = new GUIStyle("button") { normal = { textColor = new Color32(255, 0, 0, 255) }, hover = { textColor = new Color32(255, 0, 0, 255) }, focused = { textColor = new Color32(255, 0, 0, 255) } }; var laneStyle = new GUIStyle { contentOffset = new Vector2(12f, 0f) }; var laneTitleStyle = new GUIStyle { contentOffset = new Vector2(36f, 2f), normal = { textColor = new Color(1f, 1f, 1f) } }; GUILayout.BeginVertical(laneStyle); GUILayout.Label(Translation.GetString("Lane") + " " + (i + 1), laneTitleStyle); GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); if (!Flags.applyLaneArrowFlags((uint)laneList[i][0])) { Flags.removeLaneArrowFlags((uint)laneList[i][0]); } if (GUILayout.Button("←", ((flags & NetLane.Flags.Left) == NetLane.Flags.Left ? style1 : style2), GUILayout.Width(35), GUILayout.Height(25))) { if (!Flags.toggleLaneArrowFlags((uint)laneList[i][0], Flags.LaneArrows.Left) && SelectedNodeId > 0) { MainTool.ShowTooltip(Translation.GetString("Lane_Arrow_Changer_Disabled"), Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId].m_position); } } if (GUILayout.Button("↑", ((flags & NetLane.Flags.Forward) == NetLane.Flags.Forward ? style1 : style2), GUILayout.Width(25), GUILayout.Height(35))) { if (!Flags.toggleLaneArrowFlags((uint)laneList[i][0], Flags.LaneArrows.Forward) && SelectedNodeId > 0) { MainTool.ShowTooltip(Translation.GetString("Lane_Arrow_Changer_Disabled"), Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId].m_position); } } if (GUILayout.Button("→", ((flags & NetLane.Flags.Right) == NetLane.Flags.Right ? style1 : style2), GUILayout.Width(35), GUILayout.Height(25))) { if (!Flags.toggleLaneArrowFlags((uint)laneList[i][0], Flags.LaneArrows.Right) && SelectedNodeId > 0) { MainTool.ShowTooltip(Translation.GetString("Lane_Arrow_Changer_Disabled"), Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId].m_position); } } GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.EndVertical(); } GUILayout.EndHorizontal(); GUILayout.BeginVertical(); bool startNode = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].m_startNode == SelectedNodeId; if (!geometry.AreHighwayRulesEnabled(startNode)) { if (!geometry.IsOneWay()) { Flags.setUTurnAllowed(SelectedSegmentId, startNode, GUILayout.Toggle(Flags.getUTurnAllowed(SelectedSegmentId, startNode), Translation.GetString("Allow_u-turns") + " (BETA feature)", new GUILayoutOption[] { })); } if (geometry.HasOutgoingStraightSegment(SelectedNodeId)) { Flags.setStraightLaneChangingAllowed(SelectedSegmentId, startNode, GUILayout.Toggle(Flags.getStraightLaneChangingAllowed(SelectedSegmentId, startNode), Translation.GetString("Allow_lane_changing_for_vehicles_going_straight"), new GUILayoutOption[] { })); } Flags.setEnterWhenBlockedAllowed(SelectedSegmentId, startNode, GUILayout.Toggle(Flags.getEnterWhenBlockedAllowed(SelectedSegmentId, startNode), Translation.GetString("Allow_vehicles_to_enter_a_blocked_junction"), new GUILayoutOption[] { })); } GUILayout.EndVertical(); }
protected override void HandleInvalidSegment(SegmentGeometry geometry) { Flags.resetSegmentVehicleRestrictions(geometry.SegmentId); ClearCache(geometry.SegmentId); }
internal void AddSegment(ushort segmentId, bool startNode, bool propagate) { #if DEBUGGEO Log._Debug($"NodeGeometry: Add segment {segmentId}, start? {startNode} @ node {NodeId}"); #endif if (!IsValid()) { //Log.Error($"NodeGeometry: Trying to add segment {segmentId} @ invalid node {NodeId}"); Recalculate(); return; } RemoveSegment(segmentId, false); // fallback: remove segment for (int i = 0; i < 8; ++i) { if (SegmentEndGeometries[i] == null) { SegmentEndGeometries[i] = startNode ? SegmentGeometry.Get(segmentId).StartNodeGeometry : SegmentGeometry.Get(segmentId).EndNodeGeometry; break; } } if (propagate) { RecalculateSegments(segmentId); } Recalculate(); }
private bool drawSignHandles(ushort nodeId, bool viewOnly, bool handleClick, ref Vector3 camPos, out bool stateUpdated) { bool hovered = false; stateUpdated = false; if (viewOnly && !Options.junctionRestrictionsOverlay && MainTool.GetToolMode() != ToolMode.JunctionRestrictions) { return(false); } NetManager netManager = Singleton <NetManager> .instance; var guiColor = GUI.color; Vector3 nodePos = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].m_position; for (int i = 0; i < 8; ++i) { ushort segmentId = netManager.m_nodes.m_buffer[nodeId].GetSegment(i); if (segmentId == 0) { continue; } SegmentGeometry geometry = SegmentGeometry.Get(segmentId); if (geometry == null) { Log.Error($"JunctionRestrictionsTool.drawSignHandles: No geometry information available for segment {segmentId}"); continue; } bool startNode = geometry.StartNodeId() == nodeId; bool incoming = geometry.IsIncoming(startNode); int numSignsPerRow = incoming ? 2 : 1; NetInfo segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info; ItemClass connectionClass = segmentInfo.GetConnectionClass(); if (connectionClass.m_service != ItemClass.Service.Road) { continue; // only for road junctions } // draw all junction restriction signs Vector3 segmentCenterPos = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_bounds.center; Vector3 yu = (segmentCenterPos - nodePos).normalized; Vector3 xu = Vector3.Cross(yu, new Vector3(0, 1f, 0)).normalized; float f = viewOnly ? 6f : 7f; // reserved sign size in game coordinates Vector3 centerStart = nodePos + yu * (viewOnly ? 5f : 14f); Vector3 zero = centerStart - 0.5f * (float)(numSignsPerRow - 1) * f * xu; // "top left" if (viewOnly) { if (Constants.ServiceFactory.SimulationService.LeftHandDrive) { zero -= xu * 8f; } else { zero += xu * 8f; } } bool signHovered; int x = 0; int y = 0; // draw "lane-changing when going straight allowed" sign at (0; 0) bool allowed = JunctionRestrictionsManager.Instance.IsLaneChangingAllowedWhenGoingStraight(segmentId, startNode); if (incoming && (!viewOnly || allowed != Options.allowLaneChangesWhileGoingStraight)) { DrawSign(viewOnly, ref camPos, ref xu, ref yu, f, ref zero, x, y, ref guiColor, allowed ? TextureResources.LaneChangeAllowedTexture2D : TextureResources.LaneChangeForbiddenTexture2D, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { JunctionRestrictionsManager.Instance.ToggleLaneChangingAllowedWhenGoingStraight(segmentId, startNode); stateUpdated = true; } } if (viewOnly) { ++y; } else { ++x; } } // draw "u-turns allowed" sign at (1; 0) allowed = JunctionRestrictionsManager.Instance.IsUturnAllowed(segmentId, startNode); if (incoming && (!viewOnly || allowed != Options.allowUTurns)) { DrawSign(viewOnly, ref camPos, ref xu, ref yu, f, ref zero, x, y, ref guiColor, allowed ? TextureResources.UturnAllowedTexture2D : TextureResources.UturnForbiddenTexture2D, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { if (!JunctionRestrictionsManager.Instance.ToggleUturnAllowed(segmentId, startNode)) { // TODO MainTool.ShowTooltip(Translation.GetString("..."), Singleton<NetManager>.instance.m_nodes.m_buffer[nodeId].m_position); } else { stateUpdated = true; } } } ++y; x = 0; } // draw "entering blocked junctions allowed" sign at (0; 1) allowed = JunctionRestrictionsManager.Instance.IsEnteringBlockedJunctionAllowed(segmentId, startNode); if (incoming && (!viewOnly || allowed != Options.allowEnterBlockedJunctions)) { DrawSign(viewOnly, ref camPos, ref xu, ref yu, f, ref zero, x, y, ref guiColor, allowed ? TextureResources.EnterBlockedJunctionAllowedTexture2D : TextureResources.EnterBlockedJunctionForbiddenTexture2D, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { JunctionRestrictionsManager.Instance.ToggleEnteringBlockedJunctionAllowed(segmentId, startNode); stateUpdated = true; } } if (viewOnly) { ++y; } else { ++x; } } // draw "pedestrian crossing allowed" sign at (1; 1) allowed = JunctionRestrictionsManager.Instance.IsPedestrianCrossingAllowed(segmentId, startNode); if (!viewOnly || !allowed) { DrawSign(viewOnly, ref camPos, ref xu, ref yu, f, ref zero, x, y, ref guiColor, allowed ? TextureResources.PedestrianCrossingAllowedTexture2D : TextureResources.PedestrianCrossingForbiddenTexture2D, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { JunctionRestrictionsManager.Instance.TogglePedestrianCrossingAllowed(segmentId, startNode); stateUpdated = true; } } } } guiColor.a = 1f; GUI.color = guiColor; return(hovered); }
internal void Recalculate(bool propagate) { #if DEBUG //Log._Debug($"SegmentEndGeometry: Recalculate seg. {SegmentId} @ node {NodeId()}, propagate={propagate}"); #endif ushort nodeIdBeforeRecalc = LastKnownNodeId; Cleanup(); if (!IsValid()) { if (nodeIdBeforeRecalc != 0) { NodeGeometry.Get(nodeIdBeforeRecalc).RemoveSegment(SegmentId, propagate); } return; } NetManager netManager = Singleton <NetManager> .instance; ushort nodeId = NodeId(); LastKnownNodeId = nodeId; bool oneway; bool outgoingOneWay; SegmentGeometry.calculateOneWayAtNode(SegmentId, nodeId, out oneway, out outgoingOneWay); OutgoingOneWay = outgoingOneWay; if (oneway && !OutgoingOneWay) { IncomingOneWay = true; } OnlyHighways = true; //ItemClass connectionClass = netManager.m_segments.m_buffer[SegmentId].Info.GetConnectionClass(); bool hasOtherSegments = false; for (var s = 0; s < 8; s++) { ushort otherSegmentId = netManager.m_nodes.m_buffer[nodeId].GetSegment(s); if (otherSegmentId == 0 || otherSegmentId == SegmentId || !SegmentGeometry.IsValid(otherSegmentId)) { continue; } /*ItemClass otherConnectionClass = Singleton<NetManager>.instance.m_segments.m_buffer[otherSegmentId].Info.GetConnectionClass(); * if (otherConnectionClass.m_service != connectionClass.m_service) * continue;*/ hasOtherSegments = true; // determine geometry bool otherIsOneWay; bool otherIsOutgoingOneWay; SegmentGeometry.calculateOneWayAtNode(otherSegmentId, nodeId, out otherIsOneWay, out otherIsOutgoingOneWay); if (!(SegmentGeometry.calculateIsHighway(otherSegmentId) && otherIsOneWay)) { OnlyHighways = false; } if (IsRightSegment(SegmentId, otherSegmentId, nodeId)) { RightSegments[NumRightSegments++] = otherSegmentId; if (!otherIsOutgoingOneWay) { IncomingRightSegments[NumIncomingRightSegments++] = otherSegmentId; if (!otherIsOneWay) { OutgoingRightSegments[NumOutgoingRightSegments++] = otherSegmentId; } } else { OutgoingRightSegments[NumOutgoingRightSegments++] = otherSegmentId; } } else if (IsLeftSegment(SegmentId, otherSegmentId, nodeId)) { LeftSegments[NumLeftSegments++] = otherSegmentId; if (!otherIsOutgoingOneWay) { IncomingLeftSegments[NumIncomingLeftSegments++] = otherSegmentId; if (!otherIsOneWay) { OutgoingLeftSegments[NumOutgoingLeftSegments++] = otherSegmentId; } } else { OutgoingLeftSegments[NumOutgoingLeftSegments++] = otherSegmentId; } } else { StraightSegments[NumStraightSegments++] = otherSegmentId; if (!otherIsOutgoingOneWay) { IncomingStraightSegments[NumIncomingStraightSegments++] = otherSegmentId; if (!otherIsOneWay) { OutgoingStraightSegments[NumOutgoingStraightSegments++] = otherSegmentId; } } else { OutgoingStraightSegments[NumOutgoingStraightSegments++] = otherSegmentId; } } // reset highway lane arrows Flags.removeHighwayLaneArrowFlagsAtSegment(otherSegmentId); // TODO refactor ConnectedSegments[NumConnectedSegments++] = otherSegmentId; } NumIncomingSegments = (byte)(NumIncomingLeftSegments + NumIncomingStraightSegments + NumIncomingRightSegments); NumOutgoingSegments = (byte)(NumOutgoingLeftSegments + NumOutgoingStraightSegments + NumOutgoingRightSegments); if (!hasOtherSegments) { OnlyHighways = false; } // propagate information to other segments if (nodeIdBeforeRecalc != nodeId) { if (nodeIdBeforeRecalc != 0) { NodeGeometry.Get(nodeIdBeforeRecalc).RemoveSegment(SegmentId, propagate); } NodeGeometry.Get(nodeId).AddSegment(SegmentId, StartNode, propagate); } }
public SegmentGeometry GetSegmentGeometry() { return(SegmentGeometry.Get(SegmentId)); }
/// <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 (!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.IsValid()) { #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; } foreach (ushort connectedSegmentId in connectedSegmentIds) { if (connectedSegmentId == 0) { continue; } Direction dir = segmentGeo.GetDirection(connectedSegmentId, 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 Direction.Turn: default: continue; case Direction.Forward: if ((arrows & Flags.LaneArrows.Forward) != Flags.LaneArrows.None) { continue; } break; case Direction.Left: if ((arrows & Flags.LaneArrows.Left) != Flags.LaneArrows.None) { continue; } break; case Direction.Right: if ((arrows & Flags.LaneArrows.Right) != Flags.LaneArrows.None) { continue; } break; } #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[connectedSegmentId].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 Direction.Turn: default: continue; case Direction.Forward: arrows |= Flags.LaneArrows.Forward; break; case Direction.Left: arrows |= Flags.LaneArrows.Left; break; case Direction.Right: arrows |= Flags.LaneArrows.Right; break; } #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 Flags.setLaneArrowFlags(laneId, arrows, true); }
public override void OnLoadData() { Log.Info("Loading Traffic Manager: PE Data"); StateLoading = true; bool loadingSucceeded = true; try { Log.Info("Initializing flags"); Flags.OnBeforeLoadData(); } catch (Exception e) { Log.Error($"OnLoadData: Error while initializing Flags: {e.ToString()}"); loadingSucceeded = false; } try { Log.Info("Initializing node geometries"); NodeGeometry.OnBeforeLoadData(); } catch (Exception e) { Log.Error($"OnLoadData: Error while initializing NodeGeometry: {e.ToString()}"); loadingSucceeded = false; } try { Log.Info("Initializing segment geometries"); SegmentGeometry.OnBeforeLoadData(); } catch (Exception e) { Log.Error($"OnLoadData: Error while initializing SegmentGeometry: {e.ToString()}"); loadingSucceeded = false; } foreach (ICustomManager manager in LoadingExtension.RegisteredManagers) { try { Log.Info($"OnBeforeLoadData: {manager.GetType().Name}"); manager.OnBeforeLoadData(); } catch (Exception e) { Log.Error($"OnLoadData: Error while initializing {manager.GetType().Name}: {e.ToString()}"); loadingSucceeded = false; } } Log.Info("Initialization done. Loading mod data now."); try { byte[] data = _serializableData.LoadData(DataId); DeserializeData(data); } catch (Exception e) { Log.Error($"OnLoadData: Error while deserializing data: {e.ToString()}"); loadingSucceeded = false; } // load options try { byte[] options = _serializableData.LoadData("TMPE_Options"); if (options != null) { if (!OptionsManager.Instance.LoadData(options)) { loadingSucceeded = false; } } } catch (Exception e) { Log.Error($"OnLoadData: Error while loading options: {e.ToString()}"); loadingSucceeded = false; } if (loadingSucceeded) { Log.Info("OnLoadData completed successfully."); } else { Log.Info("An error occurred while loading."); //UIView.library.ShowModal<ExceptionPanel>("ExceptionPanel").SetMessage("An error occurred while loading", "Traffic Manager: President Edition detected an error while loading. Please do NOT save this game under the old filename, otherwise your timed traffic lights, custom lane arrows, etc. are in danger. Instead, please navigate to http://steamcommunity.com/sharedfiles/filedetails/?id=583429740 and follow the steps under 'In case problems arise'.", true); } StateLoading = false; foreach (ICustomManager manager in LoadingExtension.RegisteredManagers) { try { Log.Info($"OnAfterLoadData: {manager.GetType().Name}"); manager.OnAfterLoadData(); } catch (Exception e) { Log.Error($"OnLoadData: Error while initializing {manager.GetType().Name}: {e.ToString()}"); loadingSucceeded = false; } } }
private void _guiLaneChangeWindow(int num) { var info = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info; IList <LanePos> laneList = Constants.ServiceFactory.NetService.GetSortedLanes(SelectedSegmentId, ref Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId], Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].m_startNode == SelectedNodeId, LaneArrowManager.LANE_TYPES, LaneArrowManager.VEHICLE_TYPES, true); SegmentGeometry geometry = SegmentGeometry.Get(SelectedSegmentId); if (geometry == null) { Log.Error($"LaneArrowTool._guiLaneChangeWindow: No geometry information available for segment {SelectedSegmentId}"); return; } bool startNode = geometry.StartNodeId() == SelectedNodeId; GUILayout.BeginHorizontal(); for (var i = 0; i < laneList.Count; i++) { var flags = (NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[laneList[i].laneId].m_flags; var style1 = new GUIStyle("button"); var style2 = new GUIStyle("button") { normal = { textColor = new Color32(255, 0, 0, 255) }, hover = { textColor = new Color32(255, 0, 0, 255) }, focused = { textColor = new Color32(255, 0, 0, 255) } }; var laneStyle = new GUIStyle { contentOffset = new Vector2(12f, 0f) }; var laneTitleStyle = new GUIStyle { contentOffset = new Vector2(36f, 2f), normal = { textColor = new Color(1f, 1f, 1f) } }; GUILayout.BeginVertical(laneStyle); GUILayout.Label(Translation.GetString("Lane") + " " + (i + 1), laneTitleStyle); GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); if (!Flags.applyLaneArrowFlags(laneList[i].laneId)) { Flags.removeLaneArrowFlags(laneList[i].laneId); } Flags.LaneArrowChangeResult res = Flags.LaneArrowChangeResult.Invalid; bool buttonClicked = false; if (GUILayout.Button("←", ((flags & NetLane.Flags.Left) == NetLane.Flags.Left ? style1 : style2), GUILayout.Width(35), GUILayout.Height(25))) { buttonClicked = true; LaneArrowManager.Instance.ToggleLaneArrows(laneList[i].laneId, startNode, Flags.LaneArrows.Left, out res); } if (GUILayout.Button("↑", ((flags & NetLane.Flags.Forward) == NetLane.Flags.Forward ? style1 : style2), GUILayout.Width(25), GUILayout.Height(35))) { buttonClicked = true; LaneArrowManager.Instance.ToggleLaneArrows(laneList[i].laneId, startNode, Flags.LaneArrows.Forward, out res); } if (GUILayout.Button("→", ((flags & NetLane.Flags.Right) == NetLane.Flags.Right ? style1 : style2), GUILayout.Width(35), GUILayout.Height(25))) { buttonClicked = true; LaneArrowManager.Instance.ToggleLaneArrows(laneList[i].laneId, startNode, Flags.LaneArrows.Right, out res); } if (buttonClicked) { switch (res) { case Flags.LaneArrowChangeResult.Invalid: case Flags.LaneArrowChangeResult.Success: default: break; case Flags.LaneArrowChangeResult.HighwayArrows: MainTool.ShowTooltip(Translation.GetString("Lane_Arrow_Changer_Disabled_Highway")); break; case Flags.LaneArrowChangeResult.LaneConnection: MainTool.ShowTooltip(Translation.GetString("Lane_Arrow_Changer_Disabled_Connection")); break; } } GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.EndVertical(); } GUILayout.EndHorizontal(); }