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);
            }
        }
Exemplo n.º 3
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;
        }
Exemplo n.º 4
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());
            }
        }
        /// <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.º 8
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();
        }