public void MarkAsUpdated(NodeGeometry geometry)
        {
#if DEBUGGEO
            if (GlobalConfig.Instance.Debug.Switches[5])
            {
                Log._Debug($"GeometryManager.MarkAsUpdated(node {geometry.NodeId}): Marking node as updated");
            }
#endif
            try {
                Monitor.Enter(updateLock);

                ushort nodeId = geometry.NodeId;
                if (nodeId != 0)
                {
                    updatedNodeBuckets[nodeId >> 6] |= 1uL << (int)(nodeId & 63);
                    stateUpdated = true;

                    if (!geometry.IsValid())
                    {
                        SimulationStep(true);
                    }
                }
            } finally {
                Monitor.Exit(updateLock);
            }
        }
        /// <summary>
        /// Removes custom traffic lights at the given node
        /// </summary>
        /// <param name="nodeId"></param>
        public void RemoveNodeLights(ushort nodeId)
        {
            NodeGeometry nodeGeo = NodeGeometry.Get(nodeId);

            if (!nodeGeo.IsValid())
            {
                return;
            }
            foreach (SegmentEndGeometry endGeo in nodeGeo.SegmentEndGeometries)
            {
                if (endGeo == null)
                {
                    continue;
                }

                RemoveSegmentLight(endGeo.SegmentId, endGeo.StartNode);
            }
        }
        /// <summary>
        /// Add custom traffic lights at the given node
        /// </summary>
        /// <param name="nodeId"></param>
        public void AddNodeLights(ushort nodeId)
        {
            NodeGeometry nodeGeo = NodeGeometry.Get(nodeId);

            if (!nodeGeo.IsValid())
            {
                return;
            }

            foreach (SegmentEndGeometry endGeo in nodeGeo.SegmentEndGeometries)
            {
                if (endGeo == null)
                {
                    continue;
                }

                AddSegmentLights(endGeo.SegmentId, endGeo.StartNode);

                DebugOutputPanel.AddMessage(PluginManager.MessageType.Message, "Adding to Queue: " + nodeId);
                NetworkInterface.Network.UpdateSelectedIds(nodeId);
            }
        }
예제 #4
0
        public void MarkAsUpdated(NodeGeometry geometry, bool updateSegments = false)
        {
#if DEBUGGEO
            if (GlobalConfig.Instance.Debug.Switches[5])
            {
                Log._Debug($"GeometryManager.MarkAsUpdated(node {geometry.NodeId}): Marking node as updated");
            }
#endif
            try {
                Monitor.Enter(updateLock);

                ushort nodeId = geometry.NodeId;
                if (nodeId != 0)
                {
                    updatedNodeBuckets[nodeId >> 6] |= 1uL << (int)(nodeId & 63);
                    stateUpdated = true;

                    if (updateSegments)
                    {
                        foreach (SegmentEndGeometry segEndGeo in geometry.SegmentEndGeometries)
                        {
                            if (segEndGeo != null)
                            {
                                MarkAsUpdated(segEndGeo.GetSegmentGeometry(), false);
                            }
                        }
                    }

                    if (!geometry.IsValid())
                    {
                        SimulationStep(true);
                    }
                }
            } finally {
                Monitor.Exit(updateLock);
            }
        }
예제 #5
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 (!Options.laneConnectorEnabled)
            {
                return;
            }

            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 == null)
            {
#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;
            }
            ushort[] allSegmentIds = new ushort[connectedSegmentIds.Length + 1];
            allSegmentIds[0] = segmentId;
            Array.Copy(connectedSegmentIds, 0, allSegmentIds, 1, connectedSegmentIds.Length);

            foreach (ushort otherSegmentId in allSegmentIds)
            {
                if (otherSegmentId == 0)
                {
                    continue;
                }
                ArrowDirection dir = segmentGeo.GetDirection(otherSegmentId, 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 (Constants.ServiceFactory.SimulationService.LeftHandDrive)
                    {
                        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[otherSegmentId].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 (Constants.ServiceFactory.SimulationService.LeftHandDrive)
                        {
                            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);
        }
예제 #6
0
        public void SimulationStep(bool onlyFirstPass = false)
        {
#if DEBUGGEO
            bool debug = GlobalConfig.Instance.Debug.Switches[5];
#endif
            if (!stateUpdated)
            {
                return;
            }

            NetManager netManager = Singleton <NetManager> .instance;
            if (!onlyFirstPass && (netManager.m_segmentsUpdated || netManager.m_nodesUpdated))               // TODO maybe refactor NetManager use (however this could influence performance)
            {
#if DEBUGGEO
                if (debug)
                {
                    Log._Debug($"GeometryManager.SimulationStep(): Skipping! stateUpdated={stateUpdated}, m_segmentsUpdated={netManager.m_segmentsUpdated}, m_nodesUpdated={netManager.m_nodesUpdated}");
                }
#endif
                return;
            }

            try {
                Monitor.Enter(updateLock);

                bool updatesMissing = onlyFirstPass;
                for (int pass = 0; pass < (onlyFirstPass ? 1 : 2); ++pass)
                {
                    bool firstPass = pass == 0;

                    int len = updatedSegmentBuckets.Length;
                    for (int i = 0; i < len; i++)
                    {
                        ulong segMask = updatedSegmentBuckets[i];
                        if (segMask != 0uL)
                        {
                            for (int m = 0; m < 64; m++)
                            {
                                if ((segMask & 1uL << m) != 0uL)
                                {
                                    ushort          segmentId       = (ushort)(i << 6 | m);
                                    SegmentGeometry segmentGeometry = SegmentGeometry.Get(segmentId, true);
                                    if (firstPass ^ !segmentGeometry.IsValid())
                                    {
                                        if (!firstPass)
                                        {
                                            updatesMissing = true;
#if DEBUGGEO
                                            if (debug)
                                            {
                                                Log.Warning($"GeometryManager.SimulationStep(): Detected invalid segment {segmentGeometry.SegmentId} in second pass");
                                            }
#endif
                                        }
                                        continue;
                                    }
#if DEBUGGEO
                                    if (debug)
                                    {
                                        Log._Debug($"GeometryManager.SimulationStep(): Notifying observers about segment {segmentGeometry.SegmentId}. Valid? {segmentGeometry.IsValid()} First pass? {firstPass}");
                                    }
#endif
                                    NotifyObservers(new GeometryUpdate(segmentGeometry));
                                    updatedSegmentBuckets[i] &= ~(1uL << m);
                                }
                            }
                        }
                    }

                    len = updatedNodeBuckets.Length;
                    for (int i = 0; i < len; i++)
                    {
                        ulong nodeMask = updatedNodeBuckets[i];
                        if (nodeMask != 0uL)
                        {
                            for (int m = 0; m < 64; m++)
                            {
                                if ((nodeMask & 1uL << m) != 0uL)
                                {
                                    ushort       nodeId       = (ushort)(i << 6 | m);
                                    NodeGeometry nodeGeometry = NodeGeometry.Get(nodeId);
                                    if (firstPass ^ !nodeGeometry.IsValid())
                                    {
                                        if (!firstPass)
                                        {
                                            updatesMissing = true;
#if DEBUGGEO
                                            if (debug)
                                            {
                                                Log.Warning($"GeometryManager.SimulationStep(): Detected invalid node {nodeGeometry.NodeId} in second pass");
                                            }
#endif
                                        }
                                        continue;
                                    }
#if DEBUGGEO
                                    if (debug)
                                    {
                                        Log._Debug($"GeometryManager.SimulationStep(): Notifying observers about node {nodeGeometry.NodeId}. Valid? {nodeGeometry.IsValid()} First pass? {firstPass}");
                                    }
#endif
                                    NotifyObservers(new GeometryUpdate(nodeGeometry));
                                    updatedNodeBuckets[i] &= ~(1uL << m);
                                }
                            }
                        }
                    }
                }

                if (!updatesMissing)
                {
                    while (segmentReplacements.Count > 0)
                    {
                        SegmentEndReplacement replacement = segmentReplacements.Dequeue();
#if DEBUGGEO
                        if (debug)
                        {
                            Log._Debug($"GeometryManager.SimulationStep(): Notifying observers about segment end replacement {replacement}");
                        }
#endif
                        NotifyObservers(new GeometryUpdate(replacement));
                    }

                    stateUpdated = false;
                }
            } finally {
                Monitor.Exit(updateLock);
            }
        }
        public void OnUpdate(GeometryUpdate update)
        {
            if (update.segmentGeometry != null)
            {
                // Handle a segment update
                SegmentGeometry geometry = update.segmentGeometry;
                if (!geometry.IsValid())
                {
#if DEBUGGEO
                    if (GlobalConfig.Instance.Debug.Switches[5])
                    {
                        Log._Debug($"{this.GetType().Name}.HandleInvalidSegment({geometry.SegmentId})");
                    }
#endif
                    HandleInvalidSegment(geometry);
                }
                else
                {
#if DEBUGGEO
                    if (GlobalConfig.Instance.Debug.Switches[5])
                    {
                        Log._Debug($"{this.GetType().Name}.HandleValidSegment({geometry.SegmentId})");
                    }
#endif
                    HandleValidSegment(geometry);
                }
            }
            else if (update.nodeGeometry != null)
            {
                // Handle a node update
                NodeGeometry geometry = update.nodeGeometry;
                if (!geometry.IsValid())
                {
#if DEBUGGEO
                    if (GlobalConfig.Instance.Debug.Switches[5])
                    {
                        Log._Debug($"{this.GetType().Name}.HandleInvalidNode({geometry.NodeId})");
                    }
#endif
                    HandleInvalidNode(geometry);
                }
                else
                {
#if DEBUGGEO
                    if (GlobalConfig.Instance.Debug.Switches[5])
                    {
                        Log._Debug($"{this.GetType().Name}.HandleValidNode({geometry.NodeId})");
                    }
#endif
                    HandleValidNode(geometry);
                }
            }
            else
            {
                // Handle a segment end replacement
                SegmentEndGeometry endGeo = SegmentGeometry.Get(update.replacement.newSegmentEndId.SegmentId)?.GetEnd(update.replacement.newSegmentEndId.StartNode);
                if (endGeo != null)
                {
#if DEBUGGEO
                    if (GlobalConfig.Instance.Debug.Switches[5])
                    {
                        Log._Debug($"{this.GetType().Name}.HandleSegmentReplacement({update.replacement.oldSegmentEndId} -> {update.replacement.newSegmentEndId})");
                    }
#endif
                    HandleSegmentEndReplacement(update.replacement, endGeo);
                }
            }
        }