public void SkipStep(bool setLights = true) { if (!isMasterNode()) { return; } TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance(); var newCurrentStep = (CurrentStep + 1) % NumSteps(); foreach (ushort slaveNodeId in NodeGroup) { TrafficLightSimulation slaveSim = tlsMan.GetNodeSimulation(slaveNodeId); if (slaveSim == null || !slaveSim.IsTimedLight()) { continue; } slaveSim.TimedLight.Steps[CurrentStep].SetStepDone(); slaveSim.TimedLight.CurrentStep = newCurrentStep; slaveSim.TimedLight.Steps[newCurrentStep].Start(); if (setLights) { slaveSim.TimedLight.Steps[newCurrentStep].SetLights(); } } }
internal void Housekeeping() { if (TrafficManagerTool.GetToolMode() != ToolMode.AddPrioritySigns && TrafficLightSimulationManager.Instance().GetNodeSimulation(NodeId) == null && Type == PriorityType.None) { TrafficPriorityManager.Instance().RemovePrioritySegments(NodeId); } }
internal void RemoveNodeFromGroup(ushort otherNodeId) { NodeGroup.Remove(otherNodeId); if (NodeGroup.Count <= 0) { TrafficLightSimulationManager.Instance().RemoveNodeFromSimulation(NodeId, true, false); return; } masterNodeId = NodeGroup[0]; }
internal TimedTrafficLights MasterLights() { TrafficLightSimulation masterSim = TrafficLightSimulationManager.Instance().GetNodeSimulation(masterNodeId); if (masterSim == null || !masterSim.IsTimedLight()) { return(null); } return(masterSim.TimedLight); }
public void OnUpdate(NodeGeometry nodeGeometry) { #if DEBUG Log._Debug($"TrafficLightSimulation: OnUpdate @ node {NodeId} ({nodeGeometry.NodeId})"); #endif if (!Flags.mayHaveTrafficLight(NodeId)) { Log.Warning($"Housekeeping: Node {NodeId} has traffic light simulation but must not have a traffic light!"); TrafficLightSimulationManager.Instance().RemoveNodeFromSimulation(NodeId, false, true); } if (!IsManualLight() && !IsTimedLight()) { return; } if (!nodeGeometry.IsValid()) { // node has become invalid. Remove manual/timed traffic light and destroy custom lights TrafficLightSimulationManager.Instance().RemoveNodeFromSimulation(NodeId, false, false); return; } CustomTrafficLightsManager customTrafficLightsManager = CustomTrafficLightsManager.Instance(); for (var s = 0; s < 8; s++) { var segmentId = Singleton <NetManager> .instance.m_nodes.m_buffer[NodeId].GetSegment(s); if (segmentId == 0) { continue; } #if DEBUG Log._Debug($"TrafficLightSimulation: OnUpdate @ node {NodeId}: Adding live traffic lights to segment {segmentId}"); #endif // add custom lights if (!customTrafficLightsManager.IsSegmentLight(NodeId, segmentId)) { customTrafficLightsManager.AddSegmentLights(NodeId, segmentId); } // housekeep timed light customTrafficLightsManager.GetSegmentLights(NodeId, segmentId).housekeeping(true); } // ensure there is a physical traffic light Flags.setNodeTrafficLight(NodeId, true); TimedLight?.handleNewSegments(); TimedLight?.housekeeping(); }
public bool CustomCheckTrafficLights(ushort node, ushort segment) { var nodeSimulation = Options.timedLightsEnabled ? TrafficLightSimulationManager.Instance().GetNodeSimulation(node) : null; var instance = Singleton <NetManager> .instance; var currentFrameIndex = Singleton <SimulationManager> .instance.m_currentFrameIndex; var num = (uint)((node << 8) / 32768); var num2 = currentFrameIndex - num & 255u; // NON-STOCK CODE START // RoadBaseAI.TrafficLightState pedestrianLightState; CustomSegmentLights lights = CustomTrafficLightsManager.Instance().GetSegmentLights(node, segment); if (lights == null || nodeSimulation == null || !nodeSimulation.IsSimulationActive()) { RoadBaseAI.TrafficLightState vehicleLightState; bool vehicles; bool pedestrians; RoadBaseAI.GetTrafficLightState(node, ref instance.m_segments.m_buffer[segment], currentFrameIndex - num, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians); if ((pedestrianLightState == RoadBaseAI.TrafficLightState.GreenToRed || pedestrianLightState == RoadBaseAI.TrafficLightState.Red) && !pedestrians && num2 >= 196u) { RoadBaseAI.SetTrafficLightState(node, ref instance.m_segments.m_buffer[segment], currentFrameIndex - num, vehicleLightState, pedestrianLightState, vehicles, true); return(true); } } else { if (lights.InvalidPedestrianLight) { pedestrianLightState = RoadBaseAI.TrafficLightState.Green; } else { pedestrianLightState = (RoadBaseAI.TrafficLightState)lights.PedestrianLightState; } } // NON-STOCK CODE END // switch (pedestrianLightState) { case RoadBaseAI.TrafficLightState.RedToGreen: if (num2 < 60u) { return(false); } break; case RoadBaseAI.TrafficLightState.Red: case RoadBaseAI.TrafficLightState.GreenToRed: return(false); } return(true); }
public override void OnPrimaryClickOverlay() { if (IsCursorInPanel()) { return; } if (SelectedNodeId != 0) { return; } TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; TrafficPriorityManager prioMan = TrafficPriorityManager.Instance; if (!tlsMan.TrafficLightSimulations[HoveredNodeId].IsTimedLight()) { if ((Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None) { prioMan.RemovePrioritySignsFromNode(HoveredNodeId); TrafficLightManager.Instance.AddTrafficLight( HoveredNodeId, ref Singleton <NetManager> .instance.m_nodes.m_buffer[ HoveredNodeId]); } if (tlsMan.SetUpManualTrafficLight(HoveredNodeId)) { SelectedNodeId = HoveredNodeId; } // for (var s = 0; s < 8; s++) { // var segment = Singleton<NetManager> // .instance.m_nodes.m_buffer[SelectedNodeId].GetSegment(s); // if (segment != 0 && // !TrafficPriority.IsPrioritySegment(SelectedNodeId, segment)) { // TrafficPriority.AddPrioritySegment( // SelectedNodeId, // segment, // SegmentEnd.PriorityType.None); // } // } } else { MainTool.ShowError( Translation.TrafficLights.Get("Dialog.Text:Node has timed TL script")); } }
public override void Cleanup() { if (SelectedNodeId == 0) { return; } TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; if (!tlsMan.HasManualSimulation(SelectedNodeId)) { return; } tlsMan.RemoveNodeFromSimulation(SelectedNodeId, true, false); }
public override void OnPrimaryClickOverlay() { if (IsCursorInPanel()) { return; } if (SelectedNodeId != 0) { return; } TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; TrafficPriorityManager prioMan = TrafficPriorityManager.Instance; ref NetNode hoveredNetNode = ref HoveredNodeId.ToNode();
public void SetLights() { TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance(); // set lights foreach (ushort slaveNodeId in NodeGroup) { TrafficLightSimulation slaveSim = tlsMan.GetNodeSimulation(slaveNodeId); if (slaveSim == null || !slaveSim.IsTimedLight()) { //TrafficLightSimulation.RemoveNodeFromSimulation(slaveNodeId, false); // we iterate over NodeGroup!! continue; } slaveSim.TimedLight.Steps[CurrentStep].SetLights(); } }
public override void Cleanup() { if (SelectedNodeId == 0) { return; } TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; var nodeSimulation = tlsMan.GetNodeSimulation(SelectedNodeId); if (nodeSimulation == null || !nodeSimulation.IsManualLight()) { return; } tlsMan.RemoveNodeFromSimulation(SelectedNodeId, true, false); }
public override void OnPrimaryClickOverlay() { if (IsCursorInPanel()) { return; } if (SelectedNodeId != 0) { return; } TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; TrafficPriorityManager prioMan = TrafficPriorityManager.Instance; TrafficLightSimulation sim = tlsMan.GetNodeSimulation(HoveredNodeId); if (sim == null || !sim.IsTimedLight()) { if ((Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None) { prioMan.RemovePrioritySegments(HoveredNodeId); TrafficLightManager.Instance.AddTrafficLight(HoveredNodeId); } SelectedNodeId = HoveredNodeId; sim = tlsMan.AddNodeToSimulation(SelectedNodeId); sim.SetupManualTrafficLight(); /*for (var s = 0; s < 8; s++) { * var segment = Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNodeId].GetSegment(s); * if (segment != 0 && !TrafficPriority.IsPrioritySegment(SelectedNodeId, segment)) { * TrafficPriority.AddPrioritySegment(SelectedNodeId, segment, SegmentEnd.PriorityType.None); * } * }*/ } else { MainTool.ShowTooltip(Translation.GetString("NODE_IS_TIMED_LIGHT"), Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_position); } }
private void RenderManualNodeOverlays(RenderManager.CameraInfo cameraInfo) { var nodeSimulation = TrafficLightSimulationManager.Instance().GetNodeSimulation(SelectedNodeId); CustomTrafficLightsManager customTrafficLightsManager = CustomTrafficLightsManager.Instance(); for (var i = 0; i < 8; i++) { var colorGray = new Color(0.25f, 0.25f, 0.25f, 0.25f); ushort segmentId = Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId].GetSegment(i); if (segmentId == 0 || (nodeSimulation != null && customTrafficLightsManager.IsSegmentLight(SelectedNodeId, segmentId))) { continue; } var position = CalculateNodePositionForSegment(Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId], segmentId); var width = _hoveredButton[0] == segmentId ? 11.25f : 10f; MainTool.DrawOverlayCircle(cameraInfo, colorGray, position, width, segmentId != _hoveredButton[0]); } }
public override void OnPrimaryClickOverlay() { if (IsCursorInPanel()) { return; } if (SelectedNodeId != 0) { return; } TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; TrafficPriorityManager prioMan = TrafficPriorityManager.Instance; if (!tlsMan.TrafficLightSimulations[HoveredNodeId].IsTimedLight()) { if ((Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None) { prioMan.RemovePrioritySignsFromNode(HoveredNodeId); TrafficLightManager.Instance.AddTrafficLight( HoveredNodeId, ref Singleton <NetManager> .instance.m_nodes.m_buffer[ HoveredNodeId]); } if (tlsMan.SetUpManualTrafficLight(HoveredNodeId)) { SelectedNodeId = HoveredNodeId; MainTool.RequestOnscreenDisplayUpdate(); } } else { MainTool.WarningPrompt(Translation.TrafficLights.Get("Dialog.Text:Node has timed TL script")); } }
public override void OnPrimaryClickOverlay() { if (HoveredNodeId == 0) { return; } if ((Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags & NetNode.Flags.Junction) == NetNode.Flags.None) { return; } TrafficLightSimulation sim = TrafficLightSimulationManager.Instance().GetNodeSimulation(HoveredNodeId); if (sim != null && sim.IsTimedLight()) { MainTool.ShowTooltip(Translation.GetString("NODE_IS_TIMED_LIGHT"), Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_position); return; } TrafficPriorityManager.Instance().RemovePrioritySegments(HoveredNodeId); Flags.setNodeTrafficLight(HoveredNodeId, (Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None); }
public void ShowGUI(bool viewOnly) { try { TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; TrafficPriorityManager prioMan = TrafficPriorityManager.Instance; TrafficLightManager tlm = TrafficLightManager.Instance; 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>(); foreach (ushort segmentId in currentPrioritySegmentIds) { var trafficSegment = prioMan.TrafficSegments[segmentId]; if (trafficSegment == null) { continue; } SegmentGeometry geometry = SegmentGeometry.Get(segmentId); prioritySegments[0] = null; prioritySegments[1] = null; if (tlsMan.GetNodeSimulation(trafficSegment.Node1) == null) { SegmentEnd tmpSeg1 = prioMan.GetPrioritySegment(trafficSegment.Node1, segmentId); bool startNode = geometry.StartNodeId() == trafficSegment.Node1; if (tmpSeg1 != null && !geometry.IsOutgoingOneWay(startNode)) { prioritySegments[0] = tmpSeg1; nodeIdsWithSigns.Add(trafficSegment.Node1); prioMan.AddPriorityNode(trafficSegment.Node1); } } if (tlsMan.GetNodeSimulation(trafficSegment.Node2) == null) { SegmentEnd tmpSeg2 = prioMan.GetPrioritySegment(trafficSegment.Node2, segmentId); bool startNode = geometry.StartNodeId() == trafficSegment.Node2; if (tmpSeg2 != null && !geometry.IsOutgoingOneWay(startNode)) { prioritySegments[1] = tmpSeg2; nodeIdsWithSigns.Add(trafficSegment.Node2); prioMan.AddPriorityNode(trafficSegment.Node2); } } //Log.Message("init ok"); foreach (var prioritySegment in prioritySegments) { if (prioritySegment == null) { continue; } 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; bool setUndefinedSignsToMainRoad = false; 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; setUndefinedSignsToMainRoad = true; 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; setUndefinedSignsToMainRoad = true; 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.Main; 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; if (prioritySegment.Type == SegmentEnd.PriorityType.Yield) { setUndefinedSignsToMainRoad = true; } clicked = false; } break; } if (setUndefinedSignsToMainRoad) { foreach (var otherPrioritySegment in prioMan.GetPrioritySegments(nodeId)) { if (otherPrioritySegment.SegmentId == prioritySegment.SegmentId) { continue; } if (otherPrioritySegment.Type == SegmentEnd.PriorityType.None) { otherPrioritySegment.Type = SegmentEnd.PriorityType.Main; } } } } } 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 * MainTool.GetBaseZoom(); var size = 90f * 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; TrafficLightSimulation nodeSim = tlsMan.GetNodeSimulation(HoveredNodeId); if ((Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None) { // no traffic light set ok = true; } else if (nodeSim == null || !nodeSim.IsTimedLight()) { ok = true; } if (!Flags.mayHaveTrafficLight(HoveredNodeId)) { ok = false; } if (clicked) { Log._Debug("_guiPrioritySigns: hovered+clicked @ nodeId=" + HoveredNodeId + "/" + hoveredExistingNodeId + " ok=" + ok); if (delete) { prioMan.RemovePrioritySegments(hoveredExistingNodeId); RefreshCurrentPrioritySegmentIds(); } else if (ok) { //if (!prioMan.IsPriorityNode(HoveredNodeId)) { Log._Debug("_guiPrioritySigns: adding prio segments @ nodeId=" + HoveredNodeId); tlsMan.RemoveNodeFromSimulation(HoveredNodeId, false, true); tlm.RemoveTrafficLight(HoveredNodeId); prioMan.AddPriorityNode(HoveredNodeId); RefreshCurrentPrioritySegmentIds(); //} } else if (nodeSim != null && nodeSim.IsTimedLight()) { 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 override void OnToolGUI(Event e) { var hoveredSegment = false; if (SelectedNodeId != 0) { CustomSegmentLightsManager customTrafficLightsManager = CustomSegmentLightsManager.Instance; TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; var nodeSimulation = tlsMan.GetNodeSimulation(SelectedNodeId); if (nodeSimulation == null || !nodeSimulation.IsManualLight()) { return; } nodeSimulation.housekeeping(); /*if (Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode].CountSegments() == 2) { * _guiManualTrafficLightsCrosswalk(ref Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode]); * return; * }*/// TODO check NodeGeometry nodeGeometry = NodeGeometry.Get(SelectedNodeId); foreach (SegmentEndGeometry end in nodeGeometry.SegmentEndGeometries) { if (end == null) { continue; } var position = CalculateNodePositionForSegment(Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId], ref Singleton <NetManager> .instance.m_segments.m_buffer[end.SegmentId]); var segmentLights = customTrafficLightsManager.GetSegmentLights(end.SegmentId, end.StartNode, false); if (segmentLights == null) { continue; } 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, end.SegmentId, screenPos, lightWidth, segmentLights, hoveredSegment); // SWITCH PEDESTRIAN LIGHT guiColor.a = _hoveredButton[0] == end.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, end.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(end.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, end.SegmentId, hoveredSegment, segmentLight); // COUNTER hoveredSegment = RenderCounter(end.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; } } if (end.OutgoingOneWay) { continue; } var hasLeftSegment = end.NumLeftSegments > 0; var hasForwardSegment = end.NumStraightSegments > 0; var hasRightSegment = end.NumRightSegments > 0; switch (segmentLight.CurrentMode) { case CustomSegmentLight.Mode.Simple: hoveredSegment = SimpleManualSegmentLightMode(end.SegmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment); break; case CustomSegmentLight.Mode.SingleLeft: hoveredSegment = LeftForwardRManualSegmentLightMode(hasLeftSegment, end.SegmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment, hasForwardSegment, hasRightSegment); break; case CustomSegmentLight.Mode.SingleRight: hoveredSegment = RightForwardLSegmentLightMode(end.SegmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, hasForwardSegment, hasLeftSegment, segmentLight, hasRightSegment, hoveredSegment); break; default: // left arrow light if (hasLeftSegment) { hoveredSegment = LeftArrowLightMode(end.SegmentId, lightWidth, hasRightSegment, hasForwardSegment, offsetScreenPos, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment); } // forward arrow light if (hasForwardSegment) { hoveredSegment = ForwardArrowLightMode(end.SegmentId, lightWidth, hasRightSegment, offsetScreenPos, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment); } // right arrow light if (hasRightSegment) { hoveredSegment = RightArrowLightMode(end.SegmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment); } break; } } } } if (hoveredSegment) { return; } _hoveredButton[0] = 0; _hoveredButton[1] = 0; }
/// <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 TRACE Singleton <CodeProfiler> .instance.Start("TimedTrafficLightsStep.calcWaitFlow"); #endif #if DEBUGMETRIC bool debug = timedNode.NodeId == 3201; #else bool debug = false; #endif #if DEBUGMETRIC if (debug) { Log.Warning($"TimedTrafficLightsStep.calcWaitFlow: ***START*** @ node {timedNode.NodeId}"); } #endif uint numFlows = 0; uint numWaits = 0; uint curMeanFlow = 0; uint curMeanWait = 0; TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance(); TrafficPriorityManager prioMan = TrafficPriorityManager.Instance(); // we are the master node. calculate traffic data foreach (ushort timedNodeId in timedNode.NodeGroup) { TrafficLightSimulation sim = tlsMan.GetNodeSimulation(timedNodeId); if (sim == null || !sim.IsTimedLight()) { continue; } TimedTrafficLights slaveTimedNode = sim.TimedLight; 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 = prioMan.GetPrioritySegment(timedNodeId, fromSegmentId); if (fromSeg == null) { #if DEBUGMETRIC if (debug) { Log.Warning($"TimedTrafficLightsStep.calcWaitFlow: No priority segment @ seg. {fromSegmentId} found!"); } #endif //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.Instance().GetAllowedVehicleTypes(fromSegmentId, timedNode.NodeId); foreach (KeyValuePair <byte, ExtVehicleType> e2 in segLights.VehicleTypeByLaneIndex) { byte laneIndex = e2.Key; ExtVehicleType vehicleType = e2.Value; if (vehicleType != ExtVehicleType.None && (validVehicleTypes & vehicleType) == ExtVehicleType.None) { continue; } CustomSegmentLight segLight = segLights.GetCustomLight(laneIndex); if (segLight == null) { Log.Warning($"Timed traffic light step: Failed to get custom light for vehicleType {vehicleType} @ seg. {fromSegmentId}, node {timedNode.NodeId}!"); continue; } #if DEBUGMETRIC if (debug) { Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: Checking lane {laneIndex} @ seg. {fromSegmentId}. Vehicle types: {vehicleType}"); } #endif Dictionary <ushort, uint> carsFlowingToSegmentMetric = null; Dictionary <ushort, uint> allCarsToSegmentMetric = null; try { carsFlowingToSegmentMetric = fromSeg.GetVehicleMetricGoingToSegment(false, laneIndex, debug); } catch (Exception ex) { Log.Warning("calcWaitFlow (1): " + ex.ToString()); } try { allCarsToSegmentMetric = fromSeg.GetVehicleMetricGoingToSegment(true, laneIndex, debug); } catch (Exception ex) { Log.Warning("calcWaitFlow (2): " + ex.ToString()); } if (carsFlowingToSegmentMetric == null) { continue; } // build directions from toSegment to fromSegment Dictionary <ushort, ArrowDirection> directions = new Dictionary <ushort, ArrowDirection>(); foreach (KeyValuePair <ushort, uint> f in allCarsToSegmentMetric) { var toSegmentId = f.Key; SegmentGeometry geometry = SegmentGeometry.Get(fromSegmentId); ArrowDirection dir = geometry.GetDirection(toSegmentId, timedNodeId == geometry.StartNodeId()); directions[toSegmentId] = dir; #if DEBUGMETRIC if (debug) { Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: Calculated direction for seg. {fromSegmentId} -> seg. {toSegmentId}: {dir}"); } #endif } // calculate waiting/flowing traffic foreach (KeyValuePair <ushort, uint> f in allCarsToSegmentMetric) { ushort toSegmentId = f.Key; uint totalNormCarLength = f.Value; uint totalFlowingNormCarLength = carsFlowingToSegmentMetric[f.Key]; #if DEBUGMETRIC if (debug) { Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: Total norm. car length of vehicles on lane {laneIndex} going to seg. {toSegmentId}: {totalNormCarLength}"); } #endif bool addToFlow = false; switch (directions[toSegmentId]) { case ArrowDirection.Turn: addToFlow = TrafficPriorityManager.IsLeftHandDrive() ? segLight.isRightGreen() : segLight.isLeftGreen(); break; case ArrowDirection.Left: addToFlow = segLight.isLeftGreen(); break; case ArrowDirection.Right: addToFlow = segLight.isRightGreen(); break; case ArrowDirection.Forward: default: addToFlow = segLight.isForwardGreen(); break; } if (addToFlow) { ++numFlows; curMeanFlow += totalFlowingNormCarLength; } else { ++numWaits; curMeanWait += totalNormCarLength; } #if DEBUGMETRIC if (debug) { Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: Vehicles on lane {laneIndex} on seg. {fromSegmentId} going to seg. {toSegmentId} flowing? {addToFlow} curMeanFlow={curMeanFlow}, curMeanWait={curMeanWait}"); } #endif } } } // delete invalid segments from step /*foreach (int segmentId in segmentIdsToDelete) { * slaveStep.segmentLightStates.Remove(segmentId); * }*/ } #if DEBUGMETRIC if (debug) { Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: ### Calculation completed. numFlows={numFlows}, numWaits={numWaits}, curMeanFlow={curMeanFlow}, curMeanWait={curMeanWait}"); } wait = curMeanWait; flow = curMeanFlow; #else if (numFlows > 0) { curMeanFlow /= numFlows; } if (numWaits > 0) { curMeanWait /= numWaits; } float fCurMeanFlow = curMeanFlow; fCurMeanFlow /= waitFlowBalance; // a value smaller than 1 rewards steady traffic currents wait = (float)curMeanWait; flow = fCurMeanFlow; #endif #if TRACE Singleton <CodeProfiler> .instance.Stop("TimedTrafficLightsStep.calcWaitFlow"); #endif return(true); }
public void SimulationStep() { // TODO [version 1.9] this method is currently called on each node, but should be called on the master node only if (!IsMasterNode() || !IsStarted()) { #if DEBUGTTL Log._Debug($"TTL SimStep: *STOP* NodeId={NodeId} isMasterNode={isMasterNode()} IsStarted={IsStarted()}"); #endif return; } // we are the master node /*if (!housekeeping()) { #if DEBUGTTL * Log.Warning($"TTL SimStep: *STOP* NodeId={NodeId} Housekeeping detected that this timed traffic light has become invalid: {NodeId}."); #endif * Stop(); * return; * }*/ #if DEBUGTTL Log._Debug($"TTL SimStep: NodeId={NodeId} Setting lights (1)"); #endif SetLights(); if (!Steps[CurrentStep].StepDone(true)) { #if DEBUGTTL Log._Debug($"TTL SimStep: *STOP* NodeId={NodeId} current step ({CurrentStep}) is not done."); #endif return; } // step is done #if DEBUGTTL Log._Debug($"TTL SimStep: NodeId={NodeId} Setting lights (2)"); #endif #if DEBUG bool debug = GlobalConfig.Instance.DebugSwitches[7] && GlobalConfig.Instance.TTLDebugNodeId == NodeId; #endif TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; if (Steps[CurrentStep].NextStepRefIndex < 0) { #if DEBUG if (debug) { Log._Debug($"Step {CurrentStep} is done at timed light {NodeId}. Determining next step."); } #endif // next step has not yet identified yet. check for minTime=0 steps int nextStepIndex = (CurrentStep + 1) % NumSteps(); if (Steps[nextStepIndex].minTime == 0) { // next step has minTime=0. calculate flow/wait ratios and compare. int prevStepIndex = CurrentStep; float maxWaitFlowDiff = Steps[CurrentStep].minFlow - Steps[CurrentStep].maxWait; if (float.IsNaN(maxWaitFlowDiff)) { maxWaitFlowDiff = float.MinValue; } int bestNextStepIndex = prevStepIndex; #if DEBUG if (debug) { Log._Debug($"Next step {nextStepIndex} has minTime = 0 at timed light {NodeId}. Old step {CurrentStep} has waitFlowDiff={maxWaitFlowDiff} (flow={Steps[CurrentStep].minFlow}, wait={Steps[CurrentStep].maxWait})."); } #endif while (nextStepIndex != prevStepIndex) { float wait; float flow; Steps[nextStepIndex].calcWaitFlow(false, nextStepIndex, out wait, out flow); float flowWaitDiff = flow - wait; if (flowWaitDiff > maxWaitFlowDiff) { maxWaitFlowDiff = flowWaitDiff; bestNextStepIndex = nextStepIndex; } #if DEBUG if (debug) { Log._Debug($"Checking upcoming step {nextStepIndex} @ node {NodeId}: flow={flow} wait={wait} minTime={Steps[nextStepIndex].minTime}. bestWaitFlowDiff={bestNextStepIndex}, bestNextStepIndex={bestNextStepIndex}"); } #endif if (Steps[nextStepIndex].minTime != 0) { break; } nextStepIndex = (nextStepIndex + 1) % NumSteps(); } if (bestNextStepIndex == CurrentStep) { #if DEBUG if (debug) { Log._Debug($"Best next step {bestNextStepIndex} (wait/flow diff = {maxWaitFlowDiff}) equals CurrentStep @ node {NodeId}."); } #endif // restart the current step foreach (ushort slaveNodeId in NodeGroup) { TrafficLightSimulation slaveSim = tlsMan.GetNodeSimulation(slaveNodeId); if (slaveSim == null || !slaveSim.IsTimedLight()) { continue; } slaveSim.TimedLight.Steps[CurrentStep].Start(CurrentStep); slaveSim.TimedLight.Steps[CurrentStep].UpdateLiveLights(); } return; } else { #if DEBUG if (debug) { Log._Debug($"Best next step {bestNextStepIndex} (wait/flow diff = {maxWaitFlowDiff}) does not equal CurrentStep @ node {NodeId}."); } #endif // set next step reference index for assuring a correct end transition foreach (ushort slaveNodeId in NodeGroup) { TrafficLightSimulation slaveSim = tlsMan.GetNodeSimulation(slaveNodeId); if (slaveSim == null || !slaveSim.IsTimedLight()) { continue; } TimedTrafficLights timedLights = slaveSim.TimedLight; timedLights.Steps[CurrentStep].NextStepRefIndex = bestNextStepIndex; } } } else { Steps[CurrentStep].NextStepRefIndex = nextStepIndex; } } SetLights(); // check if this is needed if (!Steps[CurrentStep].IsEndTransitionDone()) { #if DEBUGTTL Log._Debug($"TTL SimStep: *STOP* NodeId={NodeId} current step ({CurrentStep}): end transition is not done."); #endif return; } // ending transition (yellow) finished #if DEBUGTTL Log._Debug($"TTL SimStep: NodeId={NodeId} ending transition done. NodeGroup={string.Join(", ", NodeGroup.Select(x => x.ToString()).ToArray())}, nodeId={NodeId}, NumSteps={NumSteps()}"); #endif // change step int newStepIndex = Steps[CurrentStep].NextStepRefIndex; int oldStepIndex = CurrentStep; foreach (ushort slaveNodeId in NodeGroup) { TrafficLightSimulation slaveSim = tlsMan.GetNodeSimulation(slaveNodeId); if (slaveSim == null || !slaveSim.IsTimedLight()) { continue; } TimedTrafficLights timedLights = slaveSim.TimedLight; timedLights.CurrentStep = newStepIndex; #if DEBUGTTL Log._Debug($"TTL SimStep: NodeId={slaveNodeId} setting lgihts of next step: {CurrentStep}"); #endif timedLights.Steps[oldStepIndex].NextStepRefIndex = -1; timedLights.Steps[newStepIndex].Start(oldStepIndex); timedLights.Steps[newStepIndex].UpdateLiveLights(); } }
public override void OnToolGUI(Event e) { IExtSegmentManager segMan = Constants.ManagerFactory.ExtSegmentManager; IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager; var hoveredSegment = false; if (SelectedNodeId != 0) { CustomSegmentLightsManager customTrafficLightsManager = CustomSegmentLightsManager.Instance; TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; JunctionRestrictionsManager junctionRestrictionsManager = JunctionRestrictionsManager.Instance; if (!tlsMan.HasManualSimulation(SelectedNodeId)) { return; } tlsMan.TrafficLightSimulations[SelectedNodeId].Housekeeping(); // TODO check // if (Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode].CountSegments() == 2) { // _guiManualTrafficLightsCrosswalk( // ref Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode]); // return; // } NetNode[] nodesBuffer = Singleton <NetManager> .instance.m_nodes.m_buffer; NetSegment[] segmentsBuffer = Singleton <NetManager> .instance.m_segments.m_buffer; for (int i = 0; i < 8; ++i) { ushort segmentId = nodesBuffer[SelectedNodeId].GetSegment(i); if (segmentId == 0) { continue; } bool startNode = (bool)Constants.ServiceFactory.NetService.IsStartNode( segmentId, SelectedNodeId); Vector3 position = CalculateNodePositionForSegment( nodesBuffer[SelectedNodeId], ref segmentsBuffer[segmentId]); ICustomSegmentLights segmentLights = customTrafficLightsManager.GetSegmentLights(segmentId, startNode, false); if (segmentLights == null) { continue; } bool showPedLight = segmentLights.PedestrianLightState != null && junctionRestrictionsManager.IsPedestrianCrossingAllowed( segmentLights.SegmentId, segmentLights.StartNode); bool visible = MainTool.WorldToScreenPoint(position, out Vector3 screenPos); if (!visible) { continue; } Vector3 diff = position - Camera.main.transform.position; float zoom = 1.0f / diff.magnitude * 100f; // original / 2.5 float lightWidth = 41f * zoom; float lightHeight = 97f * zoom; float pedestrianWidth = 36f * zoom; float pedestrianHeight = 61f * zoom; // SWITCH MODE BUTTON float modeWidth = 41f * zoom; float modeHeight = 38f * zoom; Color guiColor = GUI.color; if (showPedLight) { // pedestrian light // SWITCH MANUAL PEDESTRIAN LIGHT BUTTON hoveredSegment = RenderManualPedestrianLightSwitch( zoom, segmentId, screenPos, lightWidth, segmentLights, hoveredSegment); // SWITCH PEDESTRIAN LIGHT guiColor.a = TrafficManagerTool.GetHandleAlpha( hoveredButton[0] == segmentId && hoveredButton[1] == 2 && segmentLights.ManualPedestrianMode); 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, TrafficLightTextures.PedestrianGreenLight); break; } // also: case RoadBaseAI.TrafficLightState.Red: default: { GUI.DrawTexture( myRect3, TrafficLightTextures.PedestrianRedLight); break; } } hoveredSegment = IsPedestrianLightHovered( myRect3, segmentId, hoveredSegment, segmentLights); } int lightOffset = -1; foreach (ExtVehicleType vehicleType in segmentLights.VehicleTypes) { ++lightOffset; ICustomSegmentLight 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, TrafficLightTextures.LightMode); hoveredSegment = GetHoveredSegment( myRect1, segmentId, hoveredSegment, segmentLight); // COUNTER hoveredSegment = RenderCounter( segmentId, offsetScreenPos, modeWidth, modeHeight, zoom, segmentLights, hoveredSegment); if (vehicleType != ExtVehicleType.None) { // Info sign float infoWidth = 56.125f * zoom; float 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 = TrafficManagerTool.GetHandleAlpha(false); GUI.DrawTexture( infoRect, RoadUITextures.VehicleInfoSignTextures[TrafficManagerTool.InfoSignsToDisplay[k]]); ++numInfos; } } ExtSegment seg = segMan.ExtSegments[segmentId]; ExtSegmentEnd segEnd = segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, startNode)]; if (seg.oneWay && segEnd.outgoing) { continue; } segEndMan.CalculateOutgoingLeftStraightRightSegments( ref segEnd, ref nodesBuffer[segmentId], out bool hasLeftSegment, out bool hasForwardSegment, out bool hasRightSegment); switch (segmentLight.CurrentMode) { case LightMode.Simple: { hoveredSegment = SimpleManualSegmentLightMode( segmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment); break; } case LightMode.SingleLeft: { hoveredSegment = LeftForwardRManualSegmentLightMode( hasLeftSegment, segmentId, offsetScreenPos, lightWidth, pedestrianWidth, zoom, lightHeight, segmentLight, hoveredSegment, hasForwardSegment, hasRightSegment); break; } case LightMode.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; } } // end switch } // end foreach all vehicle type } // end for all 8 segments } // end if a node is selected if (hoveredSegment) { return; } hoveredButton[0] = 0; hoveredButton[1] = 0; }
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!"); } }
public override void OnSaveData() { bool error = false; /*try { * Log.Info("Recalculating segment geometries"); * SegmentGeometry.OnBeforeSaveData(); * } catch (Exception e) { * Log.Error($"OnSaveData: Exception occurred while calling SegmentGeometry.OnBeforeSaveData: {e.ToString()}"); * error = true; * }*/ try { Log.Info("Applying all flags"); Flags.applyAllFlags(); } catch (Exception e) { Log.Error($"OnSaveData: Exception occurred while applying all flags: {e.ToString()}"); error = true; } try { Log.Info("Saving Mod Data."); var configuration = new Configuration(); TrafficPriorityManager prioMan = TrafficPriorityManager.Instance(); if (prioMan.TrafficSegments != null) { for (ushort i = 0; i < Singleton <NetManager> .instance.m_segments.m_size; i++) { try { SavePrioritySegment(i, configuration); } catch (Exception e) { Log.Error($"Exception occurred while saving priority segment @ {i}: {e.ToString()}"); error = true; } try { SaveSegmentNodeFlags(i, configuration); } catch (Exception e) { Log.Error($"Exception occurred while saving segment node flags @ {i}: {e.ToString()}"); error = true; } } } TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance(); for (ushort i = 0; i < Singleton <NetManager> .instance.m_nodes.m_size; i++) { /*if (TrafficLightSimulation.LightSimulationByNodeId != null) { * SaveTrafficLightSimulation(i, configuration); * }*/ /*if (TrafficLightsManual.ManualSegments != null) { * SaveManualTrafficLight(i, configuration); * }*/ TrafficLightSimulation sim = tlsMan.GetNodeSimulation(i); if (sim != null && sim.IsTimedLight()) { try { SaveTimedTrafficLight(i, configuration); } catch (Exception e) { Log.Error($"Exception occurred while saving timed traffic light @ {i}: {e.ToString()}"); error = true; } // TODO save new traffic lights } try { SaveNodeLights(i, configuration); } catch (Exception e) { Log.Error($"Exception occurred while saving node traffic light @ {i}: {e.ToString()}"); error = true; } } #if !TAM if (LoadingExtension.IsPathManagerCompatible) { #endif for (uint i = 0; i < Singleton <NetManager> .instance.m_lanes.m_buffer.Length; i++) { try { SaveLaneData(i, configuration); } catch (Exception e) { Log.Error($"Exception occurred while saving lane data @ {i}: {e.ToString()}"); error = true; } } #if !TAM } #endif foreach (KeyValuePair <uint, ushort> e in Flags.getAllLaneSpeedLimits()) { try { SaveLaneSpeedLimit(new Configuration.LaneSpeedLimit(e.Key, e.Value), configuration); } catch (Exception ex) { Log.Error($"Exception occurred while saving lane speed limit @ {e.Key}: {ex.ToString()}"); error = true; } } foreach (KeyValuePair <uint, ExtVehicleType> e in Flags.getAllLaneAllowedVehicleTypes()) { try { SaveLaneAllowedVehicleTypes(new Configuration.LaneVehicleTypes(e.Key, e.Value), configuration); } catch (Exception ex) { Log.Error($"Exception occurred while saving lane vehicle restrictions @ {e.Key}: {ex.ToString()}"); error = true; } } var binaryFormatter = new BinaryFormatter(); var memoryStream = new MemoryStream(); try { binaryFormatter.Serialize(memoryStream, configuration); memoryStream.Position = 0; Log.Info($"Save data byte length {memoryStream.Length}"); _serializableData.SaveData(DataId, memoryStream.ToArray()); } catch (Exception ex) { Log.Error("Unexpected error while saving data: " + ex.ToString()); error = true; } finally { memoryStream.Close(); } try { // save options _serializableData.SaveData("TMPE_Options", new byte[] { (byte)Options.simAccuracy, (byte)0, //Options.laneChangingRandomization, (byte)Options.recklessDrivers, (byte)(Options.relaxedBusses ? 1 : 0), (byte)(Options.nodesOverlay ? 1 : 0), (byte)(Options.allowEnterBlockedJunctions ? 1 : 0), (byte)(Options.advancedAI ? 1 : 0), (byte)(Options.highwayRules ? 1 : 0), (byte)(Options.prioritySignsOverlay ? 1 : 0), (byte)(Options.timedLightsOverlay ? 1 : 0), (byte)(Options.speedLimitsOverlay ? 1 : 0), (byte)(Options.vehicleRestrictionsOverlay ? 1 : 0), (byte)(Options.strongerRoadConditionEffects ? 1 : 0), (byte)(Options.allowUTurns ? 1 : 0), (byte)(Options.allowLaneChangesWhileGoingStraight ? 1 : 0), (byte)(Options.enableDespawning ? 1 : 0), (byte)(Options.IsDynamicPathRecalculationActive() ? 1 : 0), (byte)(Options.connectedLanesOverlay ? 1 : 0), (byte)(Options.prioritySignsEnabled ? 1 : 0), (byte)(Options.timedLightsEnabled ? 1 : 0), (byte)(Options.customSpeedLimitsEnabled ? 1 : 0), (byte)(Options.vehicleRestrictionsEnabled ? 1 : 0), (byte)(Options.laneConnectorEnabled ? 1 : 0), (byte)(Options.junctionRestrictionsOverlay ? 1 : 0), (byte)(Options.junctionRestrictionsEnabled ? 1 : 0) }); } catch (Exception ex) { Log.Error("Unexpected error while saving options: " + ex.Message); error = true; } } catch (Exception e) { error = true; Log.Error($"Error occurred while saving data: {e.ToString()}"); //UIView.library.ShowModal<ExceptionPanel>("ExceptionPanel").SetMessage("An error occurred while saving", "Traffic Manager: President Edition detected an error while saving. To help preventing future errors, please navigate to http://steamcommunity.com/sharedfiles/filedetails/?id=583429740 and follow the steps under 'In case problems arise'.", true); } }
private static void SaveTimedTrafficLight(ushort i, Configuration configuration) { try { TrafficLightSimulation sim = TrafficLightSimulationManager.Instance().GetNodeSimulation(i); if (sim == null || !sim.IsTimedLight()) { return; } Log._Debug($"Going to save timed light at node {i}."); var timedNode = sim.TimedLight; timedNode.handleNewSegments(); Configuration.TimedTrafficLights cnfTimedLights = new Configuration.TimedTrafficLights(); configuration.TimedLights.Add(cnfTimedLights); cnfTimedLights.nodeId = timedNode.NodeId; cnfTimedLights.nodeGroup = timedNode.NodeGroup; cnfTimedLights.started = timedNode.IsStarted(); cnfTimedLights.timedSteps = new List <Configuration.TimedTrafficLightsStep>(); for (var j = 0; j < timedNode.NumSteps(); j++) { Log._Debug($"Saving timed light step {j} at node {i}."); TimedTrafficLightsStep timedStep = timedNode.Steps[j]; Configuration.TimedTrafficLightsStep cnfTimedStep = new Configuration.TimedTrafficLightsStep(); cnfTimedLights.timedSteps.Add(cnfTimedStep); cnfTimedStep.minTime = timedStep.minTime; cnfTimedStep.maxTime = timedStep.maxTime; cnfTimedStep.waitFlowBalance = timedStep.waitFlowBalance; cnfTimedStep.segmentLights = new Dictionary <ushort, Configuration.CustomSegmentLights>(); foreach (KeyValuePair <ushort, CustomSegmentLights> e in timedStep.segmentLights) { Log._Debug($"Saving timed light step {j}, segment {e.Key} at node {i}."); CustomSegmentLights segLights = e.Value; Configuration.CustomSegmentLights cnfSegLights = new Configuration.CustomSegmentLights(); cnfTimedStep.segmentLights.Add(e.Key, cnfSegLights); cnfSegLights.nodeId = segLights.NodeId; cnfSegLights.segmentId = segLights.SegmentId; cnfSegLights.customLights = new Dictionary <ExtVehicleType, Configuration.CustomSegmentLight>(); cnfSegLights.pedestrianLightState = segLights.PedestrianLightState; cnfSegLights.manualPedestrianMode = segLights.ManualPedestrianMode; Log._Debug($"Saving pedestrian light @ seg. {e.Key}, step {j}: {cnfSegLights.pedestrianLightState} {cnfSegLights.manualPedestrianMode}"); foreach (KeyValuePair <ExtVehicleType, CustomSegmentLight> e2 in segLights.CustomLights) { Log._Debug($"Saving timed light step {j}, segment {e.Key}, vehicleType {e2.Key} at node {i}."); CustomSegmentLight segLight = e2.Value; Configuration.CustomSegmentLight cnfSegLight = new Configuration.CustomSegmentLight(); cnfSegLights.customLights.Add(e2.Key, cnfSegLight); cnfSegLight.nodeId = segLight.NodeId; cnfSegLight.segmentId = segLight.SegmentId; cnfSegLight.currentMode = (int)segLight.CurrentMode; cnfSegLight.leftLight = segLight.LightLeft; cnfSegLight.mainLight = segLight.LightMain; cnfSegLight.rightLight = segLight.LightRight; } } } } catch (Exception e) { Log.Error($"Error adding TimedTrafficLights to save {e.Message}"); } }
internal void Join(TimedTrafficLights otherTimedLight) { TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance(); if (NumSteps() < otherTimedLight.NumSteps()) { // increase the number of steps at our timed lights for (int i = NumSteps(); i < otherTimedLight.NumSteps(); ++i) { TimedTrafficLightsStep otherStep = otherTimedLight.GetStep(i); foreach (ushort slaveNodeId in NodeGroup) { TrafficLightSimulation ourSim = tlsMan.GetNodeSimulation(slaveNodeId); if (ourSim == null || !ourSim.IsTimedLight()) { continue; } TimedTrafficLights ourTimedLight = ourSim.TimedLight; ourTimedLight.AddStep(otherStep.minTime, otherStep.maxTime, otherStep.waitFlowBalance, true); } } } else { // increase the number of steps at their timed lights for (int i = otherTimedLight.NumSteps(); i < NumSteps(); ++i) { TimedTrafficLightsStep ourStep = GetStep(i); foreach (ushort slaveNodeId in otherTimedLight.NodeGroup) { TrafficLightSimulation theirSim = tlsMan.GetNodeSimulation(slaveNodeId); if (theirSim == null || !theirSim.IsTimedLight()) { continue; } TimedTrafficLights theirTimedLight = theirSim.TimedLight; theirTimedLight.AddStep(ourStep.minTime, ourStep.maxTime, ourStep.waitFlowBalance, true); } } } // join groups and re-defined master node, determine mean min/max times & mean wait-flow-balances HashSet <ushort> newNodeGroupSet = new HashSet <ushort>(); newNodeGroupSet.UnionWith(NodeGroup); newNodeGroupSet.UnionWith(otherTimedLight.NodeGroup); List <ushort> newNodeGroup = new List <ushort>(newNodeGroupSet); ushort newMasterNodeId = newNodeGroup[0]; int[] minTimes = new int[NumSteps()]; int[] maxTimes = new int[NumSteps()]; float[] waitFlowBalances = new float[NumSteps()]; foreach (ushort timedNodeId in newNodeGroup) { TrafficLightSimulation timedSim = tlsMan.GetNodeSimulation(timedNodeId); if (timedSim == null || !timedSim.IsTimedLight()) { continue; } TimedTrafficLights timedLight = timedSim.TimedLight; for (int i = 0; i < NumSteps(); ++i) { minTimes[i] += timedLight.GetStep(i).minTime; maxTimes[i] += timedLight.GetStep(i).maxTime; waitFlowBalances[i] += timedLight.GetStep(i).waitFlowBalance; } timedLight.NodeGroup = newNodeGroup; timedLight.masterNodeId = newMasterNodeId; } // build means if (NumSteps() > 0) { for (int i = 0; i < NumSteps(); ++i) { minTimes[i] = Math.Max(1, minTimes[i] / newNodeGroup.Count); maxTimes[i] = Math.Max(1, maxTimes[i] / newNodeGroup.Count); waitFlowBalances[i] = Math.Max(0.001f, waitFlowBalances[i] / (float)newNodeGroup.Count); } } // apply means & reset foreach (ushort timedNodeId in newNodeGroup) { TrafficLightSimulation timedSim = tlsMan.GetNodeSimulation(timedNodeId); if (timedSim == null || !timedSim.IsTimedLight()) { continue; } TimedTrafficLights timedLight = timedSim.TimedLight; timedLight.Stop(); timedLight.testMode = false; timedLight.lastSimulationStep = 0; for (int i = 0; i < NumSteps(); ++i) { timedLight.GetStep(i).minTime = minTimes[i]; timedLight.GetStep(i).maxTime = maxTimes[i]; timedLight.GetStep(i).waitFlowBalance = waitFlowBalances[i]; } } }
/// <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(bool onlyMoving, int stepRefIndex, out float wait, out float flow) { uint numFlows = 0; uint numWaits = 0; uint curMeanFlow = 0; uint curMeanWait = 0; // TODO checking agains getCurrentFrame() is only valid if this is the current step if (onlyMoving && getCurrentFrame() <= startFrame + minTime + 1) // during start phase all vehicles on "green" segments are counted as flowing { onlyMoving = false; } TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; TrafficPriorityManager prioMan = TrafficPriorityManager.Instance; foreach (ushort timedNodeId in timedNode.NodeGroup) { TrafficLightSimulation sim = tlsMan.GetNodeSimulation(timedNodeId); if (sim == null || !sim.IsTimedLight()) { continue; } TimedTrafficLights slaveTimedNode = sim.TimedLight; TimedTrafficLightsStep slaveStep = slaveTimedNode.Steps[stepRefIndex]; //List<int> segmentIdsToDelete = new List<int>(); // minimum time reached. check traffic! foreach (KeyValuePair <ushort, CustomSegmentLights> e in slaveStep.segmentLights) { var sourceSegmentId = e.Key; var segLights = e.Value; #if DEBUGMETRIC bool debug = sourceSegmentId == 20857 && GlobalConfig.Instance.DebugSwitches[1]; #elif DEBUG bool debug = GlobalConfig.Instance.DebugSwitches[7] && GlobalConfig.Instance.TTLDebugNodeId == timedNodeId; #else bool debug = false; #endif Dictionary <ushort, ArrowDirection> directions = null; if (slaveStep.timedNode.Directions.ContainsKey(sourceSegmentId)) { directions = slaveStep.timedNode.Directions[sourceSegmentId]; } else { #if DEBUG if (debug) { Log._Debug($"calcWaitFlow: No arrow directions defined for segment {sourceSegmentId} @ {timedNodeId}"); } #endif continue; } // one of the traffic lights at this segment is green: count minimum traffic flowing through SegmentEnd sourceSegmentEnd = prioMan.GetPrioritySegment(timedNodeId, sourceSegmentId); if (sourceSegmentEnd == null) { Log.Warning($"TimedTrafficLightsStep.calcWaitFlow: No priority segment @ seg. {sourceSegmentId} found!"); continue; // skip invalid segment } ExtVehicleType validVehicleTypes = VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(sourceSegmentId, timedNode.NodeId); foreach (KeyValuePair <byte, ExtVehicleType> e2 in segLights.VehicleTypeByLaneIndex) { byte laneIndex = e2.Key; ExtVehicleType vehicleType = e2.Value; if (vehicleType != ExtVehicleType.None && (validVehicleTypes & vehicleType) == ExtVehicleType.None) { continue; } CustomSegmentLight segLight = segLights.GetCustomLight(laneIndex); if (segLight == null) { Log.Warning($"Timed traffic light step: Failed to get custom light for vehicleType {vehicleType} @ seg. {sourceSegmentId}, node {timedNode.NodeId}!"); continue; } #if DEBUG if (debug) { Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: Checking lane {laneIndex} @ seg. {sourceSegmentId}. Vehicle types: {vehicleType}"); } #endif Dictionary <ushort, uint> carsFlowingToSegmentMetric = null; Dictionary <ushort, uint> allCarsToSegmentMetric = null; bool evalFlowingVehicles = segLight.IsAnyGreen(); // flowing vehicle need only to be evaluated if a light is green if (evalFlowingVehicles && onlyMoving) { carsFlowingToSegmentMetric = sourceSegmentEnd.GetVehicleMetricGoingToSegment(false, laneIndex, debug); } allCarsToSegmentMetric = sourceSegmentEnd.GetVehicleMetricGoingToSegment(true, laneIndex, debug); // calculate waiting/flowing traffic foreach (KeyValuePair <ushort, uint> f in allCarsToSegmentMetric) { ushort targetSegmentId = f.Key; uint totalNumCars = f.Value; if (!directions.ContainsKey(targetSegmentId)) { Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: Direction undefined for target segment {targetSegmentId} @ {timedNodeId}"); continue; } if (evalFlowingVehicles) { uint totalNumFlowingCars = onlyMoving ? carsFlowingToSegmentMetric[f.Key] : totalNumCars; #if DEBUG if (debug) { Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: Total num of flowing cars on seg. {sourceSegmentId}, lane {laneIndex} going to seg. {targetSegmentId}: {totalNumFlowingCars}"); } #endif bool addToFlow = false; switch (directions[targetSegmentId]) { case ArrowDirection.Turn: addToFlow = TrafficPriorityManager.IsLeftHandDrive() ? segLight.IsRightGreen() : segLight.IsLeftGreen(); break; case ArrowDirection.Left: addToFlow = segLight.IsLeftGreen(); break; case ArrowDirection.Right: addToFlow = segLight.IsRightGreen(); break; case ArrowDirection.Forward: default: addToFlow = segLight.IsMainGreen(); break; } if (addToFlow) { curMeanFlow += totalNumFlowingCars; ++numFlows; } else { curMeanWait += totalNumCars; ++numWaits; } } else { curMeanWait += totalNumCars; ++numWaits; } #if DEBUG if (debug) { Log._Debug($"TimedTrafficLightsStep.calcWaitFlow: Vehicles on lane {laneIndex} on seg. {sourceSegmentId} going to seg. {targetSegmentId} curMeanFlow={curMeanFlow}, curMeanWait={curMeanWait}, numFlows={numFlows}, numWaits={numWaits}"); } #endif } } } } /*if (numFlows > 0) * curMeanFlow /= numFlows; * if (numWaits > 0) * curMeanWait /= numWaits;*/ float fCurMeanFlow = numFlows > 0 ? (float)curMeanFlow / (float)numFlows : 0; float fCurMeanWait = numWaits > 0 ? (float)curMeanWait / (float)numWaits : 0; fCurMeanFlow /= waitFlowBalance; // a value smaller than 1 rewards steady traffic currents wait = (float)fCurMeanWait; flow = fCurMeanFlow; return(true); }
public void ShowGUI(bool viewOnly) { try { IExtSegmentManager segMan = Constants.ManagerFactory.ExtSegmentManager; IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager; TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance; TrafficPriorityManager prioMan = TrafficPriorityManager.Instance; TrafficLightManager tlm = TrafficLightManager.Instance; Vector3 camPos = Constants.ServiceFactory.SimulationService.CameraPosition; bool clicked = !viewOnly?MainTool.CheckClicked() : false; ushort removedNodeId = 0; bool showRemoveButton = false; foreach (ushort nodeId in currentPriorityNodeIds) { if (!Constants.ServiceFactory.NetService.IsNodeValid(nodeId)) { continue; } if (!MainTool.IsNodeWithinViewDistance(nodeId)) { continue; } Vector3 nodePos = default(Vector3); Constants.ServiceFactory.NetService.ProcessNode(nodeId, delegate(ushort nId, ref NetNode node) { nodePos = node.m_position; return(true); }); for (int i = 0; i < 8; ++i) { ushort segmentId = 0; Constants.ServiceFactory.NetService.ProcessNode(nodeId, delegate(ushort nId, ref NetNode node) { segmentId = node.GetSegment(i); return(true); }); if (segmentId == 0) { continue; } bool startNode = (bool)Constants.ServiceFactory.NetService.IsStartNode(segmentId, nodeId); ExtSegment seg = segMan.ExtSegments[segmentId]; ExtSegmentEnd segEnd = segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, startNode)]; if (seg.oneWay && segEnd.outgoing) { continue; } // calculate sign position Vector3 signPos = nodePos; Constants.ServiceFactory.NetService.ProcessSegment(segmentId, delegate(ushort sId, ref NetSegment segment) { signPos += 10f * (startNode ? segment.m_startDirection : segment.m_endDirection); return(true); }); Vector3 signScreenPos; if (!MainTool.WorldToScreenPoint(signPos, out signScreenPos)) { continue; } // draw sign and handle input PriorityType sign = prioMan.GetPrioritySign(segmentId, startNode); if (viewOnly && sign == PriorityType.None) { continue; } if (!viewOnly && sign != PriorityType.None) { showRemoveButton = true; } if (MainTool.DrawGenericSquareOverlayTexture(TextureResources.PrioritySignTextures[sign], camPos, signPos, 90f, !viewOnly) && clicked) { PriorityType?newSign = null; switch (sign) { case PriorityType.Main: newSign = PriorityType.Yield; break; case PriorityType.Yield: newSign = PriorityType.Stop; break; case PriorityType.Stop: newSign = PriorityType.Main; break; case PriorityType.None: default: newSign = prioMan.CountPrioritySignsAtNode(nodeId, PriorityType.Main) >= 2 ? PriorityType.Yield : PriorityType.Main; break; } if (newSign != null) { SetPrioritySign(segmentId, startNode, (PriorityType)newSign); } } // draw sign } // foreach segment end if (viewOnly) { continue; } // draw remove button and handle click if (showRemoveButton && MainTool.DrawHoverableSquareOverlayTexture(TextureResources.SignRemoveTexture2D, camPos, nodePos, 90f) && clicked) { prioMan.RemovePrioritySignsFromNode(nodeId); Log._Debug($"PrioritySignsTool.ShowGUI: Removed priority signs from node {nodeId}"); removedNodeId = nodeId; } } // foreach node if (removedNodeId != 0) { currentPriorityNodeIds.Remove(removedNodeId); SelectedNodeId = 0; } } catch (Exception e) { Log.Error(e.ToString()); } }
internal void Recalculate() { #if DEBUGGEO Log._Debug($"NodeGeometry: Recalculate @ {NodeId}"); #endif Cleanup(); Flags.applyNodeTrafficLightFlag(NodeId); TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance(); // check if node is valid if (!IsValid()) { for (int i = 0; i < 8; ++i) { SegmentEndGeometries[i] = null; } tlsMan.RemoveNodeFromSimulation(NodeId, false, true); Flags.setNodeTrafficLight(NodeId, false); } else { NetManager netManager = Singleton <NetManager> .instance; TrafficPriorityManager prioMan = TrafficPriorityManager.Instance(); bool hasTrafficLight = (netManager.m_nodes.m_buffer[NodeId].m_flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None; var nodeSim = tlsMan.GetNodeSimulation(NodeId); if (nodeSim == null) { byte numSegmentsWithSigns = 0; for (var s = 0; s < 8; s++) { var segmentId = netManager.m_nodes.m_buffer[NodeId].GetSegment(s); if (segmentId <= 0) { continue; } #if DEBUGx Log._Debug($"NodeGeometry.Recalculate: Housekeeping segment {segmentId}"); #endif SegmentEnd prioritySegment = prioMan.GetPrioritySegment(NodeId, segmentId); if (prioritySegment == null) { continue; } // if node is a traffic light, it must not have priority signs if (hasTrafficLight && prioritySegment.Type != SegmentEnd.PriorityType.None) { Log.Warning($"Housekeeping: Node {NodeId}, Segment {segmentId} is a priority sign but node has a traffic light!"); prioritySegment.Type = SegmentEnd.PriorityType.None; } // if a priority sign is set, everything is ok if (prioritySegment.Type != SegmentEnd.PriorityType.None) { ++numSegmentsWithSigns; } } if (numSegmentsWithSigns > 0) { // add priority segments for newly created segments numSegmentsWithSigns += prioMan.AddPriorityNode(NodeId); } } // calculate node properties byte incomingSegments = 0; byte outgoingSegments = 0; for (int i = 0; i < 8; ++i) { if (SegmentEndGeometries[i] == null) { continue; } #if DEBUGGEO Log._Debug($"NodeGeometry.Recalculate: Iterating over segment end {SegmentEndGeometries[i].SegmentId} @ node {NodeId}"); #endif bool startNode = SegmentEndGeometries[i].StartNode; if (SegmentEndGeometries[i].GetSegmentGeometry().IsIncoming(startNode)) { ++incomingSegments; } if (SegmentEndGeometries[i].GetSegmentGeometry().IsOutgoing(startNode)) { ++outgoingSegments; } } IsSimpleJunction = incomingSegments == 1 || outgoingSegments == 1; #if DEBUGGEO Log._Debug($"NodeGeometry.Recalculate: Node {NodeId} has {incomingSegments} incoming and {outgoingSegments} outgoing segments."); #endif } NotifyObservers(); }