示例#1
0
        /// <summary>
        /// Intersects this direction with a line.
        /// </summary>
        /// <param name="line">The line to intersect with.</param>
        /// <param name="closeTo">The point that the intersection should be closest to.
        /// Specify null if you don't care. In that case, if there are multiple intersections,
        /// you get the intersection that is closest to one of 3 points: the start of the
        /// direction line, the start of the line, or the end of the line.</param>
        /// <param name="xsect">The position of the intersection (if any). Null if not found.</param>
        /// <param name="closest">The default point that is closest to the intersection. Null if
        /// intersection wasn't found.</param>
        /// <returns>True if intersection was found.</returns>
        internal bool Intersect( LineFeature line
            , PointFeature closeTo
            , out IPosition xsect
            , out PointFeature closest)
        {
            // Initialize results
            xsect = null;
            closest = null;

            // Define the length of the direction line as the length
            // of a diagonal that crosses the map's extent.
            IWindow mapWin = SpatialController.Current.MapModel.Extent;
            Debug.Assert(mapWin!=null);

            // If the window is currently undefined (e.g. during deserialization),
            // just use a really big distance.
            // TODO: This is a hack, but hopefully it may be shortlived, because
            // new logic is in the works for handling updates.
            double dist = (mapWin.IsEmpty ? 100000.0 : Geom.Distance(mapWin.Min, mapWin.Max));

            // Define the position of the direction line. DON'T use the from-
            // point, because there may be an offset to the direction.
            IPosition fromPos = this.StartPosition;
            IPosition toPos = Geom.Polar(fromPos, this.Bearing.Radians, dist);

            // Construct a corresponding line segment.
            ITerminal start = new FloatingTerminal(fromPos);
            ITerminal end = new FloatingTerminal(toPos);
            SegmentGeometry seg = new SegmentGeometry(start, end);

            // Intersect the line segment with the other one.
            IntersectionResult xres = new IntersectionResult(line);
            uint nx = seg.Intersect(xres);
            if (nx==0)
                return false;

            // Determine which terminal point is the best. Start with the
            // ends of the intersected line.
            double mindsq = Double.MaxValue;

            if (xres.GetCloserPoint(line.StartPoint, ref mindsq, ref xsect))
                closest = line.StartPoint;

            if (xres.GetCloserPoint(line.EndPoint, ref mindsq, ref xsect))
                closest = line.EndPoint;

            // Check whether the direction from-point is any closer (the position may be
            // different from the start of the direction line, because the direction may
            // have an offset).

            if (xres.GetCloserPoint(this.From, ref mindsq, ref xsect))
                closest = this.From;

            // If a close-to point has been specified, that overrides
            // everything else (however, doing the above has the desired
            // effect of defining the best of the default points). In
            // this case, we allow an intersection that coincides with
            // the line being intersected.
            // -- actually, we don't, since GetClosest uses a > 0 test

            if (closeTo != null)
            {
                xres.GetClosest(closeTo, out xsect, 0.0);
                /*
                IPosition xCloseTo;
                xres.GetClosest(closeTo, out xCloseTo, 0.0);

                if (xCloseTo != null)
                    xsect = xCloseTo;
                 */
            }

            return (xsect!=null);
        }
		internal static void OnBeforeLoadData() {
			if (!initDone) {
				segmentGeometries = new SegmentGeometry[Singleton<NetManager>.instance.m_segments.m_size];
				Log._Debug($"Building {segmentGeometries.Length} segment geometries...");
				for (ushort i = 0; i < segmentGeometries.Length; ++i) {
					segmentGeometries[i] = new SegmentGeometry(i);
				}
				Log._Debug($"Calculated segment geometries.");

				currentLaneTrafficBuffer = new ushort[Singleton<NetManager>.instance.m_lanes.m_size];
				currentLaneSpeeds = new uint[Singleton<NetManager>.instance.m_lanes.m_size];
				currentLaneDensities = new uint[Singleton<NetManager>.instance.m_lanes.m_size];
				laneMeanSpeeds = new byte[Singleton<NetManager>.instance.m_lanes.m_size];
				//laneMeanDensities = new byte[Singleton<NetManager>.instance.m_lanes.m_size];
				resetTrafficStats();
				initDone = true;
			}
		}
示例#3
0
        public bool LoadData(List <Configuration.SegmentNodeConf> data)
        {
            bool success = true;

            Log.Info($"Loading junction restrictions. {data.Count} elements");
            foreach (Configuration.SegmentNodeConf segNodeConf in data)
            {
                try {
                    if (!Services.NetService.IsSegmentValid(segNodeConf.segmentId))
                    {
                        continue;
                    }

                    Log._Debug($"JunctionRestrictionsManager.LoadData: Loading junction restrictions for segment {segNodeConf.segmentId}: startNodeFlags={segNodeConf.startNodeFlags} endNodeFlags={segNodeConf.endNodeFlags}");

                    if (segNodeConf.startNodeFlags != null)
                    {
                        SegmentEndGeometry startNodeSegGeo = SegmentGeometry.Get(segNodeConf.segmentId)?.GetEnd(true);
                        if (startNodeSegGeo != null)
                        {
                            Configuration.SegmentNodeFlags flags = segNodeConf.startNodeFlags;

                            Services.NetService.ProcessNode(startNodeSegGeo.NodeId(), delegate(ushort nId, ref NetNode node) {
                                if (flags.uturnAllowed != null && IsUturnAllowedConfigurable(segNodeConf.segmentId, true, ref node))
                                {
                                    SetUturnAllowed(segNodeConf.segmentId, true, (bool)flags.uturnAllowed);
                                }

                                if (flags.turnOnRedAllowed != null && IsNearTurnOnRedAllowedConfigurable(segNodeConf.segmentId, true, ref node))
                                {
                                    SetNearTurnOnRedAllowed(segNodeConf.segmentId, true, (bool)flags.turnOnRedAllowed);
                                }

                                if (flags.farTurnOnRedAllowed != null && IsFarTurnOnRedAllowedConfigurable(segNodeConf.segmentId, true, ref node))
                                {
                                    SetFarTurnOnRedAllowed(segNodeConf.segmentId, true, (bool)flags.farTurnOnRedAllowed);
                                }

                                if (flags.straightLaneChangingAllowed != null && IsLaneChangingAllowedWhenGoingStraightConfigurable(segNodeConf.segmentId, true, ref node))
                                {
                                    SetLaneChangingAllowedWhenGoingStraight(segNodeConf.segmentId, true, (bool)flags.straightLaneChangingAllowed);
                                }

                                if (flags.enterWhenBlockedAllowed != null && IsEnteringBlockedJunctionAllowedConfigurable(segNodeConf.segmentId, true, ref node))
                                {
                                    SetEnteringBlockedJunctionAllowed(segNodeConf.segmentId, true, (bool)flags.enterWhenBlockedAllowed);
                                }

                                if (flags.pedestrianCrossingAllowed != null && IsPedestrianCrossingAllowedConfigurable(segNodeConf.segmentId, true, ref node))
                                {
                                    SetPedestrianCrossingAllowed(segNodeConf.segmentId, true, (bool)flags.pedestrianCrossingAllowed);
                                }

                                return(true);
                            });
                        }
                        else
                        {
                            Log.Warning($"JunctionRestrictionsManager.LoadData(): Could not get segment end geometry for segment {segNodeConf.segmentId} @ start node");
                        }
                    }

                    if (segNodeConf.endNodeFlags != null)
                    {
                        SegmentEndGeometry endNodeSegGeo = SegmentGeometry.Get(segNodeConf.segmentId)?.GetEnd(false);
                        if (endNodeSegGeo != null)
                        {
                            Configuration.SegmentNodeFlags flags = segNodeConf.endNodeFlags;

                            Services.NetService.ProcessNode(endNodeSegGeo.NodeId(), delegate(ushort nId, ref NetNode node) {
                                if (flags.uturnAllowed != null && IsUturnAllowedConfigurable(segNodeConf.segmentId, false, ref node))
                                {
                                    SetUturnAllowed(segNodeConf.segmentId, false, (bool)flags.uturnAllowed);
                                }

                                if (flags.straightLaneChangingAllowed != null && IsLaneChangingAllowedWhenGoingStraightConfigurable(segNodeConf.segmentId, false, ref node))
                                {
                                    SetLaneChangingAllowedWhenGoingStraight(segNodeConf.segmentId, false, (bool)flags.straightLaneChangingAllowed);
                                }

                                if (flags.enterWhenBlockedAllowed != null && IsEnteringBlockedJunctionAllowedConfigurable(segNodeConf.segmentId, false, ref node))
                                {
                                    SetEnteringBlockedJunctionAllowed(segNodeConf.segmentId, false, (bool)flags.enterWhenBlockedAllowed);
                                }

                                if (flags.pedestrianCrossingAllowed != null && IsPedestrianCrossingAllowedConfigurable(segNodeConf.segmentId, false, ref node))
                                {
                                    SetPedestrianCrossingAllowed(segNodeConf.segmentId, false, (bool)flags.pedestrianCrossingAllowed);
                                }

                                if (flags.turnOnRedAllowed != null && IsNearTurnOnRedAllowedConfigurable(segNodeConf.segmentId, false, ref node))
                                {
                                    SetNearTurnOnRedAllowed(segNodeConf.segmentId, false, (bool)flags.turnOnRedAllowed);
                                }

                                if (flags.farTurnOnRedAllowed != null && IsFarTurnOnRedAllowedConfigurable(segNodeConf.segmentId, false, ref node))
                                {
                                    SetFarTurnOnRedAllowed(segNodeConf.segmentId, false, (bool)flags.farTurnOnRedAllowed);
                                }
                                return(true);
                            });
                        }
                        else
                        {
                            Log.Warning($"JunctionRestrictionsManager.LoadData(): Could not get segment end geometry for segment {segNodeConf.segmentId} @ end node");
                        }
                    }
                } catch (Exception e) {
                    // ignore, as it's probably corrupt save data. it'll be culled on next save
                    Log.Warning($"Error loading junction restrictions @ segment {segNodeConf.segmentId}: " + e.ToString());
                    success = false;
                }
            }
            return(success);
        }
示例#4
0
        internal void AddSegment(ushort segmentId, bool startNode, bool propagate)
        {
#if DEBUGGEO
            if (GlobalConfig.Instance.DebugSwitches[5])
            {
                Log._Debug($"NodeGeometry: Add segment {segmentId}, start? {startNode} @ node {NodeId}");
            }
#endif
            if (!IsValid())
            {
                //Log.Error($"NodeGeometry: Trying to add segment {segmentId} @ invalid node {NodeId}");
                Recalculate();
                return;
            }

            for (int i = 0; i < 8; ++i)
            {
                if (SegmentEndGeometries[i]?.SegmentId == segmentId)
                {
                    SegmentEndGeometries[i] = null;
                }
            }

            for (int i = 0; i < 8; ++i)
            {
                if (SegmentEndGeometries[i] == null)
                {
                    SegmentEndGeometries[i] = startNode ? SegmentGeometry.Get(segmentId).StartNodeGeometry : SegmentGeometry.Get(segmentId).EndNodeGeometry;
                    break;
                }
            }

            if (propagate)
            {
                NeedsRecalculation = true;
                try {
                    RecalculateSegments(segmentId);
                } finally {
                    NeedsRecalculation = false;
                }
            }
            Recalculate();
        }
 protected override void HandleValidSegment(SegmentGeometry geometry)
 {
 }
示例#6
0
 protected override void HandleValidSegment(SegmentGeometry geometry)
 {
     UpdateDefaults(geometry);
 }
示例#7
0
        private void _guiLaneChangeWindow(int num)
        {
            var info = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;

            List <object[]> laneList = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, info, SelectedNodeId);
            SegmentGeometry geometry = CustomRoadAI.GetSegmentGeometry(SelectedSegmentId);

            GUILayout.BeginHorizontal();

            for (var i = 0; i < laneList.Count; i++)
            {
                var flags = (NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[(uint)laneList[i][0]].m_flags;

                var style1 = new GUIStyle("button");
                var style2 = new GUIStyle("button")
                {
                    normal  = { textColor = new Color32(255, 0, 0, 255) },
                    hover   = { textColor = new Color32(255, 0, 0, 255) },
                    focused = { textColor = new Color32(255, 0, 0, 255) }
                };

                var laneStyle = new GUIStyle {
                    contentOffset = new Vector2(12f, 0f)
                };

                var laneTitleStyle = new GUIStyle {
                    contentOffset = new Vector2(36f, 2f),
                    normal        = { textColor = new Color(1f, 1f, 1f) }
                };

                GUILayout.BeginVertical(laneStyle);
                GUILayout.Label(Translation.GetString("Lane") + " " + (i + 1), laneTitleStyle);
                GUILayout.BeginVertical();
                GUILayout.BeginHorizontal();
                if (!Flags.applyLaneArrowFlags((uint)laneList[i][0]))
                {
                    Flags.removeLaneArrowFlags((uint)laneList[i][0]);
                }
                if (GUILayout.Button("←", ((flags & NetLane.Flags.Left) == NetLane.Flags.Left ? style1 : style2), GUILayout.Width(35), GUILayout.Height(25)))
                {
                    if (!Flags.toggleLaneArrowFlags((uint)laneList[i][0], Flags.LaneArrows.Left) && SelectedNodeId > 0)
                    {
                        MainTool.ShowTooltip(Translation.GetString("Lane_Arrow_Changer_Disabled"), Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId].m_position);
                    }
                }
                if (GUILayout.Button("↑", ((flags & NetLane.Flags.Forward) == NetLane.Flags.Forward ? style1 : style2), GUILayout.Width(25), GUILayout.Height(35)))
                {
                    if (!Flags.toggleLaneArrowFlags((uint)laneList[i][0], Flags.LaneArrows.Forward) && SelectedNodeId > 0)
                    {
                        MainTool.ShowTooltip(Translation.GetString("Lane_Arrow_Changer_Disabled"), Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId].m_position);
                    }
                }
                if (GUILayout.Button("→", ((flags & NetLane.Flags.Right) == NetLane.Flags.Right ? style1 : style2), GUILayout.Width(35), GUILayout.Height(25)))
                {
                    if (!Flags.toggleLaneArrowFlags((uint)laneList[i][0], Flags.LaneArrows.Right) && SelectedNodeId > 0)
                    {
                        MainTool.ShowTooltip(Translation.GetString("Lane_Arrow_Changer_Disabled"), Singleton <NetManager> .instance.m_nodes.m_buffer[SelectedNodeId].m_position);
                    }
                }
                GUILayout.EndHorizontal();
                GUILayout.EndVertical();
                GUILayout.EndVertical();
            }

            GUILayout.EndHorizontal();

            GUILayout.BeginVertical();

            bool startNode = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].m_startNode == SelectedNodeId;

            if (!geometry.AreHighwayRulesEnabled(startNode))
            {
                if (!geometry.IsOneWay())
                {
                    Flags.setUTurnAllowed(SelectedSegmentId, startNode, GUILayout.Toggle(Flags.getUTurnAllowed(SelectedSegmentId, startNode), Translation.GetString("Allow_u-turns") + " (BETA feature)", new GUILayoutOption[] { }));
                }
                if (geometry.HasOutgoingStraightSegment(SelectedNodeId))
                {
                    Flags.setStraightLaneChangingAllowed(SelectedSegmentId, startNode, GUILayout.Toggle(Flags.getStraightLaneChangingAllowed(SelectedSegmentId, startNode), Translation.GetString("Allow_lane_changing_for_vehicles_going_straight"), new GUILayoutOption[] { }));
                }
                Flags.setEnterWhenBlockedAllowed(SelectedSegmentId, startNode, GUILayout.Toggle(Flags.getEnterWhenBlockedAllowed(SelectedSegmentId, startNode), Translation.GetString("Allow_vehicles_to_enter_a_blocked_junction"), new GUILayoutOption[] { }));
            }

            GUILayout.EndVertical();
        }
 protected override void HandleInvalidSegment(SegmentGeometry geometry)
 {
     Flags.resetSegmentVehicleRestrictions(geometry.SegmentId);
     ClearCache(geometry.SegmentId);
 }
        internal void AddSegment(ushort segmentId, bool startNode, bool propagate)
        {
#if DEBUGGEO
            Log._Debug($"NodeGeometry: Add segment {segmentId}, start? {startNode} @ node {NodeId}");
#endif
            if (!IsValid())
            {
                //Log.Error($"NodeGeometry: Trying to add segment {segmentId} @ invalid node {NodeId}");
                Recalculate();
                return;
            }

            RemoveSegment(segmentId, false);             // fallback: remove segment

            for (int i = 0; i < 8; ++i)
            {
                if (SegmentEndGeometries[i] == null)
                {
                    SegmentEndGeometries[i] = startNode ? SegmentGeometry.Get(segmentId).StartNodeGeometry : SegmentGeometry.Get(segmentId).EndNodeGeometry;
                    break;
                }
            }

            if (propagate)
            {
                RecalculateSegments(segmentId);
            }
            Recalculate();
        }
        private bool drawSignHandles(ushort nodeId, bool viewOnly, bool handleClick, ref Vector3 camPos, out bool stateUpdated)
        {
            bool hovered = false;

            stateUpdated = false;

            if (viewOnly && !Options.junctionRestrictionsOverlay && MainTool.GetToolMode() != ToolMode.JunctionRestrictions)
            {
                return(false);
            }

            NetManager netManager = Singleton <NetManager> .instance;
            var        guiColor   = GUI.color;

            Vector3 nodePos = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].m_position;

            for (int i = 0; i < 8; ++i)
            {
                ushort segmentId = netManager.m_nodes.m_buffer[nodeId].GetSegment(i);
                if (segmentId == 0)
                {
                    continue;
                }

                SegmentGeometry geometry = SegmentGeometry.Get(segmentId);
                if (geometry == null)
                {
                    Log.Error($"JunctionRestrictionsTool.drawSignHandles: No geometry information available for segment {segmentId}");
                    continue;
                }
                bool startNode = geometry.StartNodeId() == nodeId;
                bool incoming  = geometry.IsIncoming(startNode);

                int numSignsPerRow = incoming ? 2 : 1;

                NetInfo segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info;

                ItemClass connectionClass = segmentInfo.GetConnectionClass();
                if (connectionClass.m_service != ItemClass.Service.Road)
                {
                    continue;                     // only for road junctions
                }
                // draw all junction restriction signs
                Vector3 segmentCenterPos = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_bounds.center;
                Vector3 yu = (segmentCenterPos - nodePos).normalized;
                Vector3 xu = Vector3.Cross(yu, new Vector3(0, 1f, 0)).normalized;
                float   f  = viewOnly ? 6f : 7f;              // reserved sign size in game coordinates

                Vector3 centerStart = nodePos + yu * (viewOnly ? 5f : 14f);
                Vector3 zero        = centerStart - 0.5f * (float)(numSignsPerRow - 1) * f * xu;        // "top left"
                if (viewOnly)
                {
                    if (Constants.ServiceFactory.SimulationService.LeftHandDrive)
                    {
                        zero -= xu * 8f;
                    }
                    else
                    {
                        zero += xu * 8f;
                    }
                }

                bool signHovered;
                int  x = 0;
                int  y = 0;

                // draw "lane-changing when going straight allowed" sign at (0; 0)
                bool allowed = JunctionRestrictionsManager.Instance.IsLaneChangingAllowedWhenGoingStraight(segmentId, startNode);
                if (incoming && (!viewOnly || allowed != Options.allowLaneChangesWhileGoingStraight))
                {
                    DrawSign(viewOnly, ref camPos, ref xu, ref yu, f, ref zero, x, y, ref guiColor, allowed ? TextureResources.LaneChangeAllowedTexture2D : TextureResources.LaneChangeForbiddenTexture2D, out signHovered);
                    if (signHovered && handleClick)
                    {
                        hovered = true;
                        if (MainTool.CheckClicked())
                        {
                            JunctionRestrictionsManager.Instance.ToggleLaneChangingAllowedWhenGoingStraight(segmentId, startNode);
                            stateUpdated = true;
                        }
                    }

                    if (viewOnly)
                    {
                        ++y;
                    }
                    else
                    {
                        ++x;
                    }
                }

                // draw "u-turns allowed" sign at (1; 0)
                allowed = JunctionRestrictionsManager.Instance.IsUturnAllowed(segmentId, startNode);
                if (incoming && (!viewOnly || allowed != Options.allowUTurns))
                {
                    DrawSign(viewOnly, ref camPos, ref xu, ref yu, f, ref zero, x, y, ref guiColor, allowed ? TextureResources.UturnAllowedTexture2D : TextureResources.UturnForbiddenTexture2D, out signHovered);
                    if (signHovered && handleClick)
                    {
                        hovered = true;

                        if (MainTool.CheckClicked())
                        {
                            if (!JunctionRestrictionsManager.Instance.ToggleUturnAllowed(segmentId, startNode))
                            {
                                // TODO MainTool.ShowTooltip(Translation.GetString("..."), Singleton<NetManager>.instance.m_nodes.m_buffer[nodeId].m_position);
                            }
                            else
                            {
                                stateUpdated = true;
                            }
                        }
                    }

                    ++y;
                    x = 0;
                }

                // draw "entering blocked junctions allowed" sign at (0; 1)
                allowed = JunctionRestrictionsManager.Instance.IsEnteringBlockedJunctionAllowed(segmentId, startNode);
                if (incoming && (!viewOnly || allowed != Options.allowEnterBlockedJunctions))
                {
                    DrawSign(viewOnly, ref camPos, ref xu, ref yu, f, ref zero, x, y, ref guiColor, allowed ? TextureResources.EnterBlockedJunctionAllowedTexture2D : TextureResources.EnterBlockedJunctionForbiddenTexture2D, out signHovered);
                    if (signHovered && handleClick)
                    {
                        hovered = true;

                        if (MainTool.CheckClicked())
                        {
                            JunctionRestrictionsManager.Instance.ToggleEnteringBlockedJunctionAllowed(segmentId, startNode);
                            stateUpdated = true;
                        }
                    }

                    if (viewOnly)
                    {
                        ++y;
                    }
                    else
                    {
                        ++x;
                    }
                }

                // draw "pedestrian crossing allowed" sign at (1; 1)
                allowed = JunctionRestrictionsManager.Instance.IsPedestrianCrossingAllowed(segmentId, startNode);
                if (!viewOnly || !allowed)
                {
                    DrawSign(viewOnly, ref camPos, ref xu, ref yu, f, ref zero, x, y, ref guiColor, allowed ? TextureResources.PedestrianCrossingAllowedTexture2D : TextureResources.PedestrianCrossingForbiddenTexture2D, out signHovered);
                    if (signHovered && handleClick)
                    {
                        hovered = true;

                        if (MainTool.CheckClicked())
                        {
                            JunctionRestrictionsManager.Instance.TogglePedestrianCrossingAllowed(segmentId, startNode);
                            stateUpdated = true;
                        }
                    }
                }
            }

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

            return(hovered);
        }
        internal void Recalculate(bool propagate)
        {
#if DEBUG
            //Log._Debug($"SegmentEndGeometry: Recalculate seg. {SegmentId} @ node {NodeId()}, propagate={propagate}");
#endif

            ushort nodeIdBeforeRecalc = LastKnownNodeId;
            Cleanup();

            if (!IsValid())
            {
                if (nodeIdBeforeRecalc != 0)
                {
                    NodeGeometry.Get(nodeIdBeforeRecalc).RemoveSegment(SegmentId, propagate);
                }

                return;
            }

            NetManager netManager = Singleton <NetManager> .instance;

            ushort nodeId = NodeId();
            LastKnownNodeId = nodeId;

            bool oneway;
            bool outgoingOneWay;
            SegmentGeometry.calculateOneWayAtNode(SegmentId, nodeId, out oneway, out outgoingOneWay);
            OutgoingOneWay = outgoingOneWay;
            if (oneway && !OutgoingOneWay)
            {
                IncomingOneWay = true;
            }
            OnlyHighways = true;

            //ItemClass connectionClass = netManager.m_segments.m_buffer[SegmentId].Info.GetConnectionClass();

            bool hasOtherSegments = false;
            for (var s = 0; s < 8; s++)
            {
                ushort otherSegmentId = netManager.m_nodes.m_buffer[nodeId].GetSegment(s);
                if (otherSegmentId == 0 || otherSegmentId == SegmentId || !SegmentGeometry.IsValid(otherSegmentId))
                {
                    continue;
                }

                /*ItemClass otherConnectionClass = Singleton<NetManager>.instance.m_segments.m_buffer[otherSegmentId].Info.GetConnectionClass();
                 * if (otherConnectionClass.m_service != connectionClass.m_service)
                 *      continue;*/
                hasOtherSegments = true;

                // determine geometry
                bool otherIsOneWay;
                bool otherIsOutgoingOneWay;
                SegmentGeometry.calculateOneWayAtNode(otherSegmentId, nodeId, out otherIsOneWay, out otherIsOutgoingOneWay);

                if (!(SegmentGeometry.calculateIsHighway(otherSegmentId) && otherIsOneWay))
                {
                    OnlyHighways = false;
                }

                if (IsRightSegment(SegmentId, otherSegmentId, nodeId))
                {
                    RightSegments[NumRightSegments++] = otherSegmentId;
                    if (!otherIsOutgoingOneWay)
                    {
                        IncomingRightSegments[NumIncomingRightSegments++] = otherSegmentId;
                        if (!otherIsOneWay)
                        {
                            OutgoingRightSegments[NumOutgoingRightSegments++] = otherSegmentId;
                        }
                    }
                    else
                    {
                        OutgoingRightSegments[NumOutgoingRightSegments++] = otherSegmentId;
                    }
                }
                else if (IsLeftSegment(SegmentId, otherSegmentId, nodeId))
                {
                    LeftSegments[NumLeftSegments++] = otherSegmentId;
                    if (!otherIsOutgoingOneWay)
                    {
                        IncomingLeftSegments[NumIncomingLeftSegments++] = otherSegmentId;
                        if (!otherIsOneWay)
                        {
                            OutgoingLeftSegments[NumOutgoingLeftSegments++] = otherSegmentId;
                        }
                    }
                    else
                    {
                        OutgoingLeftSegments[NumOutgoingLeftSegments++] = otherSegmentId;
                    }
                }
                else
                {
                    StraightSegments[NumStraightSegments++] = otherSegmentId;
                    if (!otherIsOutgoingOneWay)
                    {
                        IncomingStraightSegments[NumIncomingStraightSegments++] = otherSegmentId;
                        if (!otherIsOneWay)
                        {
                            OutgoingStraightSegments[NumOutgoingStraightSegments++] = otherSegmentId;
                        }
                    }
                    else
                    {
                        OutgoingStraightSegments[NumOutgoingStraightSegments++] = otherSegmentId;
                    }
                }

                // reset highway lane arrows
                Flags.removeHighwayLaneArrowFlagsAtSegment(otherSegmentId);                 // TODO refactor

                ConnectedSegments[NumConnectedSegments++] = otherSegmentId;
            }

            NumIncomingSegments = (byte)(NumIncomingLeftSegments + NumIncomingStraightSegments + NumIncomingRightSegments);
            NumOutgoingSegments = (byte)(NumOutgoingLeftSegments + NumOutgoingStraightSegments + NumOutgoingRightSegments);

            if (!hasOtherSegments)
            {
                OnlyHighways = false;
            }

            // propagate information to other segments
            if (nodeIdBeforeRecalc != nodeId)
            {
                if (nodeIdBeforeRecalc != 0)
                {
                    NodeGeometry.Get(nodeIdBeforeRecalc).RemoveSegment(SegmentId, propagate);
                }

                NodeGeometry.Get(nodeId).AddSegment(SegmentId, StartNode, propagate);
            }
        }
 public SegmentGeometry GetSegmentGeometry()
 {
     return(SegmentGeometry.Get(SegmentId));
 }
        /// <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;
                }
                Direction 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 Direction.Turn:
                default:
                    continue;

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

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

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

#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 Direction.Turn:
                    default:
                        continue;

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

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

                    case Direction.Right:
                        arrows |= Flags.LaneArrows.Right;
                        break;
                    }

#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

            Flags.setLaneArrowFlags(laneId, arrows, true);
        }
        public override void OnLoadData()
        {
            Log.Info("Loading Traffic Manager: PE Data");
            StateLoading = true;
            bool loadingSucceeded = true;

            try {
                Log.Info("Initializing flags");
                Flags.OnBeforeLoadData();
            } catch (Exception e) {
                Log.Error($"OnLoadData: Error while initializing Flags: {e.ToString()}");
                loadingSucceeded = false;
            }

            try {
                Log.Info("Initializing node geometries");
                NodeGeometry.OnBeforeLoadData();
            } catch (Exception e) {
                Log.Error($"OnLoadData: Error while initializing NodeGeometry: {e.ToString()}");
                loadingSucceeded = false;
            }

            try {
                Log.Info("Initializing segment geometries");
                SegmentGeometry.OnBeforeLoadData();
            } catch (Exception e) {
                Log.Error($"OnLoadData: Error while initializing SegmentGeometry: {e.ToString()}");
                loadingSucceeded = false;
            }

            foreach (ICustomManager manager in LoadingExtension.RegisteredManagers)
            {
                try {
                    Log.Info($"OnBeforeLoadData: {manager.GetType().Name}");
                    manager.OnBeforeLoadData();
                } catch (Exception e) {
                    Log.Error($"OnLoadData: Error while initializing {manager.GetType().Name}: {e.ToString()}");
                    loadingSucceeded = false;
                }
            }

            Log.Info("Initialization done. Loading mod data now.");

            try {
                byte[] data = _serializableData.LoadData(DataId);
                DeserializeData(data);
            } catch (Exception e) {
                Log.Error($"OnLoadData: Error while deserializing data: {e.ToString()}");
                loadingSucceeded = false;
            }

            // load options
            try {
                byte[] options = _serializableData.LoadData("TMPE_Options");
                if (options != null)
                {
                    if (!OptionsManager.Instance.LoadData(options))
                    {
                        loadingSucceeded = false;
                    }
                }
            } catch (Exception e) {
                Log.Error($"OnLoadData: Error while loading options: {e.ToString()}");
                loadingSucceeded = false;
            }

            if (loadingSucceeded)
            {
                Log.Info("OnLoadData completed successfully.");
            }
            else
            {
                Log.Info("An error occurred while loading.");
                //UIView.library.ShowModal<ExceptionPanel>("ExceptionPanel").SetMessage("An error occurred while loading", "Traffic Manager: President Edition detected an error while loading. Please do NOT save this game under the old filename, otherwise your timed traffic lights, custom lane arrows, etc. are in danger. Instead, please navigate to http://steamcommunity.com/sharedfiles/filedetails/?id=583429740 and follow the steps under 'In case problems arise'.", true);
            }

            StateLoading = false;

            foreach (ICustomManager manager in LoadingExtension.RegisteredManagers)
            {
                try {
                    Log.Info($"OnAfterLoadData: {manager.GetType().Name}");
                    manager.OnAfterLoadData();
                } catch (Exception e) {
                    Log.Error($"OnLoadData: Error while initializing {manager.GetType().Name}: {e.ToString()}");
                    loadingSucceeded = false;
                }
            }
        }
示例#15
0
        private void _guiLaneChangeWindow(int num)
        {
            var info = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info;

            IList <LanePos> laneList = Constants.ServiceFactory.NetService.GetSortedLanes(SelectedSegmentId, ref Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId], Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].m_startNode == SelectedNodeId, LaneArrowManager.LANE_TYPES, LaneArrowManager.VEHICLE_TYPES, true);
            SegmentGeometry geometry = SegmentGeometry.Get(SelectedSegmentId);

            if (geometry == null)
            {
                Log.Error($"LaneArrowTool._guiLaneChangeWindow: No geometry information available for segment {SelectedSegmentId}");
                return;
            }
            bool startNode = geometry.StartNodeId() == SelectedNodeId;

            GUILayout.BeginHorizontal();

            for (var i = 0; i < laneList.Count; i++)
            {
                var flags = (NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[laneList[i].laneId].m_flags;

                var style1 = new GUIStyle("button");
                var style2 = new GUIStyle("button")
                {
                    normal  = { textColor = new Color32(255, 0, 0, 255) },
                    hover   = { textColor = new Color32(255, 0, 0, 255) },
                    focused = { textColor = new Color32(255, 0, 0, 255) }
                };

                var laneStyle = new GUIStyle {
                    contentOffset = new Vector2(12f, 0f)
                };

                var laneTitleStyle = new GUIStyle {
                    contentOffset = new Vector2(36f, 2f),
                    normal        = { textColor = new Color(1f, 1f, 1f) }
                };

                GUILayout.BeginVertical(laneStyle);
                GUILayout.Label(Translation.GetString("Lane") + " " + (i + 1), laneTitleStyle);
                GUILayout.BeginVertical();
                GUILayout.BeginHorizontal();
                if (!Flags.applyLaneArrowFlags(laneList[i].laneId))
                {
                    Flags.removeLaneArrowFlags(laneList[i].laneId);
                }
                Flags.LaneArrowChangeResult res = Flags.LaneArrowChangeResult.Invalid;
                bool buttonClicked = false;
                if (GUILayout.Button("←", ((flags & NetLane.Flags.Left) == NetLane.Flags.Left ? style1 : style2), GUILayout.Width(35), GUILayout.Height(25)))
                {
                    buttonClicked = true;
                    LaneArrowManager.Instance.ToggleLaneArrows(laneList[i].laneId, startNode, Flags.LaneArrows.Left, out res);
                }
                if (GUILayout.Button("↑", ((flags & NetLane.Flags.Forward) == NetLane.Flags.Forward ? style1 : style2), GUILayout.Width(25), GUILayout.Height(35)))
                {
                    buttonClicked = true;
                    LaneArrowManager.Instance.ToggleLaneArrows(laneList[i].laneId, startNode, Flags.LaneArrows.Forward, out res);
                }
                if (GUILayout.Button("→", ((flags & NetLane.Flags.Right) == NetLane.Flags.Right ? style1 : style2), GUILayout.Width(35), GUILayout.Height(25)))
                {
                    buttonClicked = true;
                    LaneArrowManager.Instance.ToggleLaneArrows(laneList[i].laneId, startNode, Flags.LaneArrows.Right, out res);
                }

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

                    case Flags.LaneArrowChangeResult.HighwayArrows:
                        MainTool.ShowTooltip(Translation.GetString("Lane_Arrow_Changer_Disabled_Highway"));
                        break;

                    case Flags.LaneArrowChangeResult.LaneConnection:
                        MainTool.ShowTooltip(Translation.GetString("Lane_Arrow_Changer_Disabled_Connection"));
                        break;
                    }
                }

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

            GUILayout.EndHorizontal();
        }