public override void RenderOverlay(RenderManager.CameraInfo cameraInfo) { //Log._Debug($"TppLaneConnectorTool: RenderOverlay. SelectedNodeId={SelectedNodeId} SelectedSegmentId={SelectedSegmentId} HoveredNodeId={HoveredNodeId} HoveredSegmentId={HoveredSegmentId} IsInsideUI={MainTool.GetToolController().IsInsideUI}"); // draw lane markers and connections hoveredMarker = null; ShowOverlay(false, cameraInfo); // draw bezier from source marker to mouse position in target marker selection if (SelectedNodeId != 0) { if (GetMarkerSelectionMode() == MarkerSelectionMode.SelectTarget) { Vector3 selNodePos = NetManager.instance.m_nodes.m_buffer[SelectedNodeId].m_position; ToolBase.RaycastOutput output; if (RayCastSegmentAndNode(out output)) { RenderLane(cameraInfo, selectedMarker.position, output.m_hitPos, selNodePos, selectedMarker.color); } } if (Input.GetKey(KeyCode.Delete)) { // remove all connections at selected node List <NodeLaneMarker> nodeMarkers = GetNodeMarkers(SelectedNodeId); if (nodeMarkers != null) { selectedMarker = null; foreach (NodeLaneMarker sourceLaneMarker in nodeMarkers) { foreach (NodeLaneMarker targetLaneMarker in sourceLaneMarker.connectedMarkers) { LaneConnectionManager.Instance().RemoveLaneConnection(sourceLaneMarker.laneId, targetLaneMarker.laneId, sourceLaneMarker.startNode); } } } RefreshCurrentNodeMarkers(); } } if (GetMarkerSelectionMode() == MarkerSelectionMode.None && HoveredNodeId != 0) { // draw hovered node MainTool.DrawNodeCircle(cameraInfo, HoveredNodeId, Input.GetMouseButton(0)); } }
/// <summary> /// Removes lane connections that exist between two given lanes /// </summary> /// <param name="lane1Id"></param> /// <param name="lane2Id"></param> /// <param name="startNode1"></param> /// <returns></returns> internal static bool RemoveLaneConnection(uint lane1Id, uint lane2Id, bool startNode1) { if (!IsInitDone()) { return(false); } bool lane1Valid = CheckLane(lane1Id); bool lane2Valid = CheckLane(lane2Id); bool ret = false; if (!lane1Valid) { // remove all incoming/outgoing lane connections RemoveLaneConnections(lane1Id); ret = true; } if (!lane2Valid) { // remove all incoming/outgoing lane connections RemoveLaneConnections(lane2Id); ret = true; } if (lane1Valid || lane2Valid) { ushort commonNodeId; bool startNode2; LaneConnectionManager.Instance().GetCommonNodeId(lane1Id, lane2Id, startNode1, out commonNodeId, out startNode2); // TODO refactor if (CleanupLaneConnections(lane1Id, lane2Id, startNode1)) { ret = true; } if (CleanupLaneConnections(lane2Id, lane1Id, startNode2)) { ret = true; } } return(ret); }
/// <summary> /// adds lane connections between two given lanes /// </summary> /// <param name="lane1Id"></param> /// <param name="lane2Id"></param> /// <param name="startNode1"></param> /// <returns></returns> internal static bool AddLaneConnection(uint lane1Id, uint lane2Id, bool startNode1) { if (!IsInitDone()) { return(false); } bool lane1Valid = CheckLane(lane1Id); bool lane2Valid = CheckLane(lane2Id); if (!lane1Valid) { // remove all incoming/outgoing lane connections RemoveLaneConnections(lane1Id); } if (!lane2Valid) { // remove all incoming/outgoing lane connections RemoveLaneConnections(lane2Id); } if (!lane1Valid || !lane2Valid) { return(false); } ushort commonNodeId; bool startNode2; LaneConnectionManager.Instance().GetCommonNodeId(lane1Id, lane2Id, startNode1, out commonNodeId, out startNode2); // TODO refactor if (commonNodeId != 0) { CreateLaneConnection(lane1Id, lane2Id, startNode1); CreateLaneConnection(lane2Id, lane1Id, startNode2); return(true); } else { return(false); } }
public static bool toggleLaneArrowFlags(uint laneId, bool startNode, LaneArrows flags, out LaneArrowChangeResult res) { if (!mayHaveLaneArrows(laneId)) { removeLaneArrowFlags(laneId); res = LaneArrowChangeResult.Invalid; return(false); } if (highwayLaneArrowFlags[laneId] != null) { res = LaneArrowChangeResult.HighwayArrows; return(false); // disallow custom lane arrows in highway rule mode } if (LaneConnectionManager.Instance().HasConnections(laneId, startNode)) // TODO refactor { res = LaneArrowChangeResult.LaneConnection; return(false); // custom lane connection present } LaneArrows?arrows = laneArrowFlags[laneId]; if (arrows == null) { // read currently defined arrows uint laneFlags = (uint)Singleton <NetManager> .instance.m_lanes.m_buffer[laneId].m_flags; laneFlags &= lfr; // filter arrows arrows = (LaneArrows)laneFlags; } arrows ^= flags; laneArrowFlags[laneId] = arrows; applyLaneArrowFlags(laneId, false); res = LaneArrowChangeResult.Success; return(true); }
/// <summary> /// Displays vehicle ids over vehicles /// </summary> private void _guiVehicles() { GUIStyle _counterStyle = new GUIStyle(); Array16 <Vehicle> vehicles = Singleton <VehicleManager> .instance.m_vehicles; LaneConnectionManager connManager = LaneConnectionManager.Instance(); SimulationManager simManager = Singleton <SimulationManager> .instance; NetManager netManager = Singleton <NetManager> .instance; VehicleStateManager vehStateManager = VehicleStateManager.Instance(); for (int i = 1; i < vehicles.m_size; ++i) { Vehicle vehicle = vehicles.m_buffer[i]; if (vehicle.m_flags == 0) // node is unused { continue; } Vector3 vehPos = vehicle.GetLastFramePosition(); var screenPos = Camera.main.WorldToScreenPoint(vehPos); screenPos.y = Screen.height - screenPos.y; if (screenPos.z < 0) { continue; } var camPos = simManager.m_simulationView.m_position; var diff = vehPos - camPos; if (diff.magnitude > DebugCloseLod) { continue; // do not draw if too distant } var zoom = 1.0f / diff.magnitude * 150f; _counterStyle.fontSize = (int)(10f * zoom); _counterStyle.normal.textColor = new Color(1f, 1f, 1f); //_counterStyle.normal.background = MakeTex(1, 1, new Color(0f, 0f, 0f, 0.4f)); VehicleState vState = vehStateManager._GetVehicleState((ushort)i); PathUnit.Position?curPos = vState?.GetCurrentPathPosition(ref vehicle); PathUnit.Position?nextPos = vState?.GetNextPathPosition(ref vehicle); bool? startNode = vState?.CurrentSegmentEnd?.StartNode; ushort?segmentId = vState?.CurrentSegmentEnd?.SegmentId; ushort?transitNodeId = vState?.CurrentSegmentEnd?.NodeId; /*float distanceToTransitNode = Single.NaN; * float timeToTransitNode = Single.NaN;*/ ushort vehSpeed = SpeedLimitManager.Instance().VehicleToCustomSpeed(vehicle.GetLastFrameVelocity().magnitude); Vector3?targetPos = null; if (transitNodeId != null) { targetPos = netManager.m_nodes.m_buffer[(ushort)transitNodeId].m_position; } /*if (transitNodeId != null && segmentId != null && startNode != null && curPos != null) { * bool outgoing = false; * connManager.GetLaneEndPoint((ushort)segmentId, (bool)startNode, ((PathUnit.Position)curPos).m_lane, null, null, out outgoing, out targetPos); * }*/ float distanceToTransitNode = Single.NaN; if (targetPos != null) { distanceToTransitNode = ((Vector3)targetPos - vehPos).magnitude; /*if (vehSpeed > 0) * timeToTransitNode = distanceToTransitNode / vehSpeed; * else * timeToTransitNode = Single.PositiveInfinity;*/ } String labelStr = "V #" + i + " is a " + (vState.Valid ? "valid" : "invalid") + " " + vState.VehicleType + " @ ~" + vehSpeed + " km/h (" + vState.JunctionTransitState + ") dist: " + distanceToTransitNode; #if USEPATHWAITCOUNTER labelStr += ", pwc: " + vState.PathWaitCounter + ", seg. " + vState.CurrentSegmentEnd?.SegmentId; #endif //String labelStr = "Veh. " + i + " @ " + String.Format("{0:0.##}", vehSpeed) + "/" + (vState != null ? vState.CurrentMaxSpeed.ToString() : "-") + " (" + (vState != null ? vState.VehicleType.ToString() : "-") + ", valid? " + (vState != null ? vState.Valid.ToString() : "-") + ")" + ", len: " + (vState != null ? vState.TotalLength.ToString() : "-") + ", state: " + (vState != null ? vState.JunctionTransitState.ToString() : "-"); #if PATHRECALC labelStr += ", recalc: " + (vState != null ? vState.LastPathRecalculation.ToString() : "-"); #endif //labelStr += "\npos: " + curPos?.m_segment + "(" + curPos?.m_lane + ")->" + nextPos?.m_segment + "(" + nextPos?.m_lane + ")" /* + ", dist: " + distanceToTransitNode + ", time: " + timeToTransitNode*/ + ", last update: " + vState?.LastPositionUpdate; Vector2 dim = _counterStyle.CalcSize(new GUIContent(labelStr)); Rect labelRect = new Rect(screenPos.x - dim.x / 2f, screenPos.y - dim.y - 50f, dim.x, dim.y); GUI.Box(labelRect, labelStr, _counterStyle); //_counterStyle.normal.background = null; } }
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; } try { Log.Info("Initializing lane connection manager"); LaneConnectionManager.Instance().OnBeforeLoadData(); // requires segment geometries } catch (Exception e) { Log.Error($"OnLoadData: Error while initializing LaneConnectionManager: {e.ToString()}"); loadingSucceeded = false; } try { Log.Info("Initializing CustomRoadAI"); CustomRoadAI.OnBeforeLoadData(); } catch (Exception e) { Log.Error($"OnLoadData: Error while initializing CustomRoadAI: {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 (options.Length >= 1) { Options.setSimAccuracy(options[0]); } if (options.Length >= 2) { //Options.setLaneChangingRandomization(options[1]); } if (options.Length >= 3) { Options.setRecklessDrivers(options[2]); } if (options.Length >= 4) { Options.setRelaxedBusses(options[3] == (byte)1); } if (options.Length >= 5) { Options.setNodesOverlay(options[4] == (byte)1); } if (options.Length >= 6) { Options.setMayEnterBlockedJunctions(options[5] == (byte)1); } if (options.Length >= 7) { #if !TAM if (!LoadingExtension.IsPathManagerCompatible) { Options.setAdvancedAI(false); } else { #endif Options.setAdvancedAI(options[6] == (byte)1); #if !TAM } #endif } if (options.Length >= 8) { Options.setHighwayRules(options[7] == (byte)1); } if (options.Length >= 9) { Options.setPrioritySignsOverlay(options[8] == (byte)1); } if (options.Length >= 10) { Options.setTimedLightsOverlay(options[9] == (byte)1); } if (options.Length >= 11) { Options.setSpeedLimitsOverlay(options[10] == (byte)1); } if (options.Length >= 12) { Options.setVehicleRestrictionsOverlay(options[11] == (byte)1); } if (options.Length >= 13) { Options.setStrongerRoadConditionEffects(options[12] == (byte)1); } if (options.Length >= 14) { Options.setAllowUTurns(options[13] == (byte)1); } if (options.Length >= 15) { Options.setAllowLaneChangesWhileGoingStraight(options[14] == (byte)1); } if (options.Length >= 16) { Options.setEnableDespawning(options[15] == (byte)1); } if (options.Length >= 17) { Options.setDynamicPathRecalculation(options[16] == (byte)1); } if (options.Length >= 18) { Options.setConnectedLanesOverlay(options[17] == (byte)1); } if (options.Length >= 19) { Options.setPrioritySignsEnabled(options[18] == (byte)1); } if (options.Length >= 20) { Options.setTimedLightsEnabled(options[19] == (byte)1); } if (options.Length >= 21) { Options.setCustomSpeedLimitsEnabled(options[20] == (byte)1); } if (options.Length >= 22) { Options.setVehicleRestrictionsEnabled(options[21] == (byte)1); } if (options.Length >= 23) { Options.setLaneConnectorEnabled(options[22] == (byte)1); } if (options.Length >= 24) { Options.setJunctionRestrictionsOverlay(options[23] == (byte)1); } if (options.Length >= 25) { Options.setJunctionRestrictionsEnabled(options[24] == (byte)1); } } } 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; }
private static void LoadDataState(out bool error) { error = false; Log.Info("Loading State from Config"); if (_configuration == null) { Log.Warning("Configuration NULL, Couldn't load save data. Possibly a new game?"); return; } TrafficPriorityManager prioMan = TrafficPriorityManager.Instance(); // load priority segments if (_configuration.PrioritySegments != null) { Log.Info($"Loading {_configuration.PrioritySegments.Count()} priority segments"); foreach (var segment in _configuration.PrioritySegments) { try { if (segment.Length < 3) { continue; } #if DEBUG bool debug = segment[0] == 13630; #endif if ((SegmentEnd.PriorityType)segment[2] == SegmentEnd.PriorityType.None) { #if DEBUG if (debug) { Log._Debug($"Loading priority segment: Not adding 'None' priority segment: {segment[1]} @ node {segment[0]}"); } #endif continue; } if (!NetUtil.IsNodeValid((ushort)segment[0])) { #if DEBUG if (debug) { Log._Debug($"Loading priority segment: node {segment[0]} is invalid"); } #endif continue; } if (!NetUtil.IsSegmentValid((ushort)segment[1])) { #if DEBUG if (debug) { Log._Debug($"Loading priority segment: segment {segment[1]} @ node {segment[0]} is invalid"); } #endif continue; } if (prioMan.IsPrioritySegment((ushort)segment[0], (ushort)segment[1])) { #if DEBUG if (debug) { Log._Debug($"Loading priority segment: segment {segment[1]} @ node {segment[0]} is already a priority segment"); } #endif prioMan.GetPrioritySegment((ushort)segment[0], (ushort)segment[1]).Type = (SegmentEnd.PriorityType)segment[2]; continue; } #if DEBUG Log._Debug($"Adding Priority Segment of type: {segment[2].ToString()} to segment {segment[1]} @ node {segment[0]}"); #endif prioMan.AddPrioritySegment((ushort)segment[0], (ushort)segment[1], (SegmentEnd.PriorityType)segment[2]); } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading data from Priority segments: " + e.ToString()); error = true; } } } else { Log.Warning("Priority segments data structure undefined!"); } // load vehicle restrictions (warning: has to be done before loading timed lights!) if (_configuration.LaneAllowedVehicleTypes != null) { Log.Info($"Loading lane vehicle restriction data. {_configuration.LaneAllowedVehicleTypes.Count} elements"); foreach (Configuration.LaneVehicleTypes laneVehicleTypes in _configuration.LaneAllowedVehicleTypes) { try { ExtVehicleType baseMask = VehicleRestrictionsManager.Instance().GetBaseMask(laneVehicleTypes.laneId); ExtVehicleType maskedType = laneVehicleTypes.vehicleTypes & baseMask; Log._Debug($"Loading lane vehicle restriction: lane {laneVehicleTypes.laneId} = {laneVehicleTypes.vehicleTypes}, masked = {maskedType}"); if (maskedType != baseMask) { Flags.setLaneAllowedVehicleTypes(laneVehicleTypes.laneId, maskedType); } else { Log._Debug($"Masked type does not differ from base type. Ignoring."); } } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading data from vehicle restrictions: " + e.ToString()); error = true; } } } else { Log.Warning("Vehicle restrctions structure undefined!"); } NetManager netManager = Singleton <NetManager> .instance; TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance(); if (_configuration.TimedLights != null) { Log.Info($"Loading {_configuration.TimedLights.Count()} timed traffic lights (new method)"); foreach (Configuration.TimedTrafficLights cnfTimedLights in _configuration.TimedLights) { try { if (!NetUtil.IsNodeValid(cnfTimedLights.nodeId)) { continue; } Flags.setNodeTrafficLight(cnfTimedLights.nodeId, true); Log._Debug($"Adding Timed Node at node {cnfTimedLights.nodeId}"); TrafficLightSimulation sim = tlsMan.AddNodeToSimulation(cnfTimedLights.nodeId); sim.SetupTimedTrafficLight(cnfTimedLights.nodeGroup); var timedNode = sim.TimedLight; int j = 0; foreach (Configuration.TimedTrafficLightsStep cnfTimedStep in cnfTimedLights.timedSteps) { Log._Debug($"Loading timed step {j} at node {cnfTimedLights.nodeId}"); TimedTrafficLightsStep step = timedNode.AddStep(cnfTimedStep.minTime, cnfTimedStep.maxTime, cnfTimedStep.waitFlowBalance); foreach (KeyValuePair <ushort, Configuration.CustomSegmentLights> e in cnfTimedStep.segmentLights) { Log._Debug($"Loading timed step {j}, segment {e.Key} at node {cnfTimedLights.nodeId}"); CustomSegmentLights lights = null; if (!step.segmentLights.TryGetValue(e.Key, out lights)) { Log._Debug($"No segment lights found at timed step {j} for segment {e.Key}, node {cnfTimedLights.nodeId}"); continue; } Configuration.CustomSegmentLights cnfLights = e.Value; Log._Debug($"Loading pedestrian light @ seg. {e.Key}, step {j}: {cnfLights.pedestrianLightState} {cnfLights.manualPedestrianMode}"); lights.ManualPedestrianMode = cnfLights.manualPedestrianMode; lights.PedestrianLightState = cnfLights.pedestrianLightState; foreach (KeyValuePair <ExtVehicleType, Configuration.CustomSegmentLight> e2 in cnfLights.customLights) { Log._Debug($"Loading timed step {j}, segment {e.Key}, vehicleType {e2.Key} at node {cnfTimedLights.nodeId}"); CustomSegmentLight light = null; if (!lights.CustomLights.TryGetValue(e2.Key, out light)) { Log._Debug($"No segment light found for timed step {j}, segment {e.Key}, vehicleType {e2.Key} at node {cnfTimedLights.nodeId}"); continue; } Configuration.CustomSegmentLight cnfLight = e2.Value; light.CurrentMode = (CustomSegmentLight.Mode)cnfLight.currentMode; light.LightLeft = cnfLight.leftLight; light.LightMain = cnfLight.mainLight; light.LightRight = cnfLight.rightLight; } } ++j; } if (cnfTimedLights.started) { timedNode.Start(); } } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading data from TimedNode (new method): " + e.ToString()); error = true; } } } else { Log.Warning("Timed traffic lights data structure undefined!"); } if (_configuration.NodeTrafficLights != null) { var trafficLightDefs = _configuration.NodeTrafficLights.Split(','); Log.Info($"Loading junction traffic light data"); // new method foreach (var split in trafficLightDefs.Select(def => def.Split(':')).Where(split => split.Length > 1)) { try { Log._Debug($"Traffic light split data: {split[0]} , {split[1]}"); var nodeId = Convert.ToUInt16(split[0]); uint flag = Convert.ToUInt16(split[1]); Flags.setNodeTrafficLight(nodeId, flag > 0); } catch (Exception e) { // ignore as it's probably bad save data. Log.Error($"Error setting the NodeTrafficLights: " + e.ToString()); error = true; } } } else { Log.Warning("Junction traffic lights data structure undefined!"); } if (_configuration.LaneFlags != null) { Log.Info($"Loading lane arrow data"); #if DEBUG Log._Debug($"LaneFlags: {_configuration.LaneFlags}"); #endif var lanes = _configuration.LaneFlags.Split(','); if (lanes.Length > 1) { foreach (var split in lanes.Select(lane => lane.Split(':')).Where(split => split.Length > 1)) { try { Log._Debug($"Split Data: {split[0]} , {split[1]}"); var laneId = Convert.ToUInt32(split[0]); uint flags = Convert.ToUInt32(split[1]); //make sure we don't cause any overflows because of bad save data. if (Singleton <NetManager> .instance.m_lanes.m_buffer.Length <= laneId) { continue; } if (flags > ushort.MaxValue) { continue; } if (!NetUtil.IsLaneValid(laneId)) { continue; } //Singleton<NetManager>.instance.m_lanes.m_buffer[laneId].m_flags = fixLaneFlags(Singleton<NetManager>.instance.m_lanes.m_buffer[laneId].m_flags); uint laneArrowFlags = flags & Flags.lfr; uint origFlags = (Singleton <NetManager> .instance.m_lanes.m_buffer[laneId].m_flags & Flags.lfr); #if DEBUG Log._Debug("Setting flags for lane " + laneId + " to " + flags + " (" + ((Flags.LaneArrows)(laneArrowFlags)).ToString() + ")"); if ((origFlags | laneArrowFlags) == origFlags) // only load if setting differs from default { Log._Debug("Flags for lane " + laneId + " are original (" + ((NetLane.Flags)(origFlags)).ToString() + ")"); } #endif Flags.setLaneArrowFlags(laneId, (Flags.LaneArrows)(laneArrowFlags)); } catch (Exception e) { Log.Error($"Error loading Lane Split data. Length: {split.Length} value: {split}\nError: {e.ToString()}"); error = true; } } } } else { Log.Warning("Lane arrow data structure undefined!"); } // load lane connections if (_configuration.LaneConnections != null) { Log.Info($"Loading {_configuration.LaneConnections.Count()} lane connections"); foreach (Configuration.LaneConnection conn in _configuration.LaneConnections) { try { Log._Debug($"Loading lane connection: lane {conn.lowerLaneId} -> {conn.higherLaneId}"); LaneConnectionManager.Instance().AddLaneConnection(conn.lowerLaneId, conn.higherLaneId, conn.lowerStartNode); } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Error("Error loading data from lane connection: " + e.ToString()); error = true; } } } else { Log.Warning("Lane connection data structure undefined!"); } // load speed limits if (_configuration.LaneSpeedLimits != null) { Log.Info($"Loading lane speed limit data. {_configuration.LaneSpeedLimits.Count} elements"); foreach (Configuration.LaneSpeedLimit laneSpeedLimit in _configuration.LaneSpeedLimits) { try { Log._Debug($"Loading lane speed limit: lane {laneSpeedLimit.laneId} = {laneSpeedLimit.speedLimit}"); Flags.setLaneSpeedLimit(laneSpeedLimit.laneId, laneSpeedLimit.speedLimit); } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading speed limits: " + e.ToString()); error = true; } } } else { Log.Warning("Lane speed limit structure undefined!"); } // Load segment-at-node flags if (_configuration.SegmentNodeConfs != null) { Log.Info($"Loading segment-at-node data. {_configuration.SegmentNodeConfs.Count} elements"); foreach (Configuration.SegmentNodeConf segNodeConf in _configuration.SegmentNodeConfs) { try { if (!NetUtil.IsSegmentValid(segNodeConf.segmentId)) { continue; } Flags.setSegmentNodeFlags(segNodeConf.segmentId, true, segNodeConf.startNodeFlags); Flags.setSegmentNodeFlags(segNodeConf.segmentId, false, segNodeConf.endNodeFlags); } catch (Exception e) { // ignore, as it's probably corrupt save data. it'll be culled on next save Log.Warning("Error loading segment-at-node config: " + e.ToString()); error = true; } } } else { Log.Warning("Segment-at-node structure undefined!"); } }
private List <NodeLaneMarker> GetNodeMarkers(ushort nodeId) { if (nodeId == 0) { return(null); } if ((NetManager.instance.m_nodes.m_buffer[nodeId].m_flags & NetNode.Flags.Created) == NetNode.Flags.None) { return(null); } List <NodeLaneMarker> nodeMarkers = new List <NodeLaneMarker>(); LaneConnectionManager connManager = LaneConnectionManager.Instance(); int offsetMultiplier = NetManager.instance.m_nodes.m_buffer[nodeId].CountSegments() <= 2 ? 3 : 1; for (int i = 0; i < 8; i++) { ushort segmentId = NetManager.instance.m_nodes.m_buffer[nodeId].GetSegment(i); if (segmentId == 0) { continue; } bool isEndNode = NetManager.instance.m_segments.m_buffer[segmentId].m_endNode == nodeId; Vector3 offset = NetManager.instance.m_segments.m_buffer[segmentId].FindDirection(segmentId, nodeId) * offsetMultiplier; NetInfo.Lane[] lanes = NetManager.instance.m_segments.m_buffer[segmentId].Info.m_lanes; uint laneId = NetManager.instance.m_segments.m_buffer[segmentId].m_lanes; for (byte laneIndex = 0; laneIndex < lanes.Length && laneId != 0; laneIndex++) { if ((lanes[laneIndex].m_laneType & (NetInfo.LaneType.TransportVehicle | NetInfo.LaneType.Vehicle)) != NetInfo.LaneType.None && (lanes[laneIndex].m_vehicleType & (VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train)) != VehicleInfo.VehicleType.None) { Vector3?pos = null; bool isSource = false; if (connManager.GetLaneEndPoint(segmentId, !isEndNode, laneIndex, laneId, lanes[laneIndex], out isSource, out pos)) { nodeMarkers.Add(new NodeLaneMarker() { segmentId = segmentId, laneId = laneId, nodeId = nodeId, startNode = !isEndNode, position = (Vector3)pos + offset, color = colors[nodeMarkers.Count], isSource = isSource, laneType = lanes[laneIndex].m_laneType, vehicleType = lanes[laneIndex].m_vehicleType }); } } laneId = NetManager.instance.m_lanes.m_buffer[laneId].m_nextLane; } } if (nodeMarkers.Count == 0) { return(null); } foreach (NodeLaneMarker laneMarker1 in nodeMarkers) { if (!laneMarker1.isSource) { continue; } uint[] connections = LaneConnectionManager.Instance().GetLaneConnections(laneMarker1.laneId, laneMarker1.startNode); if (connections == null || connections.Length == 0) { continue; } foreach (NodeLaneMarker laneMarker2 in nodeMarkers) { if (laneMarker2.isSource) { continue; } if (connections.Contains(laneMarker2.laneId)) { laneMarker1.connectedMarkers.Add(laneMarker2); } } } return(nodeMarkers); }
public override void OnPrimaryClickOverlay() { #if DEBUGCONN Log._Debug($"TppLaneConnectorTool: OnPrimaryClickOverlay. SelectedNodeId={SelectedNodeId} SelectedSegmentId={SelectedSegmentId} HoveredNodeId={HoveredNodeId} HoveredSegmentId={HoveredSegmentId}"); #endif if (GetMarkerSelectionMode() == MarkerSelectionMode.None) { if (HoveredNodeId != 0) { #if DEBUGCONN Log._Debug($"TppLaneConnectorTool: HoveredNode != 0"); #endif if (NetManager.instance.m_nodes.m_buffer[HoveredNodeId].CountSegments() < 2) { // this node cannot be configured (dead end) #if DEBUGCONN Log._Debug($"TppLaneConnectorTool: Node is a dead end"); #endif SelectedNodeId = 0; selectedMarker = null; return; } if (SelectedNodeId != HoveredNodeId) { #if DEBUGCONN Log._Debug($"Node {HoveredNodeId} has been selected. Creating markers."); #endif // selected node has changed. create markers List <NodeLaneMarker> markers = GetNodeMarkers(HoveredNodeId); if (markers != null) { SelectedNodeId = HoveredNodeId; selectedMarker = null; currentNodeMarkers[SelectedNodeId] = markers; } //this.allNodeMarkers[SelectedNodeId] = GetNodeMarkers(SelectedNodeId); } } else { #if DEBUGCONN Log._Debug($"TppLaneConnectorTool: Node {SelectedNodeId} has been deselected."); #endif // click on free spot. deselect node SelectedNodeId = 0; selectedMarker = null; return; } } if (hoveredMarker != null) { #if DEBUGCONN Log._Debug($"TppLaneConnectorTool: hoveredMarker != null. selMode={GetMarkerSelectionMode()}"); #endif // hovered marker has been clicked if (GetMarkerSelectionMode() == MarkerSelectionMode.SelectSource) { // select source marker selectedMarker = hoveredMarker; #if DEBUGCONN Log._Debug($"TppLaneConnectorTool: set selected marker"); #endif } else if (GetMarkerSelectionMode() == MarkerSelectionMode.SelectTarget) { // select target marker //bool success = false; if (LaneConnectionManager.Instance().RemoveLaneConnection(selectedMarker.laneId, hoveredMarker.laneId, selectedMarker.startNode)) // try to remove connection { selectedMarker.connectedMarkers.Remove(hoveredMarker); #if DEBUGCONN Log._Debug($"TppLaneConnectorTool: removed lane connection: {selectedMarker.laneId}, {hoveredMarker.laneId}"); #endif //success = true; } else if (LaneConnectionManager.Instance().AddLaneConnection(selectedMarker.laneId, hoveredMarker.laneId, selectedMarker.startNode)) // try to add connection { selectedMarker.connectedMarkers.Add(hoveredMarker); #if DEBUGCONN Log._Debug($"TppLaneConnectorTool: added lane connection: {selectedMarker.laneId}, {hoveredMarker.laneId}"); #endif //success = true; } /*if (success) { * // connection has been modified. switch back to source marker selection * Log._Debug($"TppLaneConnectorTool: switch back to source marker selection"); * selectedMarker = null; * selMode = MarkerSelectionMode.SelectSource; * }*/ } } }