Exemplo n.º 1
0
        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);
        }
Exemplo n.º 6
0
        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);
            }
        }
Exemplo n.º 7
0
        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");
        }
Exemplo n.º 9
0
        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());
            }
        }
Exemplo n.º 10
0
        /*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);
        }
Exemplo n.º 15
0
        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();
        }