internal void LogTraffic(ushort vehicleId, ref Vehicle vehicleData, bool logSpeed) { #if TRACE Singleton <CodeProfiler> .instance.Start("VehicleStateManager.LogTraffic"); #endif VehicleState state = GetVehicleState(vehicleId); if (state == null) { return; } ushort length = (ushort)state.TotalLength; if (length == 0) { return; } ushort?speed = logSpeed ? (ushort?)Mathf.RoundToInt(vehicleData.GetLastFrameData().m_velocity.magnitude) : null; state.ProcessCurrentPathPosition(ref vehicleData, delegate(ref PathUnit.Position pos) { CustomRoadAI.AddTraffic(pos.m_segment, pos.m_lane, length, speed); }); #if TRACE Singleton <CodeProfiler> .instance.Stop("VehicleStateManager.LogTraffic"); #endif }
public void ChangeMode() { SegmentGeometry geometry = CustomRoadAI.GetSegmentGeometry(SegmentId); geometry.Recalculate(true, true); var hasLeftSegment = geometry.HasOutgoingLeftSegment(NodeId); var hasForwardSegment = geometry.HasOutgoingStraightSegment(NodeId); var hasRightSegment = geometry.HasOutgoingRightSegment(NodeId); Log._Debug($"ChangeMode. segment {SegmentId} @ node {NodeId}, hasOutgoingLeft={hasLeftSegment}, hasOutgoingStraight={hasForwardSegment}, hasOutgoingRight={hasRightSegment}"); if (CurrentMode == Mode.Simple) { if (!hasLeftSegment) { CurrentMode = Mode.SingleRight; } else { CurrentMode = Mode.SingleLeft; } } else if (CurrentMode == Mode.SingleLeft) { if (!hasForwardSegment || !hasRightSegment) { CurrentMode = Mode.Simple; } else { CurrentMode = Mode.SingleRight; } } else if (CurrentMode == Mode.SingleRight) { if (!hasLeftSegment) { CurrentMode = Mode.Simple; } else { CurrentMode = Mode.All; } } else { CurrentMode = Mode.Simple; } if (CurrentMode == Mode.Simple) { LightLeft = LightMain; LightRight = LightMain; //LightPedestrian = _checkPedestrianLight(); } }
private void setupLiveSegments() { for (var s = 0; s < 8; s++) { var segmentId = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].GetSegment(s); if (segmentId == 0) { continue; } CustomRoadAI.GetSegmentGeometry(segmentId)?.Recalculate(true, true); TrafficLight.CustomTrafficLights.AddLiveSegmentLights(nodeId, segmentId); } }
public void UpdateVisuals() { #if TRACE Singleton <CodeProfiler> .instance.Start("CustomSegmentLight.UpdateVisuals"); #endif var instance = Singleton <NetManager> .instance; uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; uint num = (uint)(((int)NodeId << 8) / 32768); RoadBaseAI.TrafficLightState vehicleLightState; RoadBaseAI.TrafficLightState pedestrianLightState; RoadBaseAI.TrafficLightState mainLight = LightMain; RoadBaseAI.TrafficLightState leftLight = LightLeft; RoadBaseAI.TrafficLightState rightLight = LightRight; switch (CurrentMode) { case Mode.Simple: leftLight = mainLight; rightLight = mainLight; break; case Mode.SingleLeft: rightLight = mainLight; break; case Mode.SingleRight: leftLight = mainLight; break; case Mode.All: default: break; } vehicleLightState = GetVisualLightState(); pedestrianLightState = lights.PedestrianLightState == null ? RoadBaseAI.TrafficLightState.Red : (RoadBaseAI.TrafficLightState)lights.PedestrianLightState; uint now = ((currentFrameIndex - num) >> 8) & 1; CustomRoadAI.OriginalSetTrafficLightState(true, NodeId, ref instance.m_segments.m_buffer[SegmentId], now << 8, vehicleLightState, pedestrianLightState, false, false); CustomRoadAI.OriginalSetTrafficLightState(true, NodeId, ref instance.m_segments.m_buffer[SegmentId], (1u - now) << 8, vehicleLightState, pedestrianLightState, false, false); #if TRACE Singleton <CodeProfiler> .instance.Stop("CustomSegmentLight.UpdateVisuals"); #endif }
public void UpdateVisuals() { var instance = Singleton <NetManager> .instance; ushort nodeId = lights.NodeId; uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; uint num = (uint)(((int)nodeId << 8) / 32768); RoadBaseAI.TrafficLightState vehicleLightState; RoadBaseAI.TrafficLightState pedestrianLightState; RoadBaseAI.TrafficLightState mainLight = LightMain; RoadBaseAI.TrafficLightState leftLight = LightLeft; RoadBaseAI.TrafficLightState rightLight = LightRight; switch (CurrentMode) { case LightMode.Simple: leftLight = mainLight; rightLight = mainLight; break; case LightMode.SingleLeft: rightLight = mainLight; break; case LightMode.SingleRight: leftLight = mainLight; break; case LightMode.All: default: break; } vehicleLightState = GetVisualLightState(); pedestrianLightState = lights.PedestrianLightState == null ? RoadBaseAI.TrafficLightState.Red : (RoadBaseAI.TrafficLightState)lights.PedestrianLightState; #if DEBUGVISUALS Log._Debug($"Setting visual traffic light state of node {NodeId}, seg. {SegmentId} to vehicleState={vehicleLightState} pedState={pedestrianLightState}"); #endif uint now = ((currentFrameIndex - num) >> 8) & 1; CustomRoadAI.OriginalSetTrafficLightState(true, nodeId, ref instance.m_segments.m_buffer[SegmentId], now << 8, vehicleLightState, pedestrianLightState, false, false); CustomRoadAI.OriginalSetTrafficLightState(true, nodeId, ref instance.m_segments.m_buffer[SegmentId], (1u - now) << 8, vehicleLightState, pedestrianLightState, false, false); }
internal void ClearTraffic() { try { Monitor.Enter(Singleton <VehicleManager> .instance); for (ushort i = 0; i < Singleton <VehicleManager> .instance.m_vehicles.m_size; ++i) { if ( (Singleton <VehicleManager> .instance.m_vehicles.m_buffer[i].m_flags & Vehicle.Flags.Created) != 0) { Singleton <VehicleManager> .instance.ReleaseVehicle(i); } } CustomRoadAI.resetTrafficStats(); } catch (Exception ex) { Log.Error($"Error occured while trying to clear traffic: {ex.ToString()}"); } finally { Monitor.Exit(Singleton <VehicleManager> .instance); } }
public TimedTrafficLights(ushort nodeId, IEnumerable <ushort> nodeGroup) { this.NodeId = nodeId; NodeGroup = new List <ushort>(nodeGroup); masterNodeId = NodeGroup[0]; // setup priority segments & live traffic lights foreach (ushort slaveNodeId in nodeGroup) { for (int s = 0; s < 8; ++s) { ushort segmentId = Singleton <NetManager> .instance.m_nodes.m_buffer[slaveNodeId].GetSegment(s); if (segmentId <= 0) { continue; } CustomRoadAI.GetSegmentGeometry(segmentId).Recalculate(true, true); TrafficPriority.AddPrioritySegment(slaveNodeId, segmentId, SegmentEnd.PriorityType.None); CustomTrafficLights.AddLiveSegmentLights(slaveNodeId, segmentId); } } started = false; }
public override void OnLoadData() { Log.Info("Loading Traffic Manager: PE Data"); StateLoading = true; try { Log.Info("Initializing flags"); Flags.OnBeforeLoadData(); Log.Info("Initializing node geometries"); NodeGeometry.OnBeforeLoadData(); Log.Info("Initializing segment geometries"); SegmentGeometry.OnBeforeLoadData(); Log.Info("Initializing lane connection manager"); Singleton <LaneConnectionManager> .instance.OnBeforeLoadData(); // requires segment geometries Log.Info("Initializing CustomRoadAI"); CustomRoadAI.OnBeforeLoadData(); Log.Info("Initialization done. Loading mod data now."); byte[] data = _serializableData.LoadData(DataId); DeserializeData(data); // load options 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); } } } catch (Exception e) { Log.Error($"OnLoadData: {e.ToString()}"); } finally { StateLoading = false; } Log.Info("OnLoadData completed."); // load toggled traffic lights //byte[] trafficLight = _serializableData.LoadData("TMPE_Options"); }
public void ShowGUI(bool viewOnly) { try { if (viewOnly && !Options.prioritySignsOverlay) { return; } bool clicked = !viewOnly?MainTool.CheckClicked() : false; var hoveredSegment = false; //Log.Message("_guiPrioritySigns called. num of prio segments: " + TrafficPriority.PrioritySegments.Count); HashSet <ushort> nodeIdsWithSigns = new HashSet <ushort>(); for (ushort segmentId = 0; segmentId < TrafficPriority.PrioritySegments.Length; ++segmentId) { var trafficSegment = TrafficPriority.PrioritySegments[segmentId]; if (trafficSegment == null) { continue; } SegmentGeometry geometry = CustomRoadAI.GetSegmentGeometry(segmentId); List <SegmentEnd> prioritySegments = new List <SegmentEnd>(); if (TrafficLightSimulation.GetNodeSimulation(trafficSegment.Node1) == null) { SegmentEnd tmpSeg1 = TrafficPriority.GetPrioritySegment(trafficSegment.Node1, segmentId); if (tmpSeg1 != null && !geometry.IsOutgoingOneWay(trafficSegment.Node1)) { prioritySegments.Add(tmpSeg1); nodeIdsWithSigns.Add(trafficSegment.Node1); } } if (TrafficLightSimulation.GetNodeSimulation(trafficSegment.Node2) == null) { SegmentEnd tmpSeg2 = TrafficPriority.GetPrioritySegment(trafficSegment.Node2, segmentId); if (tmpSeg2 != null && !geometry.IsOutgoingOneWay(trafficSegment.Node2)) { prioritySegments.Add(tmpSeg2); nodeIdsWithSigns.Add(trafficSegment.Node2); } } //Log.Message("init ok"); foreach (var prioritySegment in prioritySegments) { var nodeId = prioritySegment.NodeId; //Log.Message("_guiPrioritySigns: nodeId=" + nodeId); var nodePositionVector3 = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].m_position; var camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position; var diff = nodePositionVector3 - camPos; if (diff.magnitude > TrafficManagerTool.PriorityCloseLod) { continue; // do not draw if too distant } if (Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startNode == (ushort)nodeId) { nodePositionVector3.x += Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startDirection.x * 10f; nodePositionVector3.y += Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startDirection.y * 10f; nodePositionVector3.z += Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startDirection.z * 10f; } else { nodePositionVector3.x += Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endDirection.x * 10f; nodePositionVector3.y += Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endDirection.y * 10f; nodePositionVector3.z += Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endDirection.z * 10f; } var nodeScreenPosition = Camera.main.WorldToScreenPoint(nodePositionVector3); nodeScreenPosition.y = Screen.height - nodeScreenPosition.y; if (nodeScreenPosition.z < 0) { continue; } var zoom = 1.0f / diff.magnitude * 100f * MainTool.GetBaseZoom(); var size = 110f * zoom; var guiColor = GUI.color; var nodeBoundingBox = new Rect(nodeScreenPosition.x - size / 2, nodeScreenPosition.y - size / 2, size, size); hoveredSegment = !viewOnly && TrafficManagerTool.IsMouseOver(nodeBoundingBox); if (hoveredSegment) { // mouse hovering over sign guiColor.a = 0.8f; } else { guiColor.a = 0.5f; size = 90f * zoom; } var nodeDrawingBox = new Rect(nodeScreenPosition.x - size / 2, nodeScreenPosition.y - size / 2, size, size); GUI.color = guiColor; switch (prioritySegment.Type) { case SegmentEnd.PriorityType.Main: GUI.DrawTexture(nodeDrawingBox, TrafficLightToolTextureResources.SignPriorityTexture2D); if (clicked && hoveredSegment) { //Log._Debug("Click on node " + nodeId + ", segment " + segmentId + " to change prio type (1)"); //Log.Message("PrioritySegment.Type = Yield"); prioritySegment.Type = SegmentEnd.PriorityType.Yield; clicked = false; } break; case SegmentEnd.PriorityType.Yield: GUI.DrawTexture(nodeDrawingBox, TrafficLightToolTextureResources.SignYieldTexture2D); if (clicked && hoveredSegment) { //Log._Debug("Click on node " + nodeId + ", segment " + segmentId + " to change prio type (2)"); prioritySegment.Type = SegmentEnd.PriorityType.Stop; clicked = false; } break; case SegmentEnd.PriorityType.Stop: GUI.DrawTexture(nodeDrawingBox, TrafficLightToolTextureResources.SignStopTexture2D); if (clicked && hoveredSegment) { //Log._Debug("Click on node " + nodeId + ", segment " + segmentId + " to change prio type (3)"); prioritySegment.Type = SegmentEnd.PriorityType.None; clicked = false; } break; case SegmentEnd.PriorityType.None: if (viewOnly) { break; } GUI.DrawTexture(nodeDrawingBox, TrafficLightToolTextureResources.SignNoneTexture2D); if (clicked && hoveredSegment) { //Log._Debug("Click on node " + nodeId + ", segment " + segmentId + " to change prio type (4)"); //Log.Message("PrioritySegment.Type = None"); prioritySegment.Type = GetNumberOfMainRoads(nodeId, ref Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId]) >= 2 ? SegmentEnd.PriorityType.Yield : SegmentEnd.PriorityType.Main; clicked = false; } break; } } } if (viewOnly) { return; } ushort hoveredExistingNodeId = 0; foreach (ushort nodeId in nodeIdsWithSigns) { var nodePositionVector3 = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].m_position; var camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position; var diff = nodePositionVector3 - camPos; if (diff.magnitude > TrafficManagerTool.PriorityCloseLod) { continue; } // draw deletion button var nodeScreenPosition = Camera.main.WorldToScreenPoint(nodePositionVector3); nodeScreenPosition.y = Screen.height - nodeScreenPosition.y; if (nodeScreenPosition.z < 0) { continue; } var zoom = 1.0f / diff.magnitude * 100f; var size = 100f * zoom; var nodeBoundingBox = new Rect(nodeScreenPosition.x - size / 2, nodeScreenPosition.y - size / 2, size, size); var guiColor = GUI.color; var nodeCenterHovered = TrafficManagerTool.IsMouseOver(nodeBoundingBox); if (nodeCenterHovered) { hoveredExistingNodeId = nodeId; guiColor.a = 0.8f; } else { guiColor.a = 0.5f; } GUI.color = guiColor; GUI.DrawTexture(nodeBoundingBox, TrafficLightToolTextureResources.SignRemoveTexture2D); } // add a new or delete a priority segment node if (HoveredNodeId != 0 || hoveredExistingNodeId != 0) { bool delete = false; if (hoveredExistingNodeId > 0) { delete = true; } // determine if we may add new priority signs to this node bool ok = false; if ((Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None) { // no traffic light set ok = true; } else { TrafficLightSimulation nodeSim = TrafficLightSimulation.GetNodeSimulation(HoveredNodeId); if (nodeSim == null || !nodeSim.IsTimedLight()) { ok = true; } } if (clicked) { //Log._Debug("_guiPrioritySigns: hovered+clicked @ nodeId=" + HoveredNodeId + "/" + hoveredExistingNodeId); if (delete) { TrafficPriority.RemovePrioritySegments(hoveredExistingNodeId); } else if (ok) { if (!TrafficPriority.IsPriorityNode(HoveredNodeId)) { //Log._Debug("_guiPrioritySigns: adding prio segments @ nodeId=" + HoveredNodeId); TrafficLightSimulation.RemoveNodeFromSimulation(HoveredNodeId, false); // TODO refactor! Flags.setNodeTrafficLight(HoveredNodeId, false); // TODO refactor! TrafficPriority.AddPriorityNode(HoveredNodeId); } } else { MainTool.ShowTooltip(Translation.GetString("NODE_IS_TIMED_LIGHT"), Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_position); } } } } catch (Exception e) { Log.Error(e.ToString()); } }
/*public void ChangeLightPedestrian() { * if (PedestrianEnabled) { * var invertedLight = LightPedestrian == RoadBaseAI.TrafficLightState.Green * ? RoadBaseAI.TrafficLightState.Red * : RoadBaseAI.TrafficLightState.Green; * * LightPedestrian = invertedLight; * UpdateVisuals(); * } * }*/ /*RoadBaseAI.TrafficLightState lastVehicleLightState = RoadBaseAI.TrafficLightState.Red; * RoadBaseAI.TrafficLightState lastPedestrianLightState = RoadBaseAI.TrafficLightState.Red;*/ public void UpdateVisuals() { var instance = Singleton <NetManager> .instance; uint currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; uint num = (uint)(((int)NodeId << 8) / 32768); RoadBaseAI.TrafficLightState vehicleLightState; RoadBaseAI.TrafficLightState pedestrianLightState; RoadBaseAI.TrafficLightState mainLight = LightMain; RoadBaseAI.TrafficLightState leftLight = LightLeft; RoadBaseAI.TrafficLightState rightLight = LightRight; switch (CurrentMode) { case Mode.Simple: leftLight = mainLight; rightLight = mainLight; break; case Mode.SingleLeft: rightLight = mainLight; break; case Mode.SingleRight: leftLight = mainLight; break; case Mode.All: default: break; } // any green? if (mainLight == RoadBaseAI.TrafficLightState.Green || leftLight == RoadBaseAI.TrafficLightState.Green || rightLight == RoadBaseAI.TrafficLightState.Green) { vehicleLightState = RoadBaseAI.TrafficLightState.Green; } else // all red? if (mainLight == RoadBaseAI.TrafficLightState.Red && leftLight == RoadBaseAI.TrafficLightState.Red && rightLight == RoadBaseAI.TrafficLightState.Red) { vehicleLightState = RoadBaseAI.TrafficLightState.Red; } else // any red+yellow? if (mainLight == RoadBaseAI.TrafficLightState.RedToGreen || leftLight == RoadBaseAI.TrafficLightState.RedToGreen || rightLight == RoadBaseAI.TrafficLightState.RedToGreen) { vehicleLightState = RoadBaseAI.TrafficLightState.RedToGreen; } else { vehicleLightState = RoadBaseAI.TrafficLightState.GreenToRed; } //pedestrianLightState = LightPedestrian; pedestrianLightState = lights.PedestrianLightState == null ? RoadBaseAI.TrafficLightState.Red : (RoadBaseAI.TrafficLightState)lights.PedestrianLightState; uint now = ((currentFrameIndex - num) >> 8) & 1; CustomRoadAI.OriginalSetTrafficLightState(true, NodeId, ref instance.m_segments.m_buffer[SegmentId], now << 8, vehicleLightState, pedestrianLightState, false, false); CustomRoadAI.OriginalSetTrafficLightState(true, NodeId, ref instance.m_segments.m_buffer[SegmentId], (1u - now) << 8, vehicleLightState, pedestrianLightState, false, false); /*if (vehicleLightState != lastVehicleLightState || pedestrianLightState != lastPedestrianLightState) { * // force rendering * Singleton<NetManager>.instance.UpdateSegmentRenderer(segmentId, true); * } * * lastVehicleLightState = vehicleLightState; * lastPedestrianLightState = pedestrianLightState;*/ }
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; }
/// <summary> /// Calculates the current metrics for flowing and waiting vehicles /// </summary> /// <param name="wait"></param> /// <param name="flow"></param> /// <returns>true if the values could be calculated, false otherwise</returns> public bool calcWaitFlow(out float wait, out float flow) { #if DEBUG bool debug = timedNode.NodeId == 17857; #else bool debug = false; #endif uint numFlows = 0; uint numWaits = 0; uint curMeanFlow = 0; uint curMeanWait = 0; // we are the master node. calculate traffic data foreach (ushort timedNodeId in groupNodeIds) { TrafficLightSimulation sim = TrafficLightSimulation.GetNodeSimulation(timedNodeId); if (sim == null || !sim.IsTimedLight()) { continue; } TimedTrafficLights slaveTimedNode = sim.TimedLight; if (slaveTimedNode.NumSteps() <= timedNode.CurrentStep) { for (int i = 0; i < slaveTimedNode.NumSteps(); ++i) { slaveTimedNode.GetStep(i).invalid = true; } continue; } TimedTrafficLightsStep slaveStep = slaveTimedNode.Steps[timedNode.CurrentStep]; //List<int> segmentIdsToDelete = new List<int>(); // minimum time reached. check traffic! foreach (KeyValuePair <ushort, CustomSegmentLights> e in slaveStep.segmentLights) { var fromSegmentId = e.Key; var segLights = e.Value; // one of the traffic lights at this segment is green: count minimum traffic flowing through SegmentEnd fromSeg = TrafficPriority.GetPrioritySegment(timedNodeId, fromSegmentId); if (fromSeg == null) { //Log.Warning("stepDone(): prioSeg is null"); //segmentIdsToDelete.Add(fromSegmentId); continue; // skip invalid segment } bool startPhase = getCurrentFrame() <= startFrame + minTime + 2; // during start phase all vehicles on "green" segments are counted as flowing ExtVehicleType validVehicleTypes = VehicleRestrictionsManager.GetAllowedVehicleTypes(fromSegmentId, timedNode.NodeId); foreach (ExtVehicleType vehicleType in segLights.VehicleTypes) { if (vehicleType != ExtVehicleType.None && (validVehicleTypes & vehicleType) == ExtVehicleType.None) { continue; } CustomSegmentLight segLight = segLights.GetCustomLight(vehicleType); if (segLight == null) { Log.Warning($"Timed traffic light step: Failed to get custom light for vehicleType {vehicleType} @ seg. {fromSegmentId}, node {timedNode.NodeId}!"); continue; } Dictionary <ushort, uint>[] carsToSegmentMetrics = new Dictionary <ushort, uint> [startPhase ? 1: 2]; try { carsToSegmentMetrics[0] = fromSeg.GetVehicleMetricGoingToSegment(null, vehicleType, segLights.SeparateVehicleTypes, debug); } catch (Exception ex) { Log.Warning("calcWaitFlow: " + ex.ToString()); } if (!startPhase) { try { carsToSegmentMetrics[1] = fromSeg.GetVehicleMetricGoingToSegment(0.1f, vehicleType, segLights.SeparateVehicleTypes, debug); } catch (Exception ex) { Log.Warning("calcWaitFlow: " + ex.ToString()); } } if (carsToSegmentMetrics[0] == null) { continue; } // build directions from toSegment to fromSegment Dictionary <ushort, Direction> directions = new Dictionary <ushort, Direction>(); foreach (KeyValuePair <ushort, uint> f in carsToSegmentMetrics[0]) { var toSegmentId = f.Key; SegmentGeometry geometry = CustomRoadAI.GetSegmentGeometry(fromSegmentId); Direction dir = geometry.GetDirection(toSegmentId, timedNodeId); directions[toSegmentId] = dir; } // calculate waiting/flowing traffic for (int i = 0; i < carsToSegmentMetrics.Length; ++i) { if (carsToSegmentMetrics[i] == null) { continue; } foreach (KeyValuePair <ushort, uint> f in carsToSegmentMetrics[i]) { ushort toSegmentId = f.Key; uint totalNormCarLength = f.Value; bool addToFlow = false; switch (directions[toSegmentId]) { case Direction.Left: if (segLight.isLeftGreen()) { addToFlow = true; } break; case Direction.Right: if (segLight.isRightGreen()) { addToFlow = true; } break; case Direction.Forward: default: if (segLight.isForwardGreen()) { addToFlow = true; } break; } if (addToFlow) { if (i > 0 || startPhase) { ++numFlows; curMeanFlow += totalNormCarLength; } } else if (i == 0) { ++numWaits; curMeanWait += totalNormCarLength; } } } } } // delete invalid segments from step /*foreach (int segmentId in segmentIdsToDelete) { * slaveStep.segmentLightStates.Remove(segmentId); * }*/ if (slaveStep.segmentLights.Count <= 0) { invalid = true; flow = 0f; wait = 0f; return(false); } } if (numFlows > 0) { curMeanFlow /= numFlows; } if (numWaits > 0) { curMeanWait /= numWaits; } float fCurMeanFlow = curMeanFlow; fCurMeanFlow /= 100f * waitFlowBalance; // a value smaller than 1 rewards steady traffic currents wait = (float)curMeanWait / 100f; flow = fCurMeanFlow; return(true); }
public override void OnToolGUI(Event e) { var hoveredSegment = false; if (SelectedNodeId != 0) { var nodeSimulation = TrafficLightSimulation.GetNodeSimulation(SelectedNodeId); nodeSimulation.housekeeping(true); /*if (Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode].CountSegments() == 2) { * _guiManualTrafficLightsCrosswalk(ref Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode]); * return; * }*/// TODO check for (var i = 0; i < 8; i++) { var segmentId = Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId].GetSegment(i); if (segmentId == 0 || nodeSimulation == null || !CustomTrafficLights.IsSegmentLight(SelectedNodeId, segmentId)) { continue; } var position = CalculateNodePositionForSegment(Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId], ref Singleton <NetManager> .instance.m_segments.m_buffer[segmentId]); var segmentLights = CustomTrafficLights.GetSegmentLights(SelectedNodeId, segmentId); var screenPos = Camera.main.WorldToScreenPoint(position); screenPos.y = Screen.height - screenPos.y; if (screenPos.z < 0) { continue; } var diff = position - Camera.main.transform.position; var zoom = 1.0f / diff.magnitude * 100f; // original / 2.5 var lightWidth = 41f * zoom; var lightHeight = 97f * zoom; var pedestrianWidth = 36f * zoom; var pedestrianHeight = 61f * zoom; // SWITCH MODE BUTTON var modeWidth = 41f * zoom; var modeHeight = 38f * zoom; var guiColor = GUI.color; if (segmentLights.PedestrianLightState != null) { // pedestrian light // SWITCH MANUAL PEDESTRIAN LIGHT BUTTON hoveredSegment = RenderManualPedestrianLightSwitch(zoom, segmentId, screenPos, lightWidth, segmentLights, hoveredSegment); // SWITCH PEDESTRIAN LIGHT guiColor.a = _hoveredButton[0] == segmentId && _hoveredButton[1] == 2 && segmentLights.ManualPedestrianMode ? 0.92f : 0.6f; GUI.color = guiColor; var myRect3 = new Rect(screenPos.x - pedestrianWidth / 2 - lightWidth + 5f * zoom, screenPos.y - pedestrianHeight / 2 + 22f * zoom, pedestrianWidth, pedestrianHeight); switch (segmentLights.PedestrianLightState) { case RoadBaseAI.TrafficLightState.Green: GUI.DrawTexture(myRect3, TrafficLightToolTextureResources.PedestrianGreenLightTexture2D); break; case RoadBaseAI.TrafficLightState.Red: default: GUI.DrawTexture(myRect3, TrafficLightToolTextureResources.PedestrianRedLightTexture2D); break; } hoveredSegment = IsPedestrianLightHovered(myRect3, segmentId, hoveredSegment, segmentLights); } int lightOffset = -1; foreach (ExtVehicleType vehicleType in segmentLights.VehicleTypes) { ++lightOffset; CustomSegmentLight segmentLight = segmentLights.GetCustomLight(vehicleType); Vector3 offsetScreenPos = screenPos; offsetScreenPos.y -= (lightHeight + 10f * zoom) * lightOffset; SetAlpha(segmentId, -1); var myRect1 = new Rect(offsetScreenPos.x - modeWidth / 2, offsetScreenPos.y - modeHeight / 2 + modeHeight - 7f * zoom, modeWidth, modeHeight); GUI.DrawTexture(myRect1, TrafficLightToolTextureResources.LightModeTexture2D); hoveredSegment = GetHoveredSegment(myRect1, segmentId, hoveredSegment, segmentLight); // COUNTER hoveredSegment = RenderCounter(segmentId, offsetScreenPos, modeWidth, modeHeight, zoom, segmentLights, hoveredSegment); if (lightOffset > 0) { // Info sign var infoWidth = 56.125f * zoom; var infoHeight = 51.375f * zoom; int numInfos = 0; for (int k = 0; k < TrafficManagerTool.InfoSignsToDisplay.Length; ++k) { if ((TrafficManagerTool.InfoSignsToDisplay[k] & vehicleType) == ExtVehicleType.None) { continue; } var infoRect = new Rect(offsetScreenPos.x + modeWidth / 2f + 7f * zoom * (float)(numInfos + 1) + infoWidth * (float)numInfos, offsetScreenPos.y - infoHeight / 2f, infoWidth, infoHeight); guiColor.a = 0.6f; GUI.DrawTexture(infoRect, TrafficLightToolTextureResources.VehicleInfoSignTextures[TrafficManagerTool.InfoSignsToDisplay[k]]); ++numInfos; } } SegmentGeometry geometry = CustomRoadAI.GetSegmentGeometry(segmentId); if (geometry.IsOutgoingOneWay(SelectedNodeId)) { continue; } var hasLeftSegment = geometry.HasLeftSegment(SelectedNodeId); var hasForwardSegment = geometry.HasStraightSegment(SelectedNodeId); var hasRightSegment = geometry.HasRightSegment(SelectedNodeId); switch (segmentLight.CurrentMode) { case CustomSegmentLight.Mode.Simple: hoveredSegment = SimpleManualSegmentLightMode(segmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment); break; case CustomSegmentLight.Mode.SingleLeft: hoveredSegment = LeftForwardRManualSegmentLightMode(hasLeftSegment, segmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment, hasForwardSegment, hasRightSegment); break; case CustomSegmentLight.Mode.SingleRight: hoveredSegment = RightForwardLSegmentLightMode(segmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, hasForwardSegment, hasLeftSegment, segmentLight, hasRightSegment, hoveredSegment); break; default: // left arrow light if (hasLeftSegment) { hoveredSegment = LeftArrowLightMode(segmentId, lightWidth, hasRightSegment, hasForwardSegment, offsetScreenPos, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment); } // forward arrow light if (hasForwardSegment) { hoveredSegment = ForwardArrowLightMode(segmentId, lightWidth, hasRightSegment, offsetScreenPos, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment); } // right arrow light if (hasRightSegment) { hoveredSegment = RightArrowLightMode(segmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment); } break; } } } } if (hoveredSegment) { return; } _hoveredButton[0] = 0; _hoveredButton[1] = 0; }
/// <summary> /// Calculates for each segment the number of cars going to this segment. /// We use integer arithmetic for better performance. /// </summary> public Dictionary <ushort, uint> GetVehicleMetricGoingToSegment(float?minSpeed, ExtVehicleType?vehicleTypes = null, ExtVehicleType separateVehicleTypes = ExtVehicleType.None, bool debug = false) { Dictionary <ushort, uint> numCarsGoingToSegmentId = new Dictionary <ushort, uint>(); VehicleManager vehicleManager = Singleton <VehicleManager> .instance; NetManager netManager = Singleton <NetManager> .instance; for (var s = 0; s < 8; s++) { var segmentId = netManager.m_nodes.m_buffer[NodeId].GetSegment(s); if (segmentId == 0 || segmentId == SegmentId) { continue; } if (CustomRoadAI.GetSegmentGeometry(segmentId).IsIncomingOneWay(NodeId)) { continue; } numCarsGoingToSegmentId[segmentId] = 0; } List <ushort> vehicleIdsToReHandle = new List <ushort>(); foreach (KeyValuePair <ushort, VehiclePosition> e in Vehicles) { var vehicleId = e.Key; var carPos = e.Value; if (vehicleId <= 0 || carPos.ToSegment <= 0) { continue; } if ((vehicleManager.m_vehicles.m_buffer[vehicleId].m_flags & Vehicle.Flags.Created) == Vehicle.Flags.None) { vehicleIdsToReHandle.Add(vehicleId); continue; } if (minSpeed != null && vehicleManager.m_vehicles.m_buffer[vehicleId].GetLastFrameVelocity().magnitude < minSpeed) { continue; } VehiclePosition globalPos = TrafficPriority.GetVehiclePosition(vehicleId); if (globalPos == null || !globalPos.Valid || globalPos.LastFrame >> 7 < Singleton <SimulationManager> .instance.m_currentFrameIndex >> 7) // ~64 sec. { vehicleIdsToReHandle.Add(vehicleId); continue; } if (vehicleTypes != null) { if (vehicleTypes == ExtVehicleType.None) { if ((globalPos.VehicleType & separateVehicleTypes) != ExtVehicleType.None) { // we want all vehicles that do not have separate traffic lights continue; } } else { if ((globalPos.VehicleType & vehicleTypes) == ExtVehicleType.None) { continue; } } } //debug = vehicleManager.m_vehicles.m_buffer[vehicleId].Info.m_vehicleType == VehicleInfo.VehicleType.Tram; #if DEBUG /*if (debug) { * Log._Debug($"getNumCarsGoingToSegment: Handling vehicle {vehicleId} going from {carPos.FromSegment}/{SegmentId} to {carPos.ToSegment}. carState={globalPos.CarState}. lastUpdate={globalPos.LastCarStateUpdate}"); * }*/ #endif uint avgSegmentLength = (uint)Singleton <NetManager> .instance.m_segments.m_buffer[SegmentId].m_averageLength; uint normLength = (uint)(vehicleManager.m_vehicles.m_buffer[vehicleId].CalculateTotalLength(vehicleId) * 100u) / avgSegmentLength; #if DEBUG /*if (debug) { * Log._Debug($"getNumCarsGoingToSegment: NormLength of vehicle {vehicleId} going to {carPos.ToSegment}: {avgSegmentLength} -> {normLength}"); * }*/ #endif if (numCarsGoingToSegmentId.ContainsKey(carPos.ToSegment)) { /*if (carPos.OnEmergency) * numCarsGoingToSegmentId[carPos.ToSegment] += 10000f; * else*/ numCarsGoingToSegmentId[carPos.ToSegment] += normLength; } // "else" must not happen (incoming one-way) } foreach (ushort vehicleId in vehicleIdsToReHandle) { CustomVehicleAI.HandleVehicle(vehicleId, ref Singleton <VehicleManager> .instance.m_vehicles.m_buffer[vehicleId], false, false); } return(numCarsGoingToSegmentId); }
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(); }