Пример #1
0
 internal void Housekeeping()
 {
     if (TrafficManagerTool.GetToolMode() != ToolMode.AddPrioritySigns && TrafficLightSimulationManager.Instance().GetNodeSimulation(NodeId) == null && Type == PriorityType.None)
     {
         TrafficPriorityManager.Instance().RemovePrioritySegments(NodeId);
     }
 }
        private static void SavePrioritySegment(ushort segmentId, Configuration configuration)
        {
            try {
                TrafficPriorityManager prioMan = TrafficPriorityManager.Instance();

                if (prioMan.TrafficSegments[segmentId] == null)
                {
                    return;
                }

                if (prioMan.TrafficSegments[segmentId].Node1 != 0 && prioMan.TrafficSegments[segmentId].Instance1.Type != SegmentEnd.PriorityType.None)
                {
                    Log._Debug($"Saving Priority Segment of type: {prioMan.TrafficSegments[segmentId].Instance1.Type} @ node {prioMan.TrafficSegments[segmentId].Node1}, seg. {segmentId}");
                    configuration.PrioritySegments.Add(new[]
                    {
                        prioMan.TrafficSegments[segmentId].Node1, segmentId,
                        (int)prioMan.TrafficSegments[segmentId].Instance1.Type
                    });
                }

                if (prioMan.TrafficSegments[segmentId].Node2 == 0 || prioMan.TrafficSegments[segmentId].Instance2.Type == SegmentEnd.PriorityType.None)
                {
                    return;
                }

                Log._Debug($"Saving Priority Segment of type: {prioMan.TrafficSegments[segmentId].Instance2.Type} @ node {prioMan.TrafficSegments[segmentId].Node2}, seg. {segmentId}");
                configuration.PrioritySegments.Add(new[] {
                    prioMan.TrafficSegments[segmentId].Node2, segmentId,
                    (int)prioMan.TrafficSegments[segmentId].Instance2.Type
                });
            } catch (Exception e) {
                Log.Error($"Error adding Priority Segments to Save: {e.ToString()}");
            }
        }
Пример #3
0
        private void RefreshCurrentPriorityNodeIds()
        {
            TrafficPriorityManager tpm = TrafficPriorityManager.Instance;

            currentPriorityNodeIds.Clear();
            for (uint nodeId = 0; nodeId < NetManager.MAX_NODE_COUNT; ++nodeId)
            {
                ref NetNode netNode = ref ((ushort)nodeId).ToNode();

                if (!netNode.IsValid())
                {
                    continue;
                }

                if (!tpm.MayNodeHavePrioritySigns((ushort)nodeId))
                {
                    continue;
                }

                if (!tpm.HasNodePrioritySign((ushort)nodeId) && nodeId != SelectedNodeId)
                {
                    continue;
                }

                /*if (! MainTool.IsNodeWithinViewDistance(nodeId)) {
                 *      continue;
                 * }*/

                currentPriorityNodeIds.Add((ushort)nodeId);
            }
Пример #4
0
        public static Configuration CreateConfiguration(ref bool success)
        {
            var configuration = new Configuration();

            TrafficPriorityManager prioMan = TrafficPriorityManager.Instance;

            configuration.ExtCitizens         = ExtCitizenManager.Instance.SaveData(ref success);
            configuration.ExtCitizenInstances = ExtCitizenInstanceManager.Instance.SaveData(ref success);

            configuration.PrioritySegments       = ((ICustomDataManager <List <int[]> >)TrafficPriorityManager.Instance).SaveData(ref success);
            configuration.CustomPrioritySegments = ((ICustomDataManager <List <Configuration.PrioritySegment> >)TrafficPriorityManager.Instance).SaveData(ref success);

            configuration.SegmentNodeConfs = JunctionRestrictionsManager.Instance.SaveData(ref success);

            configuration.TimedLights = TrafficLightSimulationManager.Instance.SaveData(ref success);

            //configuration.NodeTrafficLights = ((ICustomDataManager<string>)TrafficLightManager.Instance).SaveData(ref success);
            //configuration.ToggledTrafficLights = ((ICustomDataManager<List<Configuration.NodeTrafficLight>>)TrafficLightManager.Instance).SaveData(ref success);

            configuration.LaneFlags  = ((ICustomDataManager <string>)LaneArrowManager.Instance).SaveData(ref success);
            configuration.LaneArrows = ((ICustomDataManager <List <Configuration.LaneArrowData> >)LaneArrowManager.Instance).SaveData(ref success);

            configuration.LaneConnections = LaneConnectionManager.Instance.SaveData(ref success);

            configuration.LaneSpeedLimits = ((ICustomDataManager <List <Configuration.LaneSpeedLimit> >)SpeedLimitManager.Instance).SaveData(ref success);

            configuration.CustomDefaultSpeedLimits = ((ICustomDataManager <Dictionary <string, float> >)SpeedLimitManager.Instance).SaveData(ref success);

            configuration.LaneAllowedVehicleTypes = VehicleRestrictionsManager.Instance.SaveData(ref success);
            configuration.ParkingRestrictions     = ParkingRestrictionsManager.Instance.SaveData(ref success);

            return(configuration);
        }
Пример #5
0
        public override void RenderOverlay(RenderManager.CameraInfo cameraInfo)
        {
            if (MainTool.GetToolController().IsInsideUI || !Cursor.visible)
            {
                return;
            }

            // no highlight for existing priority node in sign mode
            if (TrafficPriorityManager.Instance().IsPriorityNode(HoveredNodeId))
            {
                return;
            }

            if (HoveredNodeId == 0)
            {
                return;
            }

            if (!Flags.mayHaveTrafficLight(HoveredNodeId))
            {
                return;
            }

            MainTool.DrawNodeCircle(cameraInfo, HoveredNodeId, Input.GetMouseButton(0));
        }
Пример #6
0
        private static int GetNumberOfMainRoads(ushort nodeId, ref NetNode node)
        {
            TrafficPriorityManager prioMan = TrafficPriorityManager.Instance;

            var numMainRoads = 0;

            for (var s = 0; s < 8; s++)
            {
                var segmentId2 = node.GetSegment(s);

                if (segmentId2 == 0 ||
                    !prioMan.IsPrioritySegment(nodeId, segmentId2))
                {
                    continue;
                }
                var prioritySegment2 = prioMan.GetPrioritySegment(nodeId,
                                                                  segmentId2);

                if (prioritySegment2.Type == SegmentEnd.PriorityType.Main)
                {
                    numMainRoads++;
                }
            }
            return(numMainRoads);
        }
        internal void UpdatePosition(ref Vehicle vehicleData, ref PathUnit.Position curPos, ref PathUnit.Position nextPos, bool skipCheck = false)
        {
            if (!skipCheck && !CheckValidity(ref vehicleData))
            {
                return;
            }

            LastPositionUpdate = Singleton <SimulationManager> .instance.m_currentFrameIndex;

            SegmentEnd end = TrafficPriorityManager.Instance().GetPrioritySegment(GetTransitNodeId(ref curPos, ref nextPos), curPos.m_segment);

            if (CurrentSegmentEnd != end)
            {
                if (CurrentSegmentEnd != null)
                {
                    Unlink();
                }

                WaitTime = 0;
                if (end != null)
                {
                    Link(end);
                    JunctionTransitState = VehicleJunctionTransitState.Enter;
                }
                else
                {
                    JunctionTransitState = VehicleJunctionTransitState.None;
                }
            }
        }
        private void RefreshCurrentPriorityNodeIds()
        {
            TrafficPriorityManager tpm = TrafficPriorityManager.Instance;

            currentPriorityNodeIds.Clear();
            for (uint nodeId = 0; nodeId < NetManager.MAX_NODE_COUNT; ++nodeId)
            {
                if (!Constants.ServiceFactory.NetService.IsNodeValid((ushort)nodeId))
                {
                    continue;
                }

                if (!tpm.MayNodeHavePrioritySigns((ushort)nodeId))
                {
                    continue;
                }

                if (!tpm.HasNodePrioritySign((ushort)nodeId) && nodeId != SelectedNodeId)
                {
                    continue;
                }

                /*if (! MainTool.IsNodeWithinViewDistance(nodeId)) {
                 *      continue;
                 * }*/

                currentPriorityNodeIds.Add((ushort)nodeId);
            }
            //Log._Debug($"PrioritySignsTool.RefreshCurrentPriorityNodeIds: currentPriorityNodeIds={string.Join(", ", currentPriorityNodeIds.Select(x => x.ToString()).ToArray())}");
        }
 private void DestroySegmentEnd(ushort segmentId)
 {
     if (segmentId <= 0)
     {
         return;
     }
     TrafficPriorityManager.Instance().RemovePrioritySegment(NodeId, segmentId);
 }
Пример #10
0
        internal static bool mayHaveLaneArrows(uint laneId, bool?startNode = null)
        {
            if (laneId <= 0)
            {
                return(false);
            }
            NetManager netManager = Singleton <NetManager> .instance;

            if (((NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[laneId].m_flags & (NetLane.Flags.Created | NetLane.Flags.Deleted)) != NetLane.Flags.Created)
            {
                return(false);
            }

            ushort segmentId = netManager.m_lanes.m_buffer[laneId].m_segment;

            var dir  = NetInfo.Direction.Forward;
            var dir2 = ((netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? dir : NetInfo.InvertDirection(dir);
            var dir3 = TrafficPriorityManager.IsLeftHandDrive() ? NetInfo.InvertDirection(dir2) : dir2;

            NetInfo segmentInfo = netManager.m_segments.m_buffer[segmentId].Info;
            uint    curLaneId   = netManager.m_segments.m_buffer[segmentId].m_lanes;
            int     numLanes    = segmentInfo.m_lanes.Length;
            int     laneIndex   = 0;
            int     wIter       = 0;

            while (laneIndex < numLanes && curLaneId != 0u)
            {
                ++wIter;
                if (wIter >= 20)
                {
                    Log.Error("Too many iterations in Flags.mayHaveLaneArrows!");
                    break;
                }

                if (curLaneId == laneId)
                {
                    NetInfo.Lane laneInfo    = segmentInfo.m_lanes[laneIndex];
                    bool         isStartNode = laneInfo.m_direction != dir3;
                    if (startNode != null && isStartNode != startNode)
                    {
                        return(false);
                    }
                    ushort nodeId = isStartNode ? netManager.m_segments.m_buffer[segmentId].m_startNode : netManager.m_segments.m_buffer[segmentId].m_endNode;

                    if ((netManager.m_nodes.m_buffer[nodeId].m_flags & (NetNode.Flags.Created | NetNode.Flags.Deleted)) != NetNode.Flags.Created)
                    {
                        return(false);
                    }
                    return((netManager.m_nodes.m_buffer[nodeId].m_flags & NetNode.Flags.Junction) != NetNode.Flags.None);
                }
                curLaneId = netManager.m_lanes.m_buffer[curLaneId].m_nextLane;
                ++laneIndex;
            }
            return(false);
        }
        private void SetupSegmentEnd(ushort segmentId)
        {
            if (segmentId <= 0)
            {
                return;
            }

            TrafficPriorityManager prioMan = TrafficPriorityManager.Instance;

            //if (!prioMan.IsPrioritySegment(NodeId, segmentId))
            prioMan.AddPrioritySegment(NodeId, segmentId, SegmentEnd.PriorityType.None);
        }
Пример #12
0
        public override void Cleanup()
        {
            TrafficPriorityManager prioMan = TrafficPriorityManager.Instance();

            foreach (TrafficSegment trafficSegment in prioMan.TrafficSegments)
            {
                try {
                    trafficSegment?.Instance1?.Housekeeping();
                    trafficSegment?.Instance2?.Housekeeping();
                } catch (Exception e) {
                    Log.Error($"Error occured while performing PrioritySignsTool.Cleanup: {e.ToString()}");
                }
            }
        }
Пример #13
0
        public static void resetTrafficLights(bool all)
        {
            TrafficPriorityManager prioMan = TrafficPriorityManager.Instance();

            for (ushort i = 0; i < Singleton <NetManager> .instance.m_nodes.m_size; ++i)
            {
                nodeTrafficLightFlag[i] = null;
                if (!all && prioMan.IsPriorityNode(i))
                {
                    continue;
                }
                Singleton <NetManager> .instance.UpdateNodeFlags(i);
            }
        }
Пример #14
0
        public override void OnPrimaryClickOverlay()
        {
            if (IsCursorInPanel())
            {
                return;
            }

            if (SelectedNodeId != 0)
            {
                return;
            }

            TrafficLightSimulationManager tlsMan  = TrafficLightSimulationManager.Instance;
            TrafficPriorityManager        prioMan = TrafficPriorityManager.Instance;

            if (!tlsMan.TrafficLightSimulations[HoveredNodeId].IsTimedLight())
            {
                if ((Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags &
                     NetNode.Flags.TrafficLights) == NetNode.Flags.None)
                {
                    prioMan.RemovePrioritySignsFromNode(HoveredNodeId);
                    TrafficLightManager.Instance.AddTrafficLight(
                        HoveredNodeId,
                        ref Singleton <NetManager> .instance.m_nodes.m_buffer[
                            HoveredNodeId]);
                }

                if (tlsMan.SetUpManualTrafficLight(HoveredNodeId))
                {
                    SelectedNodeId = HoveredNodeId;
                }

                // for (var s = 0; s < 8; s++) {
                //        var segment = Singleton<NetManager>
                //                      .instance.m_nodes.m_buffer[SelectedNodeId].GetSegment(s);
                //        if (segment != 0 &&
                //            !TrafficPriority.IsPrioritySegment(SelectedNodeId, segment)) {
                //            TrafficPriority.AddPrioritySegment(
                //                SelectedNodeId,
                //                segment,
                //                SegmentEnd.PriorityType.None);
                //        }
                //    }
            }
            else
            {
                MainTool.ShowError(
                    Translation.TrafficLights.Get("Dialog.Text:Node has timed TL script"));
            }
        }
        public override void OnPrimaryClickOverlay()
        {
            if (IsCursorInPanel())
            {
                return;
            }

            if (SelectedNodeId != 0)
            {
                return;
            }

            TrafficLightSimulationManager tlsMan  = TrafficLightSimulationManager.Instance;
            TrafficPriorityManager        prioMan = TrafficPriorityManager.Instance;
            ref NetNode hoveredNetNode            = ref HoveredNodeId.ToNode();
        /// <summary>
        /// Determines the allowed vehicle types that may approach the given node from the given segment (lane-wise).
        /// </summary>
        /// <param name="segmentId"></param>
        /// <param name="nodeId"></param>
        /// <returns></returns>
        internal Dictionary <byte, ExtVehicleType> GetAllowedVehicleTypesAsDict(ushort segmentId, ushort nodeId)
        {
#if TRACE
            Singleton <CodeProfiler> .instance.Start("VehicleRestrictionsManager.GetAllowedVehicleTypesAsDict");
#endif
            Dictionary <byte, ExtVehicleType> ret = new Dictionary <byte, ExtVehicleType>();

            NetManager netManager = Singleton <NetManager> .instance;
            if (segmentId == 0 || (netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Created) == NetSegment.Flags.None ||
                nodeId == 0 || (netManager.m_nodes.m_buffer[nodeId].m_flags & NetNode.Flags.Created) == NetNode.Flags.None)
            {
#if TRACE
                Singleton <CodeProfiler> .instance.Stop("VehicleRestrictionsManager.GetAllowedVehicleTypesAsDict");
#endif
                return(ret);
            }

            var dir  = NetInfo.Direction.Forward;
            var dir2 = ((netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? dir : NetInfo.InvertDirection(dir);
            var dir3 = TrafficPriorityManager.IsLeftHandDrive() ? NetInfo.InvertDirection(dir2) : dir2;

            NetInfo segmentInfo = netManager.m_segments.m_buffer[segmentId].Info;
            uint    curLaneId   = netManager.m_segments.m_buffer[segmentId].m_lanes;
            int     numLanes    = segmentInfo.m_lanes.Length;
            uint    laneIndex   = 0;
            while (laneIndex < numLanes && curLaneId != 0u)
            {
                NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex];
                ushort       toNodeId = (laneInfo.m_direction == dir3) ? netManager.m_segments.m_buffer[segmentId].m_endNode : netManager.m_segments.m_buffer[segmentId].m_startNode;

                if (toNodeId == nodeId)
                {
                    ExtVehicleType vehicleTypes = GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo);
                    if (vehicleTypes != ExtVehicleType.None)
                    {
                        ret[(byte)laneIndex] = vehicleTypes;
                    }
                }
                curLaneId = netManager.m_lanes.m_buffer[curLaneId].m_nextLane;
                ++laneIndex;
            }

#if TRACE
            Singleton <CodeProfiler> .instance.Stop("VehicleRestrictionsManager.GetAllowedVehicleTypesAsDict");
#endif
            return(ret);
        }
Пример #17
0
        private void RefreshCurrentPrioritySegmentIds()
        {
            currentPrioritySegmentIds.Clear();
            for (ushort segmentId = 0; segmentId < NetManager.MAX_SEGMENT_COUNT; ++segmentId)
            {
                if ((Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Created) == NetSegment.Flags.None)
                {
                    continue;
                }

                var trafficSegment = TrafficPriorityManager.Instance().TrafficSegments[segmentId];
                if (trafficSegment == null)
                {
                    continue;
                }

                currentPrioritySegmentIds.Add(segmentId);
            }
        }
Пример #18
0
        internal static int GetSegmentNumVehicleLanes(ushort segmentId, ushort?nodeId, out int numDirections)
        {
            var info      = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info;
            var num2      = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_lanes;
            var laneIndex = 0;

            NetInfo.Direction?dir  = null;
            NetInfo.Direction?dir2 = null;
            NetInfo.Direction?dir3 = null;

            numDirections = 0;
            HashSet <NetInfo.Direction> directions = new HashSet <NetInfo.Direction>();

            if (nodeId != null)
            {
                dir  = (Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startNode == nodeId) ? NetInfo.Direction.Backward : NetInfo.Direction.Forward;
                dir2 = ((Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? dir : NetInfo.InvertDirection((NetInfo.Direction)dir);
                dir3 = TrafficPriorityManager.IsLeftHandDrive() ? NetInfo.InvertDirection((NetInfo.Direction)dir2) : dir2;
            }

            var numLanes = 0;

            while (laneIndex < info.m_lanes.Length && num2 != 0u)
            {
                if (((info.m_lanes[laneIndex].m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != NetInfo.LaneType.None &&
                     (info.m_lanes[laneIndex].m_vehicleType & (VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train)) != VehicleInfo.VehicleType.None) &&
                    (dir3 == null || info.m_lanes[laneIndex].m_direction == dir3))
                {
                    if (!directions.Contains(info.m_lanes[laneIndex].m_direction))
                    {
                        directions.Add(info.m_lanes[laneIndex].m_direction);
                        ++numDirections;
                    }
                    numLanes++;
                }

                num2 = Singleton <NetManager> .instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_nextLane;
                laneIndex++;
            }

            return(numLanes);
        }
Пример #19
0
        public void OnUpdate(SegmentGeometry geometry)
        {
            if (!geometry.IsValid())
            {
                TrafficPriorityManager.Instance().RemovePrioritySegment(NodeId, SegmentId);
                return;
            }

            StartNode = Singleton <NetManager> .instance.m_segments.m_buffer[SegmentId].m_startNode == NodeId;
            numLanes  = Singleton <NetManager> .instance.m_segments.m_buffer[SegmentId].Info.m_lanes.Length;
            numVehiclesFlowingToSegmentId = new Dictionary <ushort, uint>(7);
            numVehiclesGoingToSegmentId   = new Dictionary <ushort, uint>(7);
            //frontVehicleIds = new ushort[numLanes];
            ushort[] outgoingSegmentIds = geometry.GetOutgoingSegments(StartNode);
            foreach (ushort otherSegmentId in outgoingSegmentIds)
            {
                numVehiclesFlowingToSegmentId[otherSegmentId] = 0;
                numVehiclesGoingToSegmentId[otherSegmentId]   = 0;
            }
        }
Пример #20
0
        public override void OnPrimaryClickOverlay()
        {
            if (IsCursorInPanel())
            {
                return;
            }
            if (SelectedNodeId != 0)
            {
                return;
            }

            TrafficLightSimulationManager tlsMan  = TrafficLightSimulationManager.Instance;
            TrafficPriorityManager        prioMan = TrafficPriorityManager.Instance;

            TrafficLightSimulation sim = tlsMan.GetNodeSimulation(HoveredNodeId);

            if (sim == null || !sim.IsTimedLight())
            {
                if ((Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None)
                {
                    prioMan.RemovePrioritySegments(HoveredNodeId);
                    TrafficLightManager.Instance.AddTrafficLight(HoveredNodeId);
                }

                SelectedNodeId = HoveredNodeId;

                sim = tlsMan.AddNodeToSimulation(SelectedNodeId);
                sim.SetupManualTrafficLight();

                /*for (var s = 0; s < 8; s++) {
                 *      var segment = Singleton<NetManager>.instance.m_nodes.m_buffer[SelectedNodeId].GetSegment(s);
                 *      if (segment != 0 && !TrafficPriority.IsPrioritySegment(SelectedNodeId, segment)) {
                 *              TrafficPriority.AddPrioritySegment(SelectedNodeId, segment, SegmentEnd.PriorityType.None);
                 *      }
                 * }*/
            }
            else
            {
                MainTool.ShowTooltip(Translation.GetString("NODE_IS_TIMED_LIGHT"), Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_position);
            }
        }
Пример #21
0
        public override void OnPrimaryClickOverlay()
        {
            if (IsCursorInPanel())
            {
                return;
            }

            if (SelectedNodeId != 0)
            {
                return;
            }

            TrafficLightSimulationManager tlsMan  = TrafficLightSimulationManager.Instance;
            TrafficPriorityManager        prioMan = TrafficPriorityManager.Instance;

            if (!tlsMan.TrafficLightSimulations[HoveredNodeId].IsTimedLight())
            {
                if ((Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags &
                     NetNode.Flags.TrafficLights) == NetNode.Flags.None)
                {
                    prioMan.RemovePrioritySignsFromNode(HoveredNodeId);
                    TrafficLightManager.Instance.AddTrafficLight(
                        HoveredNodeId,
                        ref Singleton <NetManager> .instance.m_nodes.m_buffer[
                            HoveredNodeId]);
                }

                if (tlsMan.SetUpManualTrafficLight(HoveredNodeId))
                {
                    SelectedNodeId = HoveredNodeId;
                    MainTool.RequestOnscreenDisplayUpdate();
                }
            }
            else
            {
                MainTool.WarningPrompt(Translation.TrafficLights.Get("Dialog.Text:Node has timed TL script"));
            }
        }
        public override void OnPrimaryClickOverlay()
        {
            if (HoveredNodeId == 0)
            {
                return;
            }

            if ((Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags & NetNode.Flags.Junction) == NetNode.Flags.None)
            {
                return;
            }

            TrafficLightSimulation sim = TrafficLightSimulationManager.Instance().GetNodeSimulation(HoveredNodeId);

            if (sim != null && sim.IsTimedLight())
            {
                MainTool.ShowTooltip(Translation.GetString("NODE_IS_TIMED_LIGHT"), Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_position);
                return;
            }

            TrafficPriorityManager.Instance().RemovePrioritySegments(HoveredNodeId);
            Flags.setNodeTrafficLight(HoveredNodeId, (Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None);
        }
        public override void OnSaveData()
        {
            bool success = true;

            /*try {
             *      Log.Info("Recalculating segment geometries");
             *      SegmentGeometry.OnBeforeSaveData();
             * } catch (Exception e) {
             *      Log.Error($"OnSaveData: Exception occurred while calling SegmentGeometry.OnBeforeSaveData: {e.ToString()}");
             *      error = true;
             * }*/

            foreach (ICustomManager manager in LoadingExtension.RegisteredManagers)
            {
                try {
                    Log.Info($"OnBeforeSaveData: {manager.GetType().Name}");
                    manager.OnBeforeSaveData();
                } catch (Exception e) {
                    Log.Error($"OnSaveData: Error while notifying {manager.GetType().Name}.OnBeforeSaveData: {e.ToString()}");
                    success = false;
                }
            }

            try {
                Log.Info("Saving Mod Data.");
                var configuration = new Configuration();

                TrafficPriorityManager prioMan = TrafficPriorityManager.Instance;

                configuration.ExtCitizens         = ExtCitizenManager.Instance.SaveData(ref success);
                configuration.ExtCitizenInstances = ExtCitizenInstanceManager.Instance.SaveData(ref success);

                configuration.PrioritySegments       = ((ICustomDataManager <List <int[]> >)TrafficPriorityManager.Instance).SaveData(ref success);
                configuration.CustomPrioritySegments = ((ICustomDataManager <List <Configuration.PrioritySegment> >)TrafficPriorityManager.Instance).SaveData(ref success);

                configuration.SegmentNodeConfs = JunctionRestrictionsManager.Instance.SaveData(ref success);

                configuration.TimedLights = TrafficLightSimulationManager.Instance.SaveData(ref success);

                //configuration.NodeTrafficLights = ((ICustomDataManager<string>)TrafficLightManager.Instance).SaveData(ref success);
                //configuration.ToggledTrafficLights = ((ICustomDataManager<List<Configuration.NodeTrafficLight>>)TrafficLightManager.Instance).SaveData(ref success);

                configuration.LaneFlags  = ((ICustomDataManager <string>)LaneArrowManager.Instance).SaveData(ref success);
                configuration.LaneArrows = ((ICustomDataManager <List <Configuration.LaneArrowData> >)LaneArrowManager.Instance).SaveData(ref success);

                configuration.LaneConnections = LaneConnectionManager.Instance.SaveData(ref success);

                configuration.LaneSpeedLimits = ((ICustomDataManager <List <Configuration.LaneSpeedLimit> >)SpeedLimitManager.Instance).SaveData(ref success);

                configuration.CustomDefaultSpeedLimits = ((ICustomDataManager <Dictionary <string, float> >)SpeedLimitManager.Instance).SaveData(ref success);

                configuration.LaneAllowedVehicleTypes = VehicleRestrictionsManager.Instance.SaveData(ref success);
                configuration.ParkingRestrictions     = ParkingRestrictionsManager.Instance.SaveData(ref success);

                try {
                    // save options
                    _serializableData.SaveData("TMPE_Options", OptionsManager.Instance.SaveData(ref success));
                } catch (Exception ex) {
                    Log.Error("Unexpected error while saving options: " + ex.Message);
                    success = false;
                }

                var binaryFormatter = new BinaryFormatter();
                var memoryStream    = new MemoryStream();

                try {
                    binaryFormatter.Serialize(memoryStream, configuration);
                    memoryStream.Position = 0;
                    Log.Info($"Save data byte length {memoryStream.Length}");
                    _serializableData.SaveData(DataId, memoryStream.ToArray());
                } catch (Exception ex) {
                    Log.Error("Unexpected error while saving data: " + ex.ToString());
                    success = false;
                } finally {
                    memoryStream.Close();
                }

                foreach (ICustomManager manager in LoadingExtension.RegisteredManagers)
                {
                    try {
                        Log.Info($"OnAfterSaveData: {manager.GetType().Name}");
                        manager.OnAfterSaveData();
                    } catch (Exception e) {
                        Log.Error($"OnSaveData: Error while notifying {manager.GetType().Name}.OnAfterSaveData: {e.ToString()}");
                        success = false;
                    }
                }
            } catch (Exception e) {
                success = false;
                Log.Error($"Error occurred while saving data: {e.ToString()}");
                //UIView.library.ShowModal<ExceptionPanel>("ExceptionPanel").SetMessage("An error occurred while saving", "Traffic Manager: President Edition detected an error while saving. To help preventing future errors, please navigate to http://steamcommunity.com/sharedfiles/filedetails/?id=583429740 and follow the steps under 'In case problems arise'.", true);
            }
        }
        private static void LoadDataState(out bool error)
        {
            error = false;

            Log.Info("Loading State from Config");
            if (_configuration == null)
            {
                Log.Warning("Configuration NULL, Couldn't load save data. Possibly a new game?");
                return;
            }

            TrafficPriorityManager prioMan = TrafficPriorityManager.Instance;

            // load ext. citizens
            if (_configuration.ExtCitizens != null)
            {
                if (!ExtCitizenManager.Instance.LoadData(_configuration.ExtCitizens))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Ext. citizen data structure undefined!");
            }

            // load ext. citizen instances
            if (_configuration.ExtCitizenInstances != null)
            {
                if (!ExtCitizenInstanceManager.Instance.LoadData(_configuration.ExtCitizenInstances))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Ext. citizen instance data structure undefined!");
            }

            // load priority segments
            if (_configuration.PrioritySegments != null)
            {
                if (!TrafficPriorityManager.Instance.LoadData(_configuration.PrioritySegments))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Priority segments data structure (old) undefined!");
            }

            if (_configuration.CustomPrioritySegments != null)
            {
                if (!TrafficPriorityManager.Instance.LoadData(_configuration.CustomPrioritySegments))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Priority segments data structure (new) undefined!");
            }

            // load parking restrictions
            if (_configuration.ParkingRestrictions != null)
            {
                if (!ParkingRestrictionsManager.Instance.LoadData(_configuration.ParkingRestrictions))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Parking restrctions structure undefined!");
            }

            // load vehicle restrictions (warning: has to be done before loading timed lights!)
            if (_configuration.LaneAllowedVehicleTypes != null)
            {
                if (!VehicleRestrictionsManager.Instance.LoadData(_configuration.LaneAllowedVehicleTypes))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Vehicle restrctions structure undefined!");
            }

            NetManager netManager = Singleton <NetManager> .instance;

            if (_configuration.TimedLights != null)
            {
                if (!TrafficLightSimulationManager.Instance.LoadData(_configuration.TimedLights))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Timed traffic lights data structure undefined!");
            }

            // load toggled traffic lights (old method)
            if (_configuration.NodeTrafficLights != null)
            {
                if (!TrafficLightManager.Instance.LoadData(_configuration.NodeTrafficLights))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Junction traffic lights data structure (old) undefined!");
            }

            // load toggled traffic lights (new method)
            if (_configuration.ToggledTrafficLights != null)
            {
                if (!TrafficLightManager.Instance.LoadData(_configuration.ToggledTrafficLights))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Junction traffic lights data structure (new) undefined!");
            }

            // load lane arrrows (old method)
            if (_configuration.LaneFlags != null)
            {
                if (!LaneArrowManager.Instance.LoadData(_configuration.LaneFlags))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Lane arrow data structure (old) undefined!");
            }

            // load lane arrows (new method)
            if (_configuration.LaneArrows != null)
            {
                if (!LaneArrowManager.Instance.LoadData(_configuration.LaneArrows))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Lane arrow data structure (new) undefined!");
            }

            // load lane connections
            if (_configuration.LaneConnections != null)
            {
                if (!LaneConnectionManager.Instance.LoadData(_configuration.LaneConnections))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Lane connection data structure undefined!");
            }

            // Load custom default speed limits
            if (_configuration.CustomDefaultSpeedLimits != null)
            {
                if (!SpeedLimitManager.Instance.LoadData(_configuration.CustomDefaultSpeedLimits))
                {
                    error = true;
                }
            }

            // load speed limits
            if (_configuration.LaneSpeedLimits != null)
            {
                if (!SpeedLimitManager.Instance.LoadData(_configuration.LaneSpeedLimits))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Lane speed limit structure undefined!");
            }

            // Load segment-at-node flags
            if (_configuration.SegmentNodeConfs != null)
            {
                if (!JunctionRestrictionsManager.Instance.LoadData(_configuration.SegmentNodeConfs))
                {
                    error = true;
                }
            }
            else
            {
                Log.Info("Segment-at-node structure undefined!");
            }
        }
Пример #25
0
        public void ShowGUI(bool viewOnly)
        {
            try {
                TrafficLightSimulationManager tlsMan  = TrafficLightSimulationManager.Instance;
                TrafficPriorityManager        prioMan = TrafficPriorityManager.Instance;
                TrafficLightManager           tlm     = TrafficLightManager.Instance;

                bool clicked = !viewOnly?MainTool.CheckClicked() : false;

                var hoveredSegment = false;
                //Log.Message("_guiPrioritySigns called. num of prio segments: " + TrafficPriority.PrioritySegments.Count);

                HashSet <ushort> nodeIdsWithSigns = new HashSet <ushort>();
                foreach (ushort segmentId in currentPrioritySegmentIds)
                {
                    var trafficSegment = prioMan.TrafficSegments[segmentId];
                    if (trafficSegment == null)
                    {
                        continue;
                    }
                    SegmentGeometry geometry = SegmentGeometry.Get(segmentId);

                    prioritySegments[0] = null;
                    prioritySegments[1] = null;

                    if (tlsMan.GetNodeSimulation(trafficSegment.Node1) == null)
                    {
                        SegmentEnd tmpSeg1   = prioMan.GetPrioritySegment(trafficSegment.Node1, segmentId);
                        bool       startNode = geometry.StartNodeId() == trafficSegment.Node1;
                        if (tmpSeg1 != null && !geometry.IsOutgoingOneWay(startNode))
                        {
                            prioritySegments[0] = tmpSeg1;
                            nodeIdsWithSigns.Add(trafficSegment.Node1);
                            prioMan.AddPriorityNode(trafficSegment.Node1);
                        }
                    }
                    if (tlsMan.GetNodeSimulation(trafficSegment.Node2) == null)
                    {
                        SegmentEnd tmpSeg2   = prioMan.GetPrioritySegment(trafficSegment.Node2, segmentId);
                        bool       startNode = geometry.StartNodeId() == trafficSegment.Node2;
                        if (tmpSeg2 != null && !geometry.IsOutgoingOneWay(startNode))
                        {
                            prioritySegments[1] = tmpSeg2;
                            nodeIdsWithSigns.Add(trafficSegment.Node2);
                            prioMan.AddPriorityNode(trafficSegment.Node2);
                        }
                    }

                    //Log.Message("init ok");

                    foreach (var prioritySegment in prioritySegments)
                    {
                        if (prioritySegment == null)
                        {
                            continue;
                        }

                        var nodeId = prioritySegment.NodeId;
                        //Log.Message("_guiPrioritySigns: nodeId=" + nodeId);

                        var nodePositionVector3 = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].m_position;
                        var camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position;
                        var diff   = nodePositionVector3 - camPos;
                        if (diff.magnitude > TrafficManagerTool.PriorityCloseLod)
                        {
                            continue;                             // do not draw if too distant
                        }
                        if (Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startNode == (ushort)nodeId)
                        {
                            nodePositionVector3.x += Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startDirection.x * 10f;
                            nodePositionVector3.y += Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startDirection.y * 10f;
                            nodePositionVector3.z += Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startDirection.z * 10f;
                        }
                        else
                        {
                            nodePositionVector3.x += Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endDirection.x * 10f;
                            nodePositionVector3.y += Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endDirection.y * 10f;
                            nodePositionVector3.z += Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endDirection.z * 10f;
                        }

                        var nodeScreenPosition = Camera.main.WorldToScreenPoint(nodePositionVector3);
                        nodeScreenPosition.y = Screen.height - nodeScreenPosition.y;
                        if (nodeScreenPosition.z < 0)
                        {
                            continue;
                        }
                        var zoom            = 1.0f / diff.magnitude * 100f * MainTool.GetBaseZoom();
                        var size            = 110f * zoom;
                        var guiColor        = GUI.color;
                        var nodeBoundingBox = new Rect(nodeScreenPosition.x - size / 2, nodeScreenPosition.y - size / 2, size, size);
                        hoveredSegment = !viewOnly && TrafficManagerTool.IsMouseOver(nodeBoundingBox);

                        if (hoveredSegment)
                        {
                            // mouse hovering over sign
                            guiColor.a = 0.8f;
                        }
                        else
                        {
                            guiColor.a = 0.5f;
                            size       = 90f * zoom;
                        }
                        var nodeDrawingBox = new Rect(nodeScreenPosition.x - size / 2, nodeScreenPosition.y - size / 2, size, size);

                        GUI.color = guiColor;

                        bool setUndefinedSignsToMainRoad = false;
                        switch (prioritySegment.Type)
                        {
                        case SegmentEnd.PriorityType.Main:
                            GUI.DrawTexture(nodeDrawingBox, TrafficLightToolTextureResources.SignPriorityTexture2D);
                            if (clicked && hoveredSegment)
                            {
                                //Log._Debug("Click on node " + nodeId + ", segment " + segmentId + " to change prio type (1)");
                                //Log.Message("PrioritySegment.Type = Yield");
                                prioritySegment.Type        = SegmentEnd.PriorityType.Yield;
                                setUndefinedSignsToMainRoad = true;
                                clicked = false;
                            }
                            break;

                        case SegmentEnd.PriorityType.Yield:
                            GUI.DrawTexture(nodeDrawingBox, TrafficLightToolTextureResources.SignYieldTexture2D);
                            if (clicked && hoveredSegment)
                            {
                                //Log._Debug("Click on node " + nodeId + ", segment " + segmentId + " to change prio type (2)");
                                prioritySegment.Type        = SegmentEnd.PriorityType.Stop;
                                setUndefinedSignsToMainRoad = true;
                                clicked = false;
                            }

                            break;

                        case SegmentEnd.PriorityType.Stop:
                            GUI.DrawTexture(nodeDrawingBox, TrafficLightToolTextureResources.SignStopTexture2D);
                            if (clicked && hoveredSegment)
                            {
                                //Log._Debug("Click on node " + nodeId + ", segment " + segmentId + " to change prio type (3)");
                                prioritySegment.Type = SegmentEnd.PriorityType.Main;
                                clicked = false;
                            }
                            break;

                        case SegmentEnd.PriorityType.None:
                            if (viewOnly)
                            {
                                break;
                            }
                            GUI.DrawTexture(nodeDrawingBox, TrafficLightToolTextureResources.SignNoneTexture2D);

                            if (clicked && hoveredSegment)
                            {
                                //Log._Debug("Click on node " + nodeId + ", segment " + segmentId + " to change prio type (4)");
                                //Log.Message("PrioritySegment.Type = None");
                                prioritySegment.Type = GetNumberOfMainRoads(nodeId, ref Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId]) >= 2
                                                                                ? SegmentEnd.PriorityType.Yield
                                                                                : SegmentEnd.PriorityType.Main;
                                if (prioritySegment.Type == SegmentEnd.PriorityType.Yield)
                                {
                                    setUndefinedSignsToMainRoad = true;
                                }
                                clicked = false;
                            }
                            break;
                        }

                        if (setUndefinedSignsToMainRoad)
                        {
                            foreach (var otherPrioritySegment in prioMan.GetPrioritySegments(nodeId))
                            {
                                if (otherPrioritySegment.SegmentId == prioritySegment.SegmentId)
                                {
                                    continue;
                                }
                                if (otherPrioritySegment.Type == SegmentEnd.PriorityType.None)
                                {
                                    otherPrioritySegment.Type = SegmentEnd.PriorityType.Main;
                                }
                            }
                        }
                    }
                }

                if (viewOnly)
                {
                    return;
                }

                ushort hoveredExistingNodeId = 0;
                foreach (ushort nodeId in nodeIdsWithSigns)
                {
                    var nodePositionVector3 = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].m_position;
                    var camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position;
                    var diff   = nodePositionVector3 - camPos;
                    if (diff.magnitude > TrafficManagerTool.PriorityCloseLod)
                    {
                        continue;
                    }

                    // draw deletion button
                    var nodeScreenPosition = Camera.main.WorldToScreenPoint(nodePositionVector3);
                    nodeScreenPosition.y = Screen.height - nodeScreenPosition.y;
                    if (nodeScreenPosition.z < 0)
                    {
                        continue;
                    }
                    var zoom            = 1.0f / diff.magnitude * 100f * MainTool.GetBaseZoom();
                    var size            = 90f * zoom;
                    var nodeBoundingBox = new Rect(nodeScreenPosition.x - size / 2, nodeScreenPosition.y - size / 2, size, size);

                    var guiColor          = GUI.color;
                    var nodeCenterHovered = TrafficManagerTool.IsMouseOver(nodeBoundingBox);
                    if (nodeCenterHovered)
                    {
                        hoveredExistingNodeId = nodeId;
                        guiColor.a            = 0.8f;
                    }
                    else
                    {
                        guiColor.a = 0.5f;
                    }
                    GUI.color = guiColor;

                    GUI.DrawTexture(nodeBoundingBox, TrafficLightToolTextureResources.SignRemoveTexture2D);
                }

                // add a new or delete a priority segment node
                if (HoveredNodeId != 0 || hoveredExistingNodeId != 0)
                {
                    bool delete = false;
                    if (hoveredExistingNodeId != 0)
                    {
                        delete = true;
                    }

                    // determine if we may add new priority signs to this node
                    bool ok = false;
                    TrafficLightSimulation nodeSim = tlsMan.GetNodeSimulation(HoveredNodeId);
                    if ((Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None)
                    {
                        // no traffic light set
                        ok = true;
                    }
                    else if (nodeSim == null || !nodeSim.IsTimedLight())
                    {
                        ok = true;
                    }

                    if (!Flags.mayHaveTrafficLight(HoveredNodeId))
                    {
                        ok = false;
                    }

                    if (clicked)
                    {
                        Log._Debug("_guiPrioritySigns: hovered+clicked @ nodeId=" + HoveredNodeId + "/" + hoveredExistingNodeId + " ok=" + ok);

                        if (delete)
                        {
                            prioMan.RemovePrioritySegments(hoveredExistingNodeId);
                            RefreshCurrentPrioritySegmentIds();
                        }
                        else if (ok)
                        {
                            //if (!prioMan.IsPriorityNode(HoveredNodeId)) {
                            Log._Debug("_guiPrioritySigns: adding prio segments @ nodeId=" + HoveredNodeId);
                            tlsMan.RemoveNodeFromSimulation(HoveredNodeId, false, true);
                            tlm.RemoveTrafficLight(HoveredNodeId);
                            prioMan.AddPriorityNode(HoveredNodeId);
                            RefreshCurrentPrioritySegmentIds();
                            //}
                        }
                        else if (nodeSim != null && nodeSim.IsTimedLight())
                        {
                            MainTool.ShowTooltip(Translation.GetString("NODE_IS_TIMED_LIGHT"), Singleton <NetManager> .instance.m_nodes.m_buffer[HoveredNodeId].m_position);
                        }
                    }
                }
            } catch (Exception e) {
                Log.Error(e.ToString());
            }
        }
Пример #26
0
        internal void CalculateAutoPedestrianLightState(bool propagate = true)
        {
            //Log._Debug($"CustomSegmentLights.CalculateAutoPedestrianLightState: Calculating pedestrian light state of node {NodeId}");
            SegmentGeometry    segGeo             = SegmentGeometry.Get(SegmentId);
            SegmentEndGeometry segmentEndGeometry = StartNode ? segGeo.StartNodeGeometry : segGeo.EndNodeGeometry;

            if (segmentEndGeometry == null)
            {
                Log._Debug($"Could not get SegmentEndGeometry for segment {SegmentId} @ {NodeId}.");
                AutoPedestrianLightState = RoadBaseAI.TrafficLightState.Green;
                return;
            }
            ushort nodeId = segmentEndGeometry.NodeId();

            if (propagate)
            {
                foreach (ushort otherSegmentId in segmentEndGeometry.ConnectedSegments)
                {
                    if (otherSegmentId == 0)
                    {
                        continue;
                    }

                    CustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId);
                    if (otherLights == null)
                    {
                        //Log._Debug($"Expected other (propagate) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}");
                        continue;
                    }

                    otherLights.CalculateAutoPedestrianLightState(false);
                }
            }

            if (IsAnyGreen())
            {
                //Log._Debug($"Any green at seg. {SegmentId} @ {NodeId}");
                AutoPedestrianLightState = RoadBaseAI.TrafficLightState.Red;
                return;
            }

            //Log._Debug($"Querying incoming segments at seg. {SegmentId} @ {NodeId}");
            RoadBaseAI.TrafficLightState autoPedestrianLightState = RoadBaseAI.TrafficLightState.Green;

            if (!segmentEndGeometry.IncomingOneWay)
            {
                // query straight segments
                foreach (ushort otherSegmentId in segmentEndGeometry.IncomingStraightSegments)
                {
                    if (otherSegmentId == 0)
                    {
                        continue;
                    }
                    //Log._Debug($"Checking incoming straight segment {otherSegmentId} at seg. {SegmentId} @ {NodeId}");

                    CustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId);
                    if (otherLights == null)
                    {
                        //Log._Debug($"Expected other (straight) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}");
                        continue;
                    }

                    if (!otherLights.IsAllMainRed())
                    {
                        //Log._Debug($"Not all main red at {otherSegmentId} at seg. {SegmentId} @ {NodeId}");
                        autoPedestrianLightState = RoadBaseAI.TrafficLightState.Red;
                        break;
                    }
                }

                // query left/right segments
                if (autoPedestrianLightState == RoadBaseAI.TrafficLightState.Green)
                {
                    bool lhd = TrafficPriorityManager.IsLeftHandDrive();
                    foreach (ushort otherSegmentId in lhd ? segmentEndGeometry.IncomingLeftSegments : segmentEndGeometry.IncomingRightSegments)
                    {
                        if (otherSegmentId == 0)
                        {
                            continue;
                        }

                        //Log._Debug($"Checking left/right segment {otherSegmentId} at seg. {SegmentId} @ {NodeId}");

                        CustomSegmentLights otherLights = LightsManager.GetSegmentLights(nodeId, otherSegmentId);
                        if (otherLights == null)
                        {
                            //Log._Debug($"Expected other (left/right) CustomSegmentLights at segment {otherSegmentId} @ {NodeId} but there was none. Original segment id: {SegmentId}");
                            continue;
                        }

                        if ((lhd && !otherLights.IsAllRightRed()) || (!lhd && !otherLights.IsAllLeftRed()))
                        {
                            //Log._Debug($"Not all left red at {otherSegmentId} at seg. {SegmentId} @ {NodeId}");
                            autoPedestrianLightState = RoadBaseAI.TrafficLightState.Red;
                            break;
                        }
                    }
                }
            }

            AutoPedestrianLightState = autoPedestrianLightState;
            //Log.Warning($"Calculated AutoPedestrianLightState for segment {SegmentId} @ {NodeId}: {AutoPedestrianLightState}");
        }
        public static NetInfo.Direction GetSegmentEndDirection(ushort segmentId, ref NetSegment segment, bool startNode)
        {
            NetInfo segmentInfo = segment.Info;

            var dir = startNode ? NetInfo.Direction.Backward : NetInfo.Direction.Forward;

            if ((segment.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None ^ TrafficPriorityManager.IsLeftHandDrive())
            {
                dir = NetInfo.InvertDirection(dir);
            }

            return(dir);
        }
Пример #28
0
        /// <summary>
        /// Checks for traffic lights and priority signs when changing segments (for road & rail vehicles).
        /// Sets the maximum allowed speed <paramref name="maxSpeed"/> if segment change is not allowed (otherwise <paramref name="maxSpeed"/> has to be set by the calling method).
        /// </summary>
        /// <param name="vehicleId">vehicle id</param>
        /// <param name="vehicleData">vehicle data</param>
        /// <param name="lastFrameData">last frame data of vehicle</param>
        /// <param name="isRecklessDriver">if true, this vehicle ignores red traffic lights and priority signs</param>
        /// <param name="prevPos">previous path position</param>
        /// <param name="prevTargetNodeId">previous target node</param>
        /// <param name="prevLaneID">previous lane</param>
        /// <param name="position">current path position</param>
        /// <param name="targetNodeId">transit node</param>
        /// <param name="laneID">current lane</param>
        /// <param name="nextPosition">next path position</param>
        /// <param name="nextTargetNodeId">next target node</param>
        /// <param name="maxSpeed">maximum allowed speed (only valid if method returns false)</param>
        /// <returns>true, if the vehicle may change segments, false otherwise.</returns>
        internal static bool MayChangeSegment(ushort vehicleId, ref Vehicle vehicleData, ref Vehicle.Frame lastFrameData, bool isRecklessDriver, ref PathUnit.Position prevPos, ushort prevTargetNodeId, uint prevLaneID, ref PathUnit.Position position, ushort targetNodeId, uint laneID, ref PathUnit.Position nextPosition, ushort nextTargetNodeId, out float maxSpeed, bool debug = false)
        {
            debug = false;
            if (prevTargetNodeId != targetNodeId)
            {
                // method should only be called if targetNodeId == prevTargetNode
                maxSpeed = 0f;
                return(true);
            }

            bool         forceUpdatePos = false;
            VehicleState vehicleState   = null;

            VehicleStateManager vehStateManager = VehicleStateManager.Instance();

            if (Options.prioritySignsEnabled || Options.timedLightsEnabled)
            {
                vehicleState = vehStateManager.GetVehicleState(vehicleId);
            }

            if ((Options.prioritySignsEnabled || Options.timedLightsEnabled) && (forceUpdatePos || Options.simAccuracy >= 2))
            {
                try {
                    vehStateManager.UpdateVehiclePos(vehicleId, ref vehicleData, ref prevPos, ref position);
                } catch (Exception e) {
                    Log.Error("VehicleAI MayChangeSegment Error: " + e.ToString());
                }
            }

            var netManager = Singleton <NetManager> .instance;

            uint currentFrameIndex        = Singleton <SimulationManager> .instance.m_currentFrameIndex;
            uint prevTargetNodeLower8Bits = (uint)((prevTargetNodeId << 8) / 32768);
            uint random = currentFrameIndex - prevTargetNodeLower8Bits & 255u;

            bool isRailVehicle = (vehicleData.Info.m_vehicleType & (VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Metro)) != VehicleInfo.VehicleType.None;

            NetNode.Flags targetNodeFlags    = netManager.m_nodes.m_buffer[targetNodeId].m_flags;
            bool          hasTrafficLight    = (targetNodeFlags & NetNode.Flags.TrafficLights) != NetNode.Flags.None;
            bool          checkTrafficLights = false;

            if (!isRailVehicle)
            {
                // check if to check space

#if DEBUG
                if (debug)
                {
                    Log._Debug($"CustomVehicleAI.MayChangeSegment: Vehicle {vehicleId} is not a train.");
                }
#endif

                var  prevLaneFlags    = (NetLane.Flags)netManager.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_flags;
                var  hasCrossing      = (targetNodeFlags & NetNode.Flags.LevelCrossing) != NetNode.Flags.None;
                var  isJoinedJunction = (prevLaneFlags & NetLane.Flags.JoinedJunction) != NetLane.Flags.None;
                bool checkSpace       = !Flags.getEnterWhenBlockedAllowed(prevPos.m_segment, netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode == targetNodeId) && !isRecklessDriver;
                //TrafficLightSimulation nodeSim = TrafficLightSimulation.GetNodeSimulation(destinationNodeId);
                //if (timedNode != null && timedNode.vehiclesMayEnterBlockedJunctions) {
                //	checkSpace = false;
                //}

                if (checkSpace)
                {
                    // check if there is enough space
                    if ((targetNodeFlags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) == NetNode.Flags.Junction &&
                        netManager.m_nodes.m_buffer[targetNodeId].CountSegments() != 2)
                    {
                        var len = vehicleData.CalculateTotalLength(vehicleId) + 2f;
                        if (!netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(len))
                        {
                            var sufficientSpace = false;
                            if (nextPosition.m_segment != 0 && netManager.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_length < 30f)
                            {
                                NetNode.Flags nextTargetNodeFlags = netManager.m_nodes.m_buffer[nextTargetNodeId].m_flags;
                                if ((nextTargetNodeFlags & (NetNode.Flags.Junction | NetNode.Flags.OneWayOut | NetNode.Flags.OneWayIn)) != NetNode.Flags.Junction ||
                                    netManager.m_nodes.m_buffer[nextTargetNodeId].CountSegments() == 2)
                                {
                                    uint nextLaneId = PathManager.GetLaneID(nextPosition);
                                    if (nextLaneId != 0u)
                                    {
                                        sufficientSpace = netManager.m_lanes.m_buffer[(int)((UIntPtr)nextLaneId)].CheckSpace(len);
                                    }
                                }
                            }
                            if (!sufficientSpace)
                            {
                                maxSpeed = 0f;
                                try {
                                    if (vehicleState != null)
                                    {
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to BLOCKED");
                                        }
#endif

                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Blocked;
                                    }
                                } catch (Exception e) {
                                    Log.Error("VehicleAI MayChangeSegment error while setting junction state to BLOCKED: " + e.ToString());
                                }
                                return(false);
                            }
                        }
                    }
                }

                checkTrafficLights = (!isJoinedJunction || hasCrossing);
            }
            else
            {
#if DEBUG
                if (debug)
                {
                    Log._Debug($"CustomVehicleAI.MayChangeSegment: Vehicle {vehicleId} is a train.");
                }
#endif

                checkTrafficLights = true;
            }

            try {
                if (vehicleState != null && vehicleState.JunctionTransitState == VehicleJunctionTransitState.Blocked)
                {
#if DEBUG
                    if (debug)
                    {
                        Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState from BLOCKED to ENTER");
                    }
#endif
                    vehicleState.JunctionTransitState = VehicleJunctionTransitState.Enter;
                }

                if ((vehicleData.m_flags & Vehicle.Flags.Emergency2) == 0)
                {
                    if (hasTrafficLight && checkTrafficLights)
                    {
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomVehicleAI.MayChangeSegment: Node {targetNodeId} has a traffic light.");
                        }
#endif

                        var destinationInfo = netManager.m_nodes.m_buffer[targetNodeId].Info;

                        if (vehicleState != null && vehicleState.JunctionTransitState == VehicleJunctionTransitState.None)
                        {
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to ENTER (1)");
                            }
#endif
                            vehicleState.JunctionTransitState = VehicleJunctionTransitState.Enter;
                        }

                        RoadBaseAI.TrafficLightState vehicleLightState;
                        RoadBaseAI.TrafficLightState pedestrianLightState;
                        bool vehicles;
                        bool pedestrians;
                        CustomRoadAI.GetTrafficLightState(vehicleId, ref vehicleData, targetNodeId, prevPos.m_segment, prevPos.m_lane, position.m_segment, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - prevTargetNodeLower8Bits, out vehicleLightState, out pedestrianLightState, out vehicles, out pedestrians);

                        if (vehicleData.Info.m_vehicleType == VehicleInfo.VehicleType.Car && isRecklessDriver)                           // no reckless driving at railroad crossings
                        {
                            vehicleLightState = RoadBaseAI.TrafficLightState.Green;
                        }

#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"CustomVehicleAI.MayChangeSegment: Vehicle {vehicleId} has {vehicleLightState} at node {targetNodeId}");
                        }
#endif

                        if (!vehicles && random >= 196u)
                        {
                            vehicles = true;
                            RoadBaseAI.SetTrafficLightState(targetNodeId, ref netManager.m_segments.m_buffer[prevPos.m_segment], currentFrameIndex - prevTargetNodeLower8Bits, vehicleLightState, pedestrianLightState, vehicles, pedestrians);
                        }

                        var stopCar = false;
                        switch (vehicleLightState)
                        {
                        case RoadBaseAI.TrafficLightState.RedToGreen:
                            if (random < 60u)
                            {
                                stopCar = true;
                            }
                            else
                            {
#if DEBUG
                                if (debug)
                                {
                                    Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (RedToGreen)");
                                }
#endif
                                if (vehicleState != null)
                                {
                                    vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                }
                            }
                            break;

                        case RoadBaseAI.TrafficLightState.Red:
                            stopCar = true;
                            break;

                        case RoadBaseAI.TrafficLightState.GreenToRed:
                            if (random >= 30u)
                            {
                                stopCar = true;
                            }
                            else if (vehicleState != null)
                            {
#if DEBUG
                                if (debug)
                                {
                                    Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (GreenToRed)");
                                }
#endif
                                vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                            }
                            break;
                        }

                        /*if ((vehicleLightState == RoadBaseAI.TrafficLightState.Green || vehicleLightState == RoadBaseAI.TrafficLightState.RedToGreen) && !Flags.getEnterWhenBlockedAllowed(prevPos.m_segment, netManager.m_segments.m_buffer[prevPos.m_segment].m_startNode == targetNodeId)) {
                         *      var hasIncomingCars = TrafficPriority.HasIncomingVehiclesWithHigherPriority(vehicleId, targetNodeId);
                         *
                         *      if (hasIncomingCars) {
                         *              // green light but other cars are incoming and they have priority: stop
                         *              stopCar = true;
                         *      }
                         * }*/

                        if (stopCar)
                        {
                            if (vehicleState != null)
                            {
#if DEBUG
                                if (debug)
                                {
                                    Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to STOP");
                                }
#endif
                                vehicleState.JunctionTransitState = VehicleJunctionTransitState.Stop;
                            }
                            maxSpeed = 0f;
                            return(false);
                        }
                    }
                    else if (vehicleState != null && Options.prioritySignsEnabled)
                    {
                        TrafficPriorityManager prioMan = TrafficPriorityManager.Instance();

#if DEBUG
                        //bool debug = destinationNodeId == 10864;
                        //bool debug = destinationNodeId == 13531;
                        //bool debug = false;// targetNodeId == 5027;
#endif
                        //bool debug = false;
#if DEBUG
                        if (debug)
                        {
                            Log._Debug($"Vehicle {vehicleId} is arriving @ seg. {prevPos.m_segment} ({position.m_segment}, {nextPosition.m_segment}), node {targetNodeId} which is not a traffic light.");
                        }
#endif

                        var prioritySegment = prioMan.GetPrioritySegment(targetNodeId, prevPos.m_segment);
                        if (prioritySegment != null)
                        {
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"Vehicle {vehicleId} is arriving @ seg. {prevPos.m_segment} ({position.m_segment}, {nextPosition.m_segment}), node {targetNodeId} which is not a traffic light and is a priority segment.");
                            }
#endif
                            //if (prioritySegment.HasVehicle(vehicleId)) {
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"Vehicle {vehicleId}: segment target position found");
                            }
#endif
#if DEBUG
                            if (debug)
                            {
                                Log._Debug($"Vehicle {vehicleId}: global target position found. carState = {vehicleState.JunctionTransitState.ToString()}");
                            }
#endif
                            var   currentFrameIndex2 = Singleton <SimulationManager> .instance.m_currentFrameIndex;
                            var   frame = currentFrameIndex2 >> 4;
                            float speed = lastFrameData.m_velocity.magnitude;

                            if (vehicleState.JunctionTransitState == VehicleJunctionTransitState.None)
                            {
#if DEBUG
                                if (debug)
                                {
                                    Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to ENTER (prio)");
                                }
#endif
                                vehicleState.JunctionTransitState = VehicleJunctionTransitState.Enter;
                            }

                            if (vehicleState.JunctionTransitState != VehicleJunctionTransitState.Leave)
                            {
                                bool hasIncomingCars;
                                switch (prioritySegment.Type)
                                {
                                case SegmentEnd.PriorityType.Stop:
#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"Vehicle {vehicleId}: STOP sign. waittime={vehicleState.WaitTime}, vel={speed}");
                                    }
#endif

                                    if (Options.simAccuracy <= 2 || (Options.simAccuracy >= 3 && vehicleState.WaitTime < MaxPriorityWaitTime))
                                    {
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to STOP (wait)");
                                        }
#endif
                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Stop;

                                        if (speed <= TrafficPriorityManager.maxStopVelocity)
                                        {
                                            vehicleState.WaitTime++;

                                            float minStopWaitTime = UnityEngine.Random.Range(0f, 3f);
                                            if (vehicleState.WaitTime >= minStopWaitTime)
                                            {
                                                if (Options.simAccuracy >= 4)
                                                {
                                                    vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                                }
                                                else
                                                {
                                                    hasIncomingCars = prioMan.HasIncomingVehiclesWithHigherPriority(vehicleId, ref vehicleData, ref prevPos, ref position);
#if DEBUG
                                                    if (debug)
                                                    {
                                                        Log._Debug($"hasIncomingCars: {hasIncomingCars}");
                                                    }
#endif

                                                    if (hasIncomingCars)
                                                    {
                                                        maxSpeed = 0f;
                                                        return(false);
                                                    }
#if DEBUG
                                                    if (debug)
                                                    {
                                                        Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (min wait timeout)");
                                                    }
#endif
                                                    vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                                }
                                            }
                                            else
                                            {
                                                maxSpeed = 0;
                                                return(false);
                                            }
                                        }
                                        else
                                        {
                                            vehicleState.WaitTime = 0;
                                            maxSpeed = 0f;
                                            return(false);
                                        }
                                    }
                                    else
                                    {
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (max wait timeout)");
                                        }
#endif
                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                    }
                                    break;

                                case SegmentEnd.PriorityType.Yield:
#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"Vehicle {vehicleId}: YIELD sign. waittime={vehicleState.WaitTime}");
                                    }
#endif

                                    if (Options.simAccuracy <= 2 || (Options.simAccuracy >= 3 && vehicleState.WaitTime < MaxPriorityWaitTime))
                                    {
                                        vehicleState.WaitTime++;
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to STOP (wait)");
                                        }
#endif
                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Stop;

                                        if (speed <= TrafficPriorityManager.maxYieldVelocity || Options.simAccuracy <= 2)
                                        {
                                            if (Options.simAccuracy >= 4)
                                            {
                                                vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                            }
                                            else
                                            {
                                                hasIncomingCars = prioMan.HasIncomingVehiclesWithHigherPriority(vehicleId, ref vehicleData, ref prevPos, ref position);
#if DEBUG
                                                if (debug)
                                                {
                                                    Log._Debug($"Vehicle {vehicleId}: hasIncomingCars: {hasIncomingCars}");
                                                }
#endif

                                                if (hasIncomingCars)
                                                {
                                                    maxSpeed = 0f;
                                                    return(false);
                                                }
                                                else
                                                {
#if DEBUG
                                                    if (debug)
                                                    {
                                                        Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (no incoming cars)");
                                                    }
#endif
                                                    vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                                }
                                            }
                                        }
                                        else
                                        {
#if DEBUG
                                            if (debug)
                                            {
                                                Log._Debug($"Vehicle {vehicleId}: Vehicle has not yet reached yield speed (reduce {speed} by {vehicleState.ReduceSpeedByValueToYield})");
                                            }
#endif

                                            // vehicle has not yet reached yield speed
                                            maxSpeed = TrafficPriorityManager.maxYieldVelocity;
                                            return(false);
                                        }
                                    }
                                    else
                                    {
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (max wait timeout)");
                                        }
#endif
                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                    }
                                    break;

                                case SegmentEnd.PriorityType.Main:
                                case SegmentEnd.PriorityType.None:
#if DEBUG
                                    if (debug)
                                    {
                                        Log._Debug($"Vehicle {vehicleId}: MAIN sign. waittime={vehicleState.WaitTime}");
                                    }
#endif
                                    maxSpeed = 0f;

                                    if (Options.simAccuracy == 4)
                                    {
                                        return(true);
                                    }

                                    if (Options.simAccuracy <= 2 || (Options.simAccuracy == 3 && vehicleState.WaitTime < MaxPriorityWaitTime))
                                    {
                                        vehicleState.WaitTime++;
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to STOP (wait)");
                                        }
#endif
                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Stop;

                                        hasIncomingCars = prioMan.HasIncomingVehiclesWithHigherPriority(vehicleId, ref vehicleData, ref prevPos, ref position);
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"hasIncomingCars: {hasIncomingCars}");
                                        }
#endif

                                        if (hasIncomingCars)
                                        {
                                            return(false);
                                        }
#if DEBUG
                                        if (debug)
                                        {
                                            Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState to LEAVE (no conflicting car)");
                                        }
#endif
                                        vehicleState.JunctionTransitState = VehicleJunctionTransitState.Leave;
                                    }
                                    return(true);
                                }
                            }
                            else if (speed <= TrafficPriorityManager.maxStopVelocity)
                            {
                                // vehicle is not moving. reset allowance to leave junction
#if DEBUG
                                if (debug)
                                {
                                    Log._Debug($"Vehicle {vehicleId}: Setting JunctionTransitState from LEAVE to BLOCKED (speed to low)");
                                }
#endif
                                vehicleState.JunctionTransitState = VehicleJunctionTransitState.Blocked;

                                maxSpeed = 0f;
                                return(false);
                            }
                        }
                    }
                }
            } catch (Exception e) {
                Log.Error($"Error occured in MayChangeSegment: {e.ToString()}");
            }
            maxSpeed = 0f;             // maxSpeed should be set by caller
            return(true);
        }
        public void ShowGUI(bool viewOnly)
        {
            try {
                IExtSegmentManager            segMan    = Constants.ManagerFactory.ExtSegmentManager;
                IExtSegmentEndManager         segEndMan = Constants.ManagerFactory.ExtSegmentEndManager;
                TrafficLightSimulationManager tlsMan    = TrafficLightSimulationManager.Instance;
                TrafficPriorityManager        prioMan   = TrafficPriorityManager.Instance;
                TrafficLightManager           tlm       = TrafficLightManager.Instance;

                Vector3 camPos = Constants.ServiceFactory.SimulationService.CameraPosition;

                bool clicked = !viewOnly?MainTool.CheckClicked() : false;

                ushort removedNodeId    = 0;
                bool   showRemoveButton = false;
                foreach (ushort nodeId in currentPriorityNodeIds)
                {
                    if (!Constants.ServiceFactory.NetService.IsNodeValid(nodeId))
                    {
                        continue;
                    }

                    if (!MainTool.IsNodeWithinViewDistance(nodeId))
                    {
                        continue;
                    }

                    Vector3 nodePos = default(Vector3);
                    Constants.ServiceFactory.NetService.ProcessNode(nodeId, delegate(ushort nId, ref NetNode node) {
                        nodePos = node.m_position;
                        return(true);
                    });

                    for (int i = 0; i < 8; ++i)
                    {
                        ushort segmentId = 0;
                        Constants.ServiceFactory.NetService.ProcessNode(nodeId, delegate(ushort nId, ref NetNode node) {
                            segmentId = node.GetSegment(i);
                            return(true);
                        });

                        if (segmentId == 0)
                        {
                            continue;
                        }

                        bool          startNode = (bool)Constants.ServiceFactory.NetService.IsStartNode(segmentId, nodeId);
                        ExtSegment    seg       = segMan.ExtSegments[segmentId];
                        ExtSegmentEnd segEnd    = segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, startNode)];

                        if (seg.oneWay && segEnd.outgoing)
                        {
                            continue;
                        }

                        // calculate sign position
                        Vector3 signPos = nodePos;

                        Constants.ServiceFactory.NetService.ProcessSegment(segmentId, delegate(ushort sId, ref NetSegment segment) {
                            signPos += 10f * (startNode ? segment.m_startDirection : segment.m_endDirection);
                            return(true);
                        });

                        Vector3 signScreenPos;
                        if (!MainTool.WorldToScreenPoint(signPos, out signScreenPos))
                        {
                            continue;
                        }

                        // draw sign and handle input
                        PriorityType sign = prioMan.GetPrioritySign(segmentId, startNode);
                        if (viewOnly && sign == PriorityType.None)
                        {
                            continue;
                        }
                        if (!viewOnly && sign != PriorityType.None)
                        {
                            showRemoveButton = true;
                        }

                        if (MainTool.DrawGenericSquareOverlayTexture(TextureResources.PrioritySignTextures[sign], camPos, signPos, 90f, !viewOnly) && clicked)
                        {
                            PriorityType?newSign = null;
                            switch (sign)
                            {
                            case PriorityType.Main:
                                newSign = PriorityType.Yield;
                                break;

                            case PriorityType.Yield:
                                newSign = PriorityType.Stop;
                                break;

                            case PriorityType.Stop:
                                newSign = PriorityType.Main;
                                break;

                            case PriorityType.None:
                            default:
                                newSign = prioMan.CountPrioritySignsAtNode(nodeId, PriorityType.Main) >= 2 ? PriorityType.Yield : PriorityType.Main;
                                break;
                            }

                            if (newSign != null)
                            {
                                SetPrioritySign(segmentId, startNode, (PriorityType)newSign);
                            }
                        }                 // draw sign
                    }                     // foreach segment end

                    if (viewOnly)
                    {
                        continue;
                    }

                    // draw remove button and handle click
                    if (showRemoveButton && MainTool.DrawHoverableSquareOverlayTexture(TextureResources.SignRemoveTexture2D, camPos, nodePos, 90f) && clicked)
                    {
                        prioMan.RemovePrioritySignsFromNode(nodeId);
                        Log._Debug($"PrioritySignsTool.ShowGUI: Removed priority signs from node {nodeId}");
                        removedNodeId = nodeId;
                    }
                }                 // foreach node

                if (removedNodeId != 0)
                {
                    currentPriorityNodeIds.Remove(removedNodeId);
                    SelectedNodeId = 0;
                }
            } catch (Exception e) {
                Log.Error(e.ToString());
            }
        }
Пример #30
0
        /// <summary>
        /// Recalculates lane arrows based on present lane connections.
        /// </summary>
        /// <param name="laneId"></param>
        /// <param name="nodeId"></param>
        private void RecalculateLaneArrows(uint laneId, ushort nodeId, bool startNode)
        {
#if DEBUGCONN
            Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}) called");
#endif
            if (!Flags.mayHaveLaneArrows(laneId, startNode))
            {
#if DEBUGCONN
                Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): lane {laneId}, startNode? {startNode} must not have lane arrows");
#endif
                return;
            }

            if (!HasConnections(laneId, startNode))
            {
#if DEBUGCONN
                Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): lane {laneId} does not have outgoing connections");
#endif
                return;
            }

            if (nodeId == 0)
            {
#if DEBUGCONN
                Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): invalid node");
#endif
                return;
            }

            Flags.LaneArrows arrows = Flags.LaneArrows.None;

            NetManager netManager = Singleton <NetManager> .instance;
            ushort     segmentId  = netManager.m_lanes.m_buffer[laneId].m_segment;

            if (segmentId == 0)
            {
#if DEBUGCONN
                Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): invalid segment");
#endif
                return;
            }

#if DEBUGCONN
            Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): startNode? {startNode}");
#endif

            NodeGeometry nodeGeo = NodeGeometry.Get(nodeId);
            if (!nodeGeo.IsValid())
            {
#if DEBUGCONN
                Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): invalid node geometry");
#endif
                return;
            }

            SegmentGeometry segmentGeo = SegmentGeometry.Get(segmentId);
            if (!segmentGeo.IsValid())
            {
#if DEBUGCONN
                Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): invalid segment geometry");
#endif
                return;
            }

            ushort[] connectedSegmentIds = segmentGeo.GetConnectedSegments(startNode);
            if (connectedSegmentIds == null)
            {
#if DEBUGCONN
                Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): connectedSegmentIds is null");
#endif
                return;
            }

            foreach (ushort connectedSegmentId in connectedSegmentIds)
            {
                if (connectedSegmentId == 0)
                {
                    continue;
                }
                ArrowDirection dir = segmentGeo.GetDirection(connectedSegmentId, startNode);

#if DEBUGCONN
                Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): processing connected segment {connectedSegmentId}. dir={dir}");
#endif

                // check if arrow has already been set for this direction
                switch (dir)
                {
                case ArrowDirection.Turn:
                    if (TrafficPriorityManager.IsLeftHandDrive())
                    {
                        if ((arrows & Flags.LaneArrows.Right) != Flags.LaneArrows.None)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if ((arrows & Flags.LaneArrows.Left) != Flags.LaneArrows.None)
                        {
                            continue;
                        }
                    }
                    break;

                case ArrowDirection.Forward:
                    if ((arrows & Flags.LaneArrows.Forward) != Flags.LaneArrows.None)
                    {
                        continue;
                    }
                    break;

                case ArrowDirection.Left:
                    if ((arrows & Flags.LaneArrows.Left) != Flags.LaneArrows.None)
                    {
                        continue;
                    }
                    break;

                case ArrowDirection.Right:
                    if ((arrows & Flags.LaneArrows.Right) != Flags.LaneArrows.None)
                    {
                        continue;
                    }
                    break;

                default:
                    continue;
                }

#if DEBUGCONN
                Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): processing connected segment {connectedSegmentId}: need to determine arrows");
#endif

                bool addArrow = false;

                uint curLaneId = netManager.m_segments.m_buffer[connectedSegmentId].m_lanes;
                while (curLaneId != 0)
                {
#if DEBUGCONN
                    Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): processing connected segment {connectedSegmentId}: checking lane {curLaneId}");
#endif
                    if (AreLanesConnected(laneId, curLaneId, startNode))
                    {
#if DEBUGCONN
                        Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): processing connected segment {connectedSegmentId}: checking lane {curLaneId}: lanes are connected");
#endif
                        addArrow = true;
                        break;
                    }

                    curLaneId = netManager.m_lanes.m_buffer[curLaneId].m_nextLane;
                }

#if DEBUGCONN
                Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): processing connected segment {connectedSegmentId}: finished processing lanes. addArrow={addArrow} arrows (before)={arrows}");
#endif
                if (addArrow)
                {
                    switch (dir)
                    {
                    case ArrowDirection.Turn:
                        if (TrafficPriorityManager.IsLeftHandDrive())
                        {
                            arrows |= Flags.LaneArrows.Right;
                        }
                        else
                        {
                            arrows |= Flags.LaneArrows.Left;
                        }
                        break;

                    case ArrowDirection.Forward:
                        arrows |= Flags.LaneArrows.Forward;
                        break;

                    case ArrowDirection.Left:
                        arrows |= Flags.LaneArrows.Left;
                        break;

                    case ArrowDirection.Right:
                        arrows |= Flags.LaneArrows.Right;
                        break;

                    default:
                        continue;
                    }

#if DEBUGCONN
                    Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): processing connected segment {connectedSegmentId}: arrows={arrows}");
#endif
                }
            }

#if DEBUGCONN
            Log._Debug($"LaneConnectionManager.RecalculateLaneArrows({laneId}, {nodeId}): setting lane arrows to {arrows}");
#endif

            LaneArrowManager.Instance.SetLaneArrows(laneId, arrows, true);
        }