private void ApplyRestrictionsToAllSegments(int?sortedLaneIndex = null)
        {
            NetInfo selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;
            // TODO refactor vehicle mask
            List <object[]> selectedSortedLanes = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, selectedSegmentInfo, null, VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train);

            LinkedList <ushort> nodesToProcess    = new LinkedList <ushort>();
            HashSet <ushort>    processedNodes    = new HashSet <ushort>();
            HashSet <ushort>    processedSegments = new HashSet <ushort>();

            processedSegments.Add(SelectedSegmentId);

            ushort selectedStartNodeId = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].m_startNode;
            ushort selectedEndNodeId   = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].m_endNode;

            if (selectedStartNodeId != 0)
            {
                nodesToProcess.AddFirst(selectedStartNodeId);
            }
            if (selectedEndNodeId != 0)
            {
                nodesToProcess.AddFirst(selectedEndNodeId);
            }

            while (nodesToProcess.First != null)
            {
                ushort nodeId = nodesToProcess.First.Value;
                nodesToProcess.RemoveFirst();
                processedNodes.Add(nodeId);

                if (Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].CountSegments() > 2)
                {
                    continue;                     // junction. stop.
                }
                // explore segments at node
                for (var s = 0; s < 8; s++)
                {
                    var segmentId = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].GetSegment(s);

                    if (segmentId <= 0 || processedSegments.Contains(segmentId))
                    {
                        continue;
                    }
                    processedSegments.Add(segmentId);

                    NetInfo segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info;
                    // TODO refactor vehicle mask
                    List <object[]> sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(segmentId, segmentInfo, null, VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train);

                    if (sortedLanes.Count == selectedSortedLanes.Count)
                    {
                        // number of lanes matches selected segment
                        int sli = -1;
                        for (int i = 0; i < sortedLanes.Count; ++i)
                        {
                            ++sli;

                            if (sortedLaneIndex != null && sli != sortedLaneIndex)
                            {
                                continue;
                            }

                            object[] selectedLaneData = selectedSortedLanes[i];
                            object[] laneData         = sortedLanes[i];

                            uint         selectedLaneId    = (uint)selectedLaneData[0];
                            uint         selectedLaneIndex = (uint)selectedLaneData[2];
                            NetInfo.Lane selectedLaneInfo  = segmentInfo.m_lanes[selectedLaneIndex];

                            uint         laneId    = (uint)laneData[0];
                            uint         laneIndex = (uint)laneData[2];
                            NetInfo.Lane laneInfo  = segmentInfo.m_lanes[laneIndex];

                            // apply restrictions of selected segment & lane
                            VehicleRestrictionsManager.Instance.SetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo, laneId, VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, selectedLaneIndex, selectedLaneInfo));
                        }

                        // add nodes to explore
                        ushort startNodeId = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startNode;
                        ushort endNodeId   = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endNode;

                        if (startNodeId != 0 && !processedNodes.Contains(startNodeId))
                        {
                            nodesToProcess.AddFirst(startNodeId);
                        }
                        if (endNodeId != 0 && !processedNodes.Contains(endNodeId))
                        {
                            nodesToProcess.AddFirst(endNodeId);
                        }
                    }
                }
            }
        }
        private bool drawVehicleRestrictionHandles(ushort segmentId, bool viewOnly, out bool stateUpdated)
        {
            stateUpdated = false;

            if (viewOnly && !Options.vehicleRestrictionsOverlay && TrafficManagerTool.GetToolMode() != ToolMode.VehicleRestrictions)
            {
                return(false);
            }

            Vector3 center = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_bounds.center;

            var screenPos = Camera.main.WorldToScreenPoint(center);

            screenPos.y = Screen.height - screenPos.y;
            if (screenPos.z < 0)
            {
                return(false);
            }
            var camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position;
            var diff   = center - camPos;

            if (diff.magnitude > TrafficManagerTool.PriorityCloseLod)
            {
                return(false);                // do not draw if too distant
            }
            int numDirections;
            // TODO refactor vehicle mask
            int numLanes = TrafficManagerTool.GetSegmentNumVehicleLanes(segmentId, null, out numDirections, VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train);

            // draw vehicle restrictions over each lane
            NetInfo segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info;
            Vector3 yu          = (Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endDirection - Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startDirection).normalized;

            if ((Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None)
            {
                yu = -yu;
            }
            Vector3   xu = Vector3.Cross(yu, new Vector3(0, 1f, 0)).normalized;
            float     f  = viewOnly ? 4f : 7f;        // reserved sign size in game coordinates
            ItemClass connectionClass = segmentInfo.GetConnectionClass();
            int       maxNumSigns     = 0;

            if (connectionClass.m_service == ItemClass.Service.Road)
            {
                maxNumSigns = roadVehicleTypes.Length;
            }
            else if (connectionClass.m_service == ItemClass.Service.PublicTransport && connectionClass.m_subService == ItemClass.SubService.PublicTransportTrain)
            {
                maxNumSigns = railVehicleTypes.Length;
            }
            //Vector3 zero = center - 0.5f * (float)(numLanes + numDirections - 1) * f * (xu + yu); // "bottom left"
            Vector3 zero = center - 0.5f * (float)(numLanes - 1 + numDirections - 1) * f * xu - 0.5f * (float)maxNumSigns * f * yu;             // "bottom left"

            /*if (!viewOnly)
             *      Log._Debug($"xu: {xu.ToString()} yu: {yu.ToString()} center: {center.ToString()} zero: {zero.ToString()} numLanes: {numLanes} numDirections: {numDirections}");*/

            uint x        = 0;
            var  guiColor = GUI.color;
            // TODO refactor vehicle mask
            List <object[]>             sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(segmentId, segmentInfo, null, VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train);
            bool                        hovered     = false;
            HashSet <NetInfo.Direction> directions  = new HashSet <NetInfo.Direction>();
            int sortedLaneIndex = -1;

            foreach (object[] laneData in sortedLanes)
            {
                ++sortedLaneIndex;
                uint laneId    = (uint)laneData[0];
                uint laneIndex = (uint)laneData[2];

                NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex];
                if (!directions.Contains(laneInfo.m_direction))
                {
                    if (directions.Count > 0)
                    {
                        ++x;                         // space between different directions
                    }
                    directions.Add(laneInfo.m_direction);
                }

                ExtVehicleType[] possibleVehicleTypes = null;
                if (VehicleRestrictionsManager.Instance.IsRoadLane(laneInfo))
                {
                    possibleVehicleTypes = roadVehicleTypes;
                }
                else if (VehicleRestrictionsManager.Instance.IsRailLane(laneInfo))
                {
                    possibleVehicleTypes = railVehicleTypes;
                }
                else
                {
                    ++x;
                    continue;
                }

                ExtVehicleType allowedTypes = VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo);

                uint y = 0;
#if DEBUGx
                Vector3 labelCenter = zero + f * (float)x * xu + f * (float)y * yu;                 // in game coordinates

                var labelScreenPos = Camera.main.WorldToScreenPoint(labelCenter);
                labelScreenPos.y = Screen.height - labelScreenPos.y;
                diff             = labelCenter - camPos;

                var labelZoom = 1.0f / diff.magnitude * 100f;
                _counterStyle.fontSize         = (int)(11f * labelZoom);
                _counterStyle.normal.textColor = new Color(1f, 1f, 0f);

                string  labelStr  = $"Idx {laneIndex}";
                Vector2 dim       = _counterStyle.CalcSize(new GUIContent(labelStr));
                Rect    labelRect = new Rect(labelScreenPos.x - dim.x / 2f, labelScreenPos.y, dim.x, dim.y);
                GUI.Label(labelRect, labelStr, _counterStyle);

                ++y;
#endif
                foreach (ExtVehicleType vehicleType in possibleVehicleTypes)
                {
                    bool allowed = VehicleRestrictionsManager.Instance.IsAllowed(allowedTypes, vehicleType);
                    if (allowed && viewOnly)
                    {
                        continue;                         // do not draw allowed vehicles in view-only mode
                    }
                    bool hoveredHandle;
                    DrawRestrictionsSign(viewOnly, camPos, out diff, xu, yu, f, zero, x, y, ref guiColor, TrafficLightToolTextureResources.VehicleRestrictionTextures[vehicleType][allowed], out hoveredHandle);
                    if (hoveredHandle)
                    {
                        hovered = true;
                    }

                    if (hoveredHandle && MainTool.CheckClicked())
                    {
                        // toggle vehicle restrictions
                        //Log._Debug($"Setting vehicle restrictions of segment {segmentId}, lane idx {laneIndex}, {vehicleType.ToString()} to {!allowed}");
                        VehicleRestrictionsManager.Instance.ToggleAllowedType(segmentId, segmentInfo, laneIndex, laneId, laneInfo, vehicleType, !allowed);
                        stateUpdated = true;

                        // TODO use SegmentTraverser
                        if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
                        {
                            ApplyRestrictionsToAllSegments(sortedLaneIndex);
                        }
                    }

                    ++y;
                }

                ++x;
            }

            guiColor.a = 1f;
            GUI.color  = guiColor;

            return(hovered);
        }
        private void _guiVehicleRestrictionsWindow(int num)
        {
            if (GUILayout.Button(Translation.GetString("Invert")))
            {
                // invert pattern

                NetInfo selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;
                // TODO refactor vehicle mask
                List <object[]> sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, selectedSegmentInfo, null, VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train);                // TODO does not need to be sorted, but every lane should be a vehicle lane
                foreach (object[] laneData in sortedLanes)
                {
                    uint         laneId    = (uint)laneData[0];
                    uint         laneIndex = (uint)laneData[2];
                    NetInfo.Lane laneInfo  = selectedSegmentInfo.m_lanes[laneIndex];

                    ExtVehicleType baseMask = VehicleRestrictionsManager.Instance.GetBaseMask(laneInfo);

                    if (baseMask == ExtVehicleType.None)
                    {
                        continue;
                    }

                    ExtVehicleType allowedTypes = VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo);
                    allowedTypes = ~allowedTypes & baseMask;
                    VehicleRestrictionsManager.Instance.SetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo, laneId, allowedTypes);
                }
                RefreshCurrentRestrictedSegmentIds();
            }

            GUILayout.BeginHorizontal();
            if (GUILayout.Button(Translation.GetString("Allow_all_vehicles")))
            {
                // allow all vehicle types

                NetInfo selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;
                // TODO refactor vehicle mask
                List <object[]> sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, selectedSegmentInfo, null, VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train);                // TODO does not need to be sorted, but every lane should be a vehicle lane
                foreach (object[] laneData in sortedLanes)
                {
                    uint         laneId    = (uint)laneData[0];
                    uint         laneIndex = (uint)laneData[2];
                    NetInfo.Lane laneInfo  = selectedSegmentInfo.m_lanes[laneIndex];

                    ExtVehicleType baseMask = VehicleRestrictionsManager.Instance.GetBaseMask(laneInfo);

                    if (baseMask == ExtVehicleType.None)
                    {
                        continue;
                    }

                    VehicleRestrictionsManager.Instance.SetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo, laneId, baseMask);
                }
                RefreshCurrentRestrictedSegmentIds();
            }

            if (GUILayout.Button(Translation.GetString("Ban_all_vehicles")))
            {
                // ban all vehicle types

                NetInfo         selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;
                List <object[]> sortedLanes         = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, selectedSegmentInfo, null, VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train);        // TODO does not need to be sorted, but every lane should be a vehicle lane
                foreach (object[] laneData in sortedLanes)
                {
                    uint         laneId    = (uint)laneData[0];
                    uint         laneIndex = (uint)laneData[2];
                    NetInfo.Lane laneInfo  = selectedSegmentInfo.m_lanes[laneIndex];

                    VehicleRestrictionsManager.Instance.SetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo, laneId, ExtVehicleType.None);
                }
                RefreshCurrentRestrictedSegmentIds();
            }
            GUILayout.EndHorizontal();

            if (GUILayout.Button(Translation.GetString("Apply_vehicle_restrictions_to_all_road_segments_between_two_junctions")))
            {
                ApplyRestrictionsToAllSegments();
                RefreshCurrentRestrictedSegmentIds();
            }

            DragWindow(ref windowRect);
        }
Beispiel #4
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  = SegmentGeometry.Get(SelectedSegmentId);
            bool            startNode = geometry.StartNodeId() == SelectedNodeId;

            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]);
                }
                Flags.LaneArrowChangeResult res = Flags.LaneArrowChangeResult.Invalid;
                bool buttonClicked = false;
                if (GUILayout.Button("←", ((flags & NetLane.Flags.Left) == NetLane.Flags.Left ? style1 : style2), GUILayout.Width(35), GUILayout.Height(25)))
                {
                    buttonClicked = true;
                    Flags.toggleLaneArrowFlags((uint)laneList[i][0], startNode, Flags.LaneArrows.Left, out res);
                }
                if (GUILayout.Button("↑", ((flags & NetLane.Flags.Forward) == NetLane.Flags.Forward ? style1 : style2), GUILayout.Width(25), GUILayout.Height(35)))
                {
                    buttonClicked = true;
                    Flags.toggleLaneArrowFlags((uint)laneList[i][0], startNode, Flags.LaneArrows.Forward, out res);
                }
                if (GUILayout.Button("→", ((flags & NetLane.Flags.Right) == NetLane.Flags.Right ? style1 : style2), GUILayout.Width(35), GUILayout.Height(25)))
                {
                    buttonClicked = true;
                    Flags.toggleLaneArrowFlags((uint)laneList[i][0], startNode, Flags.LaneArrows.Right, out res);
                }

                if (buttonClicked)
                {
                    switch (res)
                    {
                    case Flags.LaneArrowChangeResult.Invalid:
                    case Flags.LaneArrowChangeResult.Success:
                    default:
                        break;

                    case Flags.LaneArrowChangeResult.HighwayArrows:
                        MainTool.ShowTooltip(Translation.GetString("Lane_Arrow_Changer_Disabled_Highway"), Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId].m_position);
                        break;

                    case Flags.LaneArrowChangeResult.LaneConnection:
                        MainTool.ShowTooltip(Translation.GetString("Lane_Arrow_Changer_Disabled_Connection"), Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId].m_position);
                        break;
                    }
                }

                GUILayout.EndHorizontal();
                GUILayout.EndVertical();
                GUILayout.EndVertical();
            }

            GUILayout.EndHorizontal();
        }
        private bool drawSpeedLimitHandles(ushort segmentId, bool viewOnly, ref Vector3 camPos)
        {
            if (viewOnly && !Options.speedLimitsOverlay)
            {
                return(false);
            }

            // draw speedlimits over mean middle points of lane beziers
            if (!segmentCenterByDir.ContainsKey(segmentId))
            {
                segmentCenterByDir.Add(segmentId, new Dictionary <NetInfo.Direction, Vector3>());
                TrafficManagerTool.CalculateSegmentCenterByDir(segmentId, segmentCenterByDir[segmentId]);
            }

            bool hovered = false;

            foreach (KeyValuePair <NetInfo.Direction, Vector3> e in segmentCenterByDir[segmentId])
            {
                var screenPos = Camera.main.WorldToScreenPoint(e.Value);
                screenPos.y = Screen.height - screenPos.y;

                float zoom          = 1.0f / (e.Value - camPos).magnitude * 100f * MainTool.GetBaseZoom();
                float size          = speedLimitSignSize * zoom;
                Color guiColor      = GUI.color;
                Rect  boundingBox   = new Rect(screenPos.x - size / 2, screenPos.y - size / 2, size, size);
                bool  hoveredHandle = !viewOnly && TrafficManagerTool.IsMouseOver(boundingBox);

                if (hoveredHandle)
                {
                    // mouse hovering over sign
                    hovered    = true;
                    guiColor.a = 0.8f;
                }
                else
                {
                    guiColor.a = 0.5f;
                }

                GUI.color = guiColor;

                try {
                    GUI.DrawTexture(boundingBox, TrafficLightToolTextureResources.SpeedLimitTextures[SpeedLimitManager.Instance.GetCustomSpeedLimit(segmentId, e.Key)]);
                } catch (Exception ex) {
                    Log.Error("segment " + segmentId + " limit: " + SpeedLimitManager.Instance.GetCustomSpeedLimit(segmentId, e.Key) + ", ex: " + ex.ToString());
                }

                if (hoveredHandle && Input.GetMouseButton(0) && !IsCursorInPanel())
                {
                    // change the speed limit to the selected one
                    ushort speedLimitToSet = SpeedLimitManager.Instance.AvailableSpeedLimits[curSpeedLimitIndex];
                    //Log._Debug($"Setting speed limit of segment {segmentId}, dir {e.Key.ToString()} to {speedLimitToSet}");
                    SpeedLimitManager.Instance.SetSpeedLimit(segmentId, e.Key, speedLimitToSet);

                    // TODO use SegmentTraverser
                    if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
                    {
                        // apply new speed limit to connected segments
                        NetInfo         selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info;
                        List <object[]> selectedSortedLanes = TrafficManagerTool.GetSortedVehicleLanes(segmentId, selectedSegmentInfo, null, VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Tram | VehicleInfo.VehicleType.Metro | VehicleInfo.VehicleType.Train);                        // TODO refactor vehicle mask

                        LinkedList <ushort> nodesToProcess    = new LinkedList <ushort>();
                        HashSet <ushort>    processedNodes    = new HashSet <ushort>();
                        HashSet <ushort>    processedSegments = new HashSet <ushort>();
                        processedSegments.Add(SelectedSegmentId);

                        ushort selectedStartNodeId = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startNode;
                        ushort selectedEndNodeId   = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endNode;

                        if (selectedStartNodeId != 0)
                        {
                            nodesToProcess.AddFirst(selectedStartNodeId);
                        }
                        if (selectedEndNodeId != 0)
                        {
                            nodesToProcess.AddFirst(selectedEndNodeId);
                        }

                        while (nodesToProcess.First != null)
                        {
                            ushort nodeId = nodesToProcess.First.Value;
                            nodesToProcess.RemoveFirst();
                            processedNodes.Add(nodeId);

                            if (Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].CountSegments() > 2)
                            {
                                continue;                                 // junction. stop.
                            }
                            // explore segments at node
                            for (var s = 0; s < 8; s++)
                            {
                                var otherSegmentId = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].GetSegment(s);

                                if (otherSegmentId <= 0 || processedSegments.Contains(otherSegmentId))
                                {
                                    continue;
                                }
                                processedSegments.Add(otherSegmentId);

                                NetInfo         segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[otherSegmentId].Info;
                                List <object[]> sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(otherSegmentId, segmentInfo, null, VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Tram | VehicleInfo.VehicleType.Metro | VehicleInfo.VehicleType.Train);                                // TODO refactor vehicle mask

                                if (sortedLanes.Count == selectedSortedLanes.Count)
                                {
                                    // number of lanes matches selected segment
                                    for (int i = 0; i < sortedLanes.Count; ++i)
                                    {
                                        object[] selectedLaneData = selectedSortedLanes[i];
                                        object[] laneData         = sortedLanes[i];

                                        uint         selectedLaneId    = (uint)selectedLaneData[0];
                                        uint         selectedLaneIndex = (uint)selectedLaneData[2];
                                        NetInfo.Lane selectedLaneInfo  = segmentInfo.m_lanes[selectedLaneIndex];

                                        uint         laneId    = (uint)laneData[0];
                                        uint         laneIndex = (uint)laneData[2];
                                        NetInfo.Lane laneInfo  = segmentInfo.m_lanes[laneIndex];

                                        if (laneInfo.m_finalDirection == e.Key)
                                        {
                                            SpeedLimitManager.Instance.SetSpeedLimit(otherSegmentId, laneInfo.m_finalDirection, speedLimitToSet);
                                        }

                                        // apply restrictions of selected segment & lane
                                        //VehicleRestrictionsManager.SetAllowedVehicleTypes(otherSegmentId, segmentInfo, laneIndex, laneInfo, laneId, VehicleRestrictionsManager.GetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, selectedLaneIndex, selectedLaneInfo));
                                    }

                                    // add nodes to explore
                                    ushort startNodeId = Singleton <NetManager> .instance.m_segments.m_buffer[otherSegmentId].m_startNode;
                                    ushort endNodeId   = Singleton <NetManager> .instance.m_segments.m_buffer[otherSegmentId].m_endNode;

                                    if (startNodeId != 0 && !processedNodes.Contains(startNodeId))
                                    {
                                        nodesToProcess.AddFirst(startNodeId);
                                    }
                                    if (endNodeId != 0 && !processedNodes.Contains(endNodeId))
                                    {
                                        nodesToProcess.AddFirst(endNodeId);
                                    }
                                }
                            }
                        }
                    }
                    //mouseClickProcessed = true;
                }

                guiColor.a = 1f;
                GUI.color  = guiColor;
            }
            return(hovered);
        }
        private void _guiVehicleRestrictionsWindow(int num)
        {
            if (GUILayout.Button(Translation.GetString("Invert")))
            {
                // invert pattern

                NetInfo         selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;
                List <object[]> sortedLanes         = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, selectedSegmentInfo, null);        // TODO does not need to be sorted, but every lane should be a vehicle lane
                foreach (object[] laneData in sortedLanes)
                {
                    uint         laneId    = (uint)laneData[0];
                    uint         laneIndex = (uint)laneData[2];
                    NetInfo.Lane laneInfo  = selectedSegmentInfo.m_lanes[laneIndex];

                    ExtVehicleType baseMask = ExtVehicleType.None;
                    if (VehicleRestrictionsManager.IsRoadLane(laneInfo))
                    {
                        baseMask = ExtVehicleType.RoadVehicle;
                    }
                    else if (VehicleRestrictionsManager.IsRailLane(laneInfo))
                    {
                        baseMask = ExtVehicleType.RailVehicle;
                    }

                    if (baseMask == ExtVehicleType.None)
                    {
                        continue;
                    }

                    ExtVehicleType allowedTypes = VehicleRestrictionsManager.GetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo);
                    allowedTypes = ~allowedTypes & baseMask;
                    VehicleRestrictionsManager.SetAllowedVehicleTypes(SelectedSegmentId, laneIndex, laneId, allowedTypes);
                }
            }

            GUILayout.BeginHorizontal();
            if (GUILayout.Button(Translation.GetString("Allow_all_vehicles")))
            {
                // allow all vehicle types

                NetInfo         segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;
                List <object[]> sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, segmentInfo, null);                // TODO does not need to be sorted, but every lane should be a vehicle lane
                foreach (object[] laneData in sortedLanes)
                {
                    uint         laneId    = (uint)laneData[0];
                    uint         laneIndex = (uint)laneData[2];
                    NetInfo.Lane laneInfo  = segmentInfo.m_lanes[laneIndex];

                    ExtVehicleType baseMask = ExtVehicleType.None;
                    if (VehicleRestrictionsManager.IsRoadLane(laneInfo))
                    {
                        baseMask = ExtVehicleType.RoadVehicle;
                    }
                    else if (VehicleRestrictionsManager.IsRailLane(laneInfo))
                    {
                        baseMask = ExtVehicleType.RailVehicle;
                    }

                    if (baseMask == ExtVehicleType.None)
                    {
                        continue;
                    }

                    VehicleRestrictionsManager.SetAllowedVehicleTypes(SelectedSegmentId, laneIndex, laneId, baseMask);
                }
            }

            if (GUILayout.Button(Translation.GetString("Ban_all_vehicles")))
            {
                // ban all vehicle types

                NetInfo         segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;
                List <object[]> sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, segmentInfo, null);                // TODO does not need to be sorted, but every lane should be a vehicle lane
                foreach (object[] laneData in sortedLanes)
                {
                    uint         laneId    = (uint)laneData[0];
                    uint         laneIndex = (uint)laneData[2];
                    NetInfo.Lane laneInfo  = segmentInfo.m_lanes[laneIndex];

                    ExtVehicleType baseMask = ExtVehicleType.None;
                    if (VehicleRestrictionsManager.IsRoadLane(laneInfo))
                    {
                        baseMask = ExtVehicleType.RoadVehicle;
                    }
                    else if (VehicleRestrictionsManager.IsRailLane(laneInfo))
                    {
                        baseMask = ExtVehicleType.RailVehicle;
                    }

                    if (baseMask == ExtVehicleType.None)
                    {
                        continue;
                    }

                    VehicleRestrictionsManager.SetAllowedVehicleTypes(SelectedSegmentId, laneIndex, laneId, ~baseMask);
                }
            }
            GUILayout.EndHorizontal();

            if (GUILayout.Button(Translation.GetString("Apply_vehicle_restrictions_to_all_road_segments_between_two_junctions")))
            {
                NetInfo         selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;
                List <object[]> selectedSortedLanes = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, selectedSegmentInfo, null);

                LinkedList <ushort> nodesToProcess    = new LinkedList <ushort>();
                HashSet <ushort>    processedNodes    = new HashSet <ushort>();
                HashSet <ushort>    processedSegments = new HashSet <ushort>();
                processedSegments.Add(SelectedSegmentId);

                ushort selectedStartNodeId = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].m_startNode;
                ushort selectedEndNodeId   = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].m_endNode;

                if (selectedStartNodeId != 0)
                {
                    nodesToProcess.AddFirst(selectedStartNodeId);
                }
                if (selectedEndNodeId != 0)
                {
                    nodesToProcess.AddFirst(selectedEndNodeId);
                }

                while (nodesToProcess.First != null)
                {
                    ushort nodeId = nodesToProcess.First.Value;
                    nodesToProcess.RemoveFirst();
                    processedNodes.Add(nodeId);

                    if (Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].CountSegments() > 2)
                    {
                        continue;                         // junction. stop.
                    }
                    // explore segments at node
                    for (var s = 0; s < 8; s++)
                    {
                        var segmentId = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].GetSegment(s);

                        if (segmentId <= 0 || processedSegments.Contains(segmentId))
                        {
                            continue;
                        }
                        processedSegments.Add(segmentId);

                        NetInfo         segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info;
                        List <object[]> sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(segmentId, segmentInfo, null);

                        if (sortedLanes.Count == selectedSortedLanes.Count)
                        {
                            // number of lanes matches selected segment
                            for (int i = 0; i < sortedLanes.Count; ++i)
                            {
                                object[] selectedLaneData = selectedSortedLanes[i];
                                object[] laneData         = sortedLanes[i];

                                uint         selectedLaneId    = (uint)selectedLaneData[0];
                                uint         selectedLaneIndex = (uint)selectedLaneData[2];
                                NetInfo.Lane selectedLaneInfo  = segmentInfo.m_lanes[selectedLaneIndex];

                                uint         laneId    = (uint)laneData[0];
                                uint         laneIndex = (uint)laneData[2];
                                NetInfo.Lane laneInfo  = segmentInfo.m_lanes[laneIndex];

                                // apply restrictions of selected segment & lane
                                VehicleRestrictionsManager.SetAllowedVehicleTypes(segmentId, laneIndex, laneId, VehicleRestrictionsManager.GetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, selectedLaneIndex, selectedLaneInfo));
                            }

                            // add nodes to explore
                            ushort startNodeId = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startNode;
                            ushort endNodeId   = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endNode;

                            if (startNodeId != 0 && !processedNodes.Contains(startNodeId))
                            {
                                nodesToProcess.AddFirst(startNodeId);
                            }
                            if (endNodeId != 0 && !processedNodes.Contains(endNodeId))
                            {
                                nodesToProcess.AddFirst(endNodeId);
                            }
                        }
                    }
                }
            }
        }
Beispiel #7
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();
        }