public void SetLightMode(ushort segmentId,
                                 bool startNode,
                                 ExtVehicleType vehicleType,
                                 LightMode mode)
        {
            ICustomSegmentLights liveLights = GetSegmentLights(segmentId, startNode);

            if (liveLights == null)
            {
                Log.Warning(
                    $"CustomSegmentLightsManager.SetLightMode({segmentId}, {startNode}, " +
                    $"{vehicleType}, {mode}): Could not retrieve segment lights.");
                return;
            }

            ICustomSegmentLight liveLight = liveLights.GetCustomLight(vehicleType);

            if (liveLight == null)
            {
                Log.Error(
                    $"CustomSegmentLightsManager.SetLightMode: Cannot change light mode on seg. " +
                    $"{segmentId} @ {startNode} for vehicle type {vehicleType} to {mode}: Vehicle light not found");
                return;
            }

            liveLight.CurrentMode = mode;
        }
Beispiel #2
0
        /// <summary>
        /// Configures traffic light for and for all lane types at input segmentId, nodeId, and step.
        /// </summary>
        /// <param name="step"></param>
        /// <param name="nodeId"></param>
        /// <param name="segmentId"></param>
        /// <param name="m">Determines which directions are green</param>
        private static void SetupHelper(ITimedTrafficLightsStep step, ushort nodeId, ushort segmentId, GreenDir m)
        {
            bool startNode = (bool)netService.IsStartNode(segmentId, nodeId);

            //get step data for side seg
            ICustomSegmentLights liveSegmentLights = customTrafficLightsManager.GetSegmentLights(segmentId, startNode);

            //for each lane type
            foreach (ExtVehicleType vehicleType in liveSegmentLights.VehicleTypes)
            {
                //set light mode
                ICustomSegmentLight liveSegmentLight = liveSegmentLights.GetCustomLight(vehicleType);
                liveSegmentLight.CurrentMode = LightMode.All;

                TimedLight(nodeId).ChangeLightMode(
                    segmentId,
                    vehicleType,
                    liveSegmentLight.CurrentMode);

                // set light states
                var green = RoadBaseAI.TrafficLightState.Green;
                var red   = RoadBaseAI.TrafficLightState.Red;
                switch (m)
                {
                case GreenDir.AllRed:
                    liveSegmentLight.SetStates(red, red, red);
                    break;

                case GreenDir.AllGreen:
                    liveSegmentLight.SetStates(green, green, green);
                    break;

                case GreenDir.ShortOnly: {
                    // calculate directions
                    ref ExtSegmentEnd segEnd = ref segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, nodeId)];
                    ref NetNode       node   = ref Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId];
                    segEndMan.CalculateOutgoingLeftStraightRightSegments(ref segEnd, ref node, out bool bLeft, out bool bForward, out bool bRight);
                    bool bShort = RHT ? bRight : bLeft;
                    bool bLong  = RHT ? bLeft : bRight;

                    if (bShort)
                    {
                        SetStates(liveSegmentLight, red, red, green);
                    }
                    else if (bLong)
                    {
                        // go forward instead of short
                        SetStates(liveSegmentLight, green, red, red);
                    }
                    else
                    {
                        Debug.LogAssertion("Unreachable code.");
                        liveSegmentLight.SetStates(green, green, green);
                    }
                    break;
                }
        public override void OnToolGUI(Event e)
        {
            IExtSegmentManager    segMan    = Constants.ManagerFactory.ExtSegmentManager;
            IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager;
            var hoveredSegment = false;

            if (SelectedNodeId != 0)
            {
                CustomSegmentLightsManager    customTrafficLightsManager = CustomSegmentLightsManager.Instance;
                TrafficLightSimulationManager tlsMan = TrafficLightSimulationManager.Instance;
                JunctionRestrictionsManager   junctionRestrictionsManager = JunctionRestrictionsManager.Instance;

                if (!tlsMan.HasManualSimulation(SelectedNodeId))
                {
                    return;
                }

                tlsMan.TrafficLightSimulations[SelectedNodeId].Housekeeping();

                // TODO check
                // if (Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode].CountSegments() == 2) {
                //     _guiManualTrafficLightsCrosswalk(
                //         ref Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNode]);
                //     return;
                // }
                NetNode[]    nodesBuffer    = Singleton <NetManager> .instance.m_nodes.m_buffer;
                NetSegment[] segmentsBuffer = Singleton <NetManager> .instance.m_segments.m_buffer;

                for (int i = 0; i < 8; ++i)
                {
                    ushort segmentId = nodesBuffer[SelectedNodeId].GetSegment(i);
                    if (segmentId == 0)
                    {
                        continue;
                    }

                    bool startNode =
                        (bool)Constants.ServiceFactory.NetService.IsStartNode(
                            segmentId,
                            SelectedNodeId);
                    Vector3 position = CalculateNodePositionForSegment(
                        nodesBuffer[SelectedNodeId],
                        ref segmentsBuffer[segmentId]);
                    ICustomSegmentLights segmentLights =
                        customTrafficLightsManager.GetSegmentLights(segmentId, startNode, false);

                    if (segmentLights == null)
                    {
                        continue;
                    }

                    bool showPedLight = segmentLights.PedestrianLightState != null &&
                                        junctionRestrictionsManager.IsPedestrianCrossingAllowed(
                        segmentLights.SegmentId,
                        segmentLights.StartNode);
                    bool visible = MainTool.WorldToScreenPoint(position, out Vector3 screenPos);

                    if (!visible)
                    {
                        continue;
                    }

                    Vector3 diff = position - Camera.main.transform.position;
                    float   zoom = 1.0f / diff.magnitude * 100f;

                    // original / 2.5
                    float lightWidth  = 41f * zoom;
                    float lightHeight = 97f * zoom;

                    float pedestrianWidth  = 36f * zoom;
                    float pedestrianHeight = 61f * zoom;

                    // SWITCH MODE BUTTON
                    float modeWidth  = 41f * zoom;
                    float modeHeight = 38f * zoom;

                    Color guiColor = GUI.color;

                    if (showPedLight)
                    {
                        // pedestrian light

                        // SWITCH MANUAL PEDESTRIAN LIGHT BUTTON
                        hoveredSegment = RenderManualPedestrianLightSwitch(
                            zoom,
                            segmentId,
                            screenPos,
                            lightWidth,
                            segmentLights,
                            hoveredSegment);

                        // SWITCH PEDESTRIAN LIGHT
                        guiColor.a = TrafficManagerTool.GetHandleAlpha(
                            hoveredButton[0] == segmentId && hoveredButton[1] == 2 &&
                            segmentLights.ManualPedestrianMode);
                        GUI.color = guiColor;

                        var myRect3 = new Rect(
                            screenPos.x - pedestrianWidth / 2 - lightWidth + 5f * zoom,
                            screenPos.y - pedestrianHeight / 2 + 22f * zoom,
                            pedestrianWidth,
                            pedestrianHeight);

                        switch (segmentLights.PedestrianLightState)
                        {
                        case RoadBaseAI.TrafficLightState.Green: {
                            GUI.DrawTexture(
                                myRect3,
                                TrafficLightTextures.PedestrianGreenLight);
                            break;
                        }

                        // also: case RoadBaseAI.TrafficLightState.Red:
                        default: {
                            GUI.DrawTexture(
                                myRect3,
                                TrafficLightTextures.PedestrianRedLight);
                            break;
                        }
                        }

                        hoveredSegment = IsPedestrianLightHovered(
                            myRect3,
                            segmentId,
                            hoveredSegment,
                            segmentLights);
                    }

                    int lightOffset = -1;

                    foreach (ExtVehicleType vehicleType in segmentLights.VehicleTypes)
                    {
                        ++lightOffset;
                        ICustomSegmentLight segmentLight = segmentLights.GetCustomLight(vehicleType);

                        Vector3 offsetScreenPos = screenPos;
                        offsetScreenPos.y -= (lightHeight + 10f * zoom) * lightOffset;

                        SetAlpha(segmentId, -1);

                        var myRect1 = new Rect(
                            offsetScreenPos.x - modeWidth / 2,
                            offsetScreenPos.y - modeHeight / 2 + modeHeight - 7f * zoom,
                            modeWidth,
                            modeHeight);

                        GUI.DrawTexture(myRect1, TrafficLightTextures.LightMode);

                        hoveredSegment = GetHoveredSegment(
                            myRect1,
                            segmentId,
                            hoveredSegment,
                            segmentLight);

                        // COUNTER
                        hoveredSegment = RenderCounter(
                            segmentId,
                            offsetScreenPos,
                            modeWidth,
                            modeHeight,
                            zoom,
                            segmentLights,
                            hoveredSegment);

                        if (vehicleType != ExtVehicleType.None)
                        {
                            // Info sign
                            float infoWidth  = 56.125f * zoom;
                            float infoHeight = 51.375f * zoom;

                            int numInfos = 0;

                            for (int k = 0; k < TrafficManagerTool.InfoSignsToDisplay.Length; ++k)
                            {
                                if ((TrafficManagerTool.InfoSignsToDisplay[k] & vehicleType) ==
                                    ExtVehicleType.None)
                                {
                                    continue;
                                }

                                var infoRect = new Rect(
                                    offsetScreenPos.x + modeWidth / 2f +
                                    (7f * zoom * (float)(numInfos + 1)) + (infoWidth * (float)numInfos),
                                    offsetScreenPos.y - (infoHeight / 2f),
                                    infoWidth,
                                    infoHeight);
                                guiColor.a = TrafficManagerTool.GetHandleAlpha(false);

                                GUI.DrawTexture(
                                    infoRect,
                                    RoadUITextures.VehicleInfoSignTextures[TrafficManagerTool.InfoSignsToDisplay[k]]);

                                ++numInfos;
                            }
                        }

                        ExtSegment    seg    = segMan.ExtSegments[segmentId];
                        ExtSegmentEnd segEnd =
                            segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, startNode)];
                        if (seg.oneWay && segEnd.outgoing)
                        {
                            continue;
                        }

                        segEndMan.CalculateOutgoingLeftStraightRightSegments(
                            ref segEnd,
                            ref nodesBuffer[segmentId],
                            out bool hasLeftSegment,
                            out bool hasForwardSegment,
                            out bool hasRightSegment);

                        switch (segmentLight.CurrentMode)
                        {
                        case LightMode.Simple: {
                            hoveredSegment = SimpleManualSegmentLightMode(
                                segmentId,
                                offsetScreenPos,
                                lightWidth,
                                pedestrianWidth,
                                zoom,
                                lightHeight,
                                segmentLight,
                                hoveredSegment);
                            break;
                        }

                        case LightMode.SingleLeft: {
                            hoveredSegment = LeftForwardRManualSegmentLightMode(
                                hasLeftSegment,
                                segmentId,
                                offsetScreenPos,
                                lightWidth,
                                pedestrianWidth,
                                zoom,
                                lightHeight,
                                segmentLight,
                                hoveredSegment,
                                hasForwardSegment,
                                hasRightSegment);
                            break;
                        }

                        case LightMode.SingleRight: {
                            hoveredSegment = RightForwardLSegmentLightMode(
                                segmentId,
                                offsetScreenPos,
                                lightWidth,
                                pedestrianWidth,
                                zoom,
                                lightHeight,
                                hasForwardSegment,
                                hasLeftSegment,
                                segmentLight,
                                hasRightSegment,
                                hoveredSegment);
                            break;
                        }

                        default: {
                            // left arrow light
                            if (hasLeftSegment)
                            {
                                hoveredSegment = LeftArrowLightMode(
                                    segmentId,
                                    lightWidth,
                                    hasRightSegment,
                                    hasForwardSegment,
                                    offsetScreenPos,
                                    pedestrianWidth,
                                    zoom,
                                    lightHeight,
                                    segmentLight,
                                    hoveredSegment);
                            }

                            // forward arrow light
                            if (hasForwardSegment)
                            {
                                hoveredSegment = ForwardArrowLightMode(
                                    segmentId,
                                    lightWidth,
                                    hasRightSegment,
                                    offsetScreenPos,
                                    pedestrianWidth,
                                    zoom,
                                    lightHeight,
                                    segmentLight,
                                    hoveredSegment);
                            }

                            // right arrow light
                            if (hasRightSegment)
                            {
                                hoveredSegment = RightArrowLightMode(
                                    segmentId,
                                    offsetScreenPos,
                                    lightWidth,
                                    pedestrianWidth,
                                    zoom,
                                    lightHeight,
                                    segmentLight,
                                    hoveredSegment);
                            }

                            break;
                        }
                        } // end switch
                    }     // end foreach all vehicle type
                }         // end for all 8 segments
            }             // end if a node is selected

            if (hoveredSegment)
            {
                return;
            }

            hoveredButton[0] = 0;
            hoveredButton[1] = 0;
        }
        // TODO this should be optimized
        protected void GetCustomTrafficLightState(
#if DEBUG
            ushort vehicleId,
            ref Vehicle vehicleData,
#endif
            ushort nodeId,
            ushort fromSegmentId,
            byte fromLaneIndex,
            ushort toSegmentId,
            out TrafficLightState vehicleLightState,
            out TrafficLightState pedestrianLightState,
            ref TrafficLightSimulation nodeSim)
        {
            // get responsible traffic light
            // Log._Debug($"GetTrafficLightState: Getting custom light for vehicle {vehicleId} @
            //     node {nodeId}, segment {fromSegmentId}, lane {fromLaneIndex}.");
            // SegmentGeometry geometry = SegmentGeometry.Get(fromSegmentId);
            // if (geometry == null) {
            //    Log.Error($"GetTrafficLightState: No geometry information @ node {nodeId}, segment {fromSegmentId}.");
            //    vehicleLightState = TrafficLightState.Green;
            //    pedestrianLightState = TrafficLightState.Green;
            //    return;
            // }

            // determine node position at `fromSegment` (start/end)
            // bool isStartNode = geometry.StartNodeId == nodeId;
            bool?isStartNode = Services.NetService.IsStartNode(fromSegmentId, nodeId);

            if (isStartNode == null)
            {
                Log.Error($"GetTrafficLightState: Invalid node {nodeId} for segment {fromSegmentId}.");
                vehicleLightState    = TrafficLightState.Green;
                pedestrianLightState = TrafficLightState.Green;
                return;
            }

            ICustomSegmentLights lights =
                CustomSegmentLightsManager.Instance.GetSegmentLights(
                    fromSegmentId,
                    (bool)isStartNode,
                    false);

            if (lights != null)
            {
                // get traffic lights state for pedestrians
                pedestrianLightState = lights.PedestrianLightState ?? TrafficLightState.Green;
            }
            else
            {
                pedestrianLightState = TrafficLightState.Green;
                Log._Debug($"GetTrafficLightState: No pedestrian light @ node {nodeId}, " +
                           $"segment {fromSegmentId} found.");
            }

            ICustomSegmentLight light = lights == null ? null : lights.GetCustomLight(fromLaneIndex);

            if (lights == null || light == null)
            {
                // Log.Warning($"GetTrafficLightState: No custom light for vehicle {vehicleId} @ node
                //     {nodeId}, segment {fromSegmentId}, lane {fromLaneIndex} found. lights null?
                //     {lights == null} light null? {light == null}");
                vehicleLightState = TrafficLightState.Green;
                return;
            }

            // get traffic light state from responsible traffic light
            vehicleLightState = light.GetLightState(toSegmentId);
#if DEBUG
            // Log._Debug($"GetTrafficLightState: Getting light for vehicle {vehicleId} @ node {nodeId},
            //     segment {fromSegmentId}, lane {fromLaneIndex}. vehicleLightState={vehicleLightState},
            //     pedestrianLightState={pedestrianLightState}");
#endif
        }
        private static void GetCustomTrafficLightState(ushort nodeId, ushort fromSegmentId, byte fromLaneIndex, ushort toSegmentId, out RoadBaseAI.TrafficLightState vehicleLightState, out RoadBaseAI.TrafficLightState pedestrianLightState, ref TrafficLightSimulation nodeSim)
        {
            SegmentGeometry segmentGeometry = SegmentGeometry.Get(fromSegmentId, false);

            if (segmentGeometry == null)
            {
                //Log.Error(string.Format("GetTrafficLightState: No geometry information @ node {0}, segment {1}.", nodeId, fromSegmentId));
                vehicleLightState    = RoadBaseAI.TrafficLightState.Green;
                pedestrianLightState = RoadBaseAI.TrafficLightState.Green;
                return;
            }
            bool startNode = segmentGeometry.StartNodeId() == nodeId;
            ICustomSegmentLights segmentLights = CustomSegmentLightsManager.Instance.GetSegmentLights(fromSegmentId, startNode, false, RoadBaseAI.TrafficLightState.Red);

            if (segmentLights != null)
            {
                pedestrianLightState = (segmentLights.PedestrianLightState.HasValue ? segmentLights.PedestrianLightState.Value : RoadBaseAI.TrafficLightState.Green);
            }
            else
            {
                pedestrianLightState = RoadBaseAI.TrafficLightState.Green;
            }
            ICustomSegmentLight customSegmentLight = (segmentLights == null) ? null : segmentLights.GetCustomLight(fromLaneIndex);

            if (segmentLights == null || customSegmentLight == null)
            {
                vehicleLightState = RoadBaseAI.TrafficLightState.Green;
                return;
            }
            if (toSegmentId == fromSegmentId)
            {
                vehicleLightState = (Constants.ServiceFactory.SimulationService.LeftHandDrive ? customSegmentLight.LightRight : customSegmentLight.LightLeft);
                return;
            }
            if (segmentGeometry.IsLeftSegment(toSegmentId, startNode))
            {
                vehicleLightState = customSegmentLight.LightLeft;
                return;
            }
            if (segmentGeometry.IsRightSegment(toSegmentId, startNode))
            {
                vehicleLightState = customSegmentLight.LightRight;
                return;
            }
            vehicleLightState = customSegmentLight.LightMain;
        }