Exemplo n.º 1
0
        Segments(NetSegment.Flags flags = NetSegment.Flags.Created)
        {
            var mgr = Singleton <Cities::NetManager> .instance;

            return(mgr.m_segments.m_buffer.Where(e =>
                                                 (e.m_flags & flags) != Cities::NetSegment.Flags.None
                                                 ));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Check segment flags contain at least one of the flags in <paramref name="flagMask"/>.
        /// </summary>
        ///
        /// <param name="segmentId">The id of the segment to inspect.</param>
        /// <param name="flagMask">The flags to test.</param>
        /// <param name="expectedResult">If specified, ensure only the expected flags are found.</param>
        ///
        /// <returns>Returns <c>true</c> if the test passes, otherwise <c>false</c>.</returns>
        public bool CheckSegmentFlags(ushort segmentId,
                                      NetSegment.Flags flagMask,
                                      NetSegment.Flags?expectedResult = null)
        {
            NetSegment.Flags result = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_flags & flagMask;

            return(expectedResult == null ? result != 0 : result == expectedResult);
        }
Exemplo n.º 3
0
        public void Calculate()
        {
            //Capture the default values.
            DefaultFlags        = Segment.m_flags;
            PedestrianLaneCount = Info.CountPedestrianLanes();

            Refresh();
        }
        public bool CheckSegmentFlags(ushort segmentId, NetSegment.Flags flagMask, NetSegment.Flags?expectedResult = null)
        {
            bool ret = false;

            ProcessSegment(segmentId, delegate(ushort sId, ref NetSegment segment) {
                ret = LogicUtil.CheckFlags((uint)segment.m_flags, (uint)flagMask, (uint?)expectedResult);
                return(true);
            });
            return(ret);
        }
Exemplo n.º 5
0
 public static bool CheckFlags(this NetInfo.Segment segmentInfo, NetSegment.Flags flags, bool turnAround)
 {
     if (!turnAround)
     {
         return(flags.CheckFlags(segmentInfo.m_forwardRequired, segmentInfo.m_forwardForbidden));
     }
     else
     {
         return(flags.CheckFlags(segmentInfo.m_backwardRequired, segmentInfo.m_backwardForbidden));
     }
 }
Exemplo n.º 6
0
        public void CustomClickNodeButton(ushort nodeId, ref NetNode data, int index)
        {
            if ((data.m_flags & NetNode.Flags.Junction) == NetNode.Flags.None ||
                Singleton <InfoManager> .instance.CurrentMode != InfoManager.InfoMode.TrafficRoutes ||
                Singleton <InfoManager> .instance.CurrentSubMode !=
                InfoManager.SubInfoMode.WaterPower)
            {
                return;
            }

            if (index == -1)
            {
                /*data.m_flags ^= NetNode.Flags.TrafficLights;
                 *  data.m_flags |= NetNode.Flags.CustomTrafficLights;*/

                // NON-STOCK CODE START
                ToggleTrafficLightsTool toggleTool = (ToggleTrafficLightsTool)ModUI
                                                     .GetTrafficManagerTool(true)
                                                     .GetSubTool(ToolMode.SwitchTrafficLight);
                toggleTool.ToggleTrafficLight(nodeId, ref data, false);

                // NON-STOCK CODE END
                UpdateNodeFlags(nodeId, ref data);
                Singleton <NetManager> .instance.m_yieldLights.Disable();
            }
            else if (index >= 1 &&
                     index <= 8 &&
                     (data.m_flags & (NetNode.Flags.TrafficLights
                                      | NetNode.Flags.OneWayIn)) == NetNode.Flags.None)
            {
                ushort segmentId = data.GetSegment(index - 1);
                if (segmentId == 0)
                {
                    return;
                }

                NetManager netManager = Singleton <NetManager> .instance;
                NetInfo    info       = netManager.m_segments.m_buffer[segmentId].Info;
                if ((info.m_vehicleTypes & (VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Tram)) ==
                    VehicleInfo.VehicleType.None)
                {
                    return;
                }

                bool             flag  = netManager.m_segments.m_buffer[segmentId].m_startNode == nodeId;
                NetSegment.Flags flags = (!flag) ? NetSegment.Flags.YieldEnd : NetSegment.Flags.YieldStart;
                netManager.m_segments.m_buffer[segmentId].m_flags ^= flags;
                netManager.m_segments.m_buffer[segmentId].UpdateLanes(segmentId, true);
                Singleton <NetManager> .instance.m_yieldLights.Disable();
            }
        }
        public static void UpdateSegmentStopFlags(this RoadBridgeAI roadbridge, ushort segmentID, ref NetSegment data)
        {
            Log.Debug($"updateflags on {segmentID}");
            roadbridge.UpdateSegmentFlags(segmentID, ref data);
            NetSegment.Flags flags = data.m_flags & ~(NetSegment.Flags.StopRight | NetSegment.Flags.StopLeft | NetSegment.Flags.StopRight2 | NetSegment.Flags.StopLeft2);
            if (roadbridge.m_info.m_lanes == null)
            {
                return;
            }
            NetManager instance = Singleton <NetManager> .instance;
            bool       inverted = (data.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None;
            uint       lane     = instance.m_segments.m_buffer[(int)segmentID].m_lanes;
            int        i        = 0;

            while (i < roadbridge.m_info.m_lanes.Length && lane != 0U)
            {
                NetLane.Flags laneFlags = (NetLane.Flags)instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].m_flags;
                if ((laneFlags & NetLane.Flags.Stop) != NetLane.Flags.None)
                {
                    if (roadbridge.m_info.m_lanes[i].m_position < 0f != inverted)
                    {
                        flags |= NetSegment.Flags.StopLeft;
                    }
                    else
                    {
                        flags |= NetSegment.Flags.StopRight;
                    }
                }
                else if ((laneFlags & NetLane.Flags.Stop2) != NetLane.Flags.None)
                {
                    if (roadbridge.m_info.m_lanes[i].m_position < 0f != inverted)
                    {
                        flags |= NetSegment.Flags.StopLeft2;
                    }
                    else
                    {
                        flags |= NetSegment.Flags.StopRight2;
                    }
                }
                lane = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].m_nextLane;
                i++;
            }
            data.m_flags = flags;
            Log.Debug($"flags {flags}");
        }
        public static void UpdateSegmentStopFlags(this RoadBridgeAI roadbridge, ushort segmentID, ref NetSegment data)
        {
            roadbridge.UpdateSegmentFlags(segmentID, ref data);
            var oldflags = data.m_flags;

            NetSegment.Flags flags = data.m_flags & ~(NetSegment.Flags.StopRight | NetSegment.Flags.StopLeft | NetSegment.Flags.StopRight2 | NetSegment.Flags.StopLeft2);
            if (roadbridge.m_info.m_lanes != null)
            {
                NetManager instance = Singleton <NetManager> .instance;
                bool       flag     = (data.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None;
                uint       num      = instance.m_segments.m_buffer[(int)segmentID].m_lanes;
                int        num2     = 0;
                while (num2 < roadbridge.m_info.m_lanes.Length && num != 0U)
                {
                    NetLane.Flags flags2 = (NetLane.Flags)instance.m_lanes.m_buffer[(int)((UIntPtr)num)].m_flags;
                    if ((flags2 & NetLane.Flags.Stop) != NetLane.Flags.None)
                    {
                        if (roadbridge.m_info.m_lanes[num2].m_position < 0f != flag)
                        {
                            flags |= NetSegment.Flags.StopLeft;
                        }
                        else
                        {
                            flags |= NetSegment.Flags.StopRight;
                        }
                    }
                    if ((flags2 & NetLane.Flags.Stop2) != NetLane.Flags.None)
                    {
                        if (roadbridge.m_info.m_lanes[num2].m_position < 0f != flag)
                        {
                            flags |= NetSegment.Flags.StopLeft2;
                        }
                        else
                        {
                            flags |= NetSegment.Flags.StopRight2;
                        }
                    }
                    num = instance.m_lanes.m_buffer[(int)((UIntPtr)num)].m_nextLane;
                    num2++;
                }
            }
            Log.Debug($"oldflags {oldflags} newflags {flags} on segment {segmentID} bridge");
            data.m_flags = flags;
        }
Exemplo n.º 9
0
        public static List <ushort> GetSegmentOrderRoad(ushort segmentID, bool requireSameDirection, bool requireSameSizeAndType, bool localAdjust, out bool startRef, out bool endRef, out ushort[] nodes)
        {
            NetSegment.Flags flags = NetManager.instance.m_segments.m_buffer[segmentID].m_flags;
            var nodeList           = new List <ushort>();

            if (segmentID != 0 && flags != NetSegment.Flags.None)
            {
                List <ushort> path = CalculatePathNet(segmentID, false, requireSameDirection, requireSameSizeAndType, out nodes);
                path.Add(segmentID);

                ushort startNode0   = NetManager.instance.m_segments.m_buffer[path[0]].m_startNode;
                ushort endNode0     = NetManager.instance.m_segments.m_buffer[path[0]].m_endNode;
                ushort startNodeRef = NetManager.instance.m_segments.m_buffer[segmentID].m_startNode;
                ushort endNodeRef   = NetManager.instance.m_segments.m_buffer[segmentID].m_endNode;

                bool circular = (path.Count > 2 && (startNode0 == endNodeRef || startNode0 == startNodeRef || endNode0 == endNodeRef || endNode0 == startNodeRef)) ||
                                (path.Count == 2 && (startNode0 == endNodeRef || startNode0 == startNodeRef) && (endNode0 == endNodeRef || endNode0 == startNodeRef));

                if (circular)
                {
                    LogUtils.DoLog("Circular!");
                    ushort refer    = path.Min();
                    int    referIdx = path.IndexOf(refer);
                    if (referIdx != 0)
                    {
                        path = path.GetRange(referIdx, path.Count - referIdx).Union(path.Take(referIdx)).ToList();
                    }
                }
                else
                {
                    path.AddRange(CalculatePathNet(segmentID, true, requireSameDirection, requireSameSizeAndType, out _));
                }
                //doLog($"[s={strict}]path = [{string.Join(",", path.Select(x => x.ToString()).ToArray())}]");
                GetEdgeNodes(ref path, out startRef, out endRef, localAdjust);
                return(path);
            }
            nodes    = new ushort[0];
            startRef = false;
            endRef   = false;
            return(null);
        }
Exemplo n.º 10
0
        private void ExportWays()
        {
            NetManager netManager = Singleton <NetManager> .instance;

            NetSegment[] netSegments = netManager.m_segments.m_buffer;
            for (int segmentId = 0; segmentId < netSegments.Length; segmentId++)
            {
                NetSegment       netSegment   = netSegments[segmentId];
                NetSegment.Flags segmentFlags = netSegment.m_flags;

                if (segmentFlags.IsFlagSet(NetSegment.Flags.Created))
                {
                    OSMWay generatedWay = CreateWay(unindexedWayOffset++, netSegment, (ushort)segmentId);

                    if (generatedWay != null)
                    {
                        osmWays.Add(generatedWay);
                    }
                }
            }
        }
Exemplo n.º 11
0
 public bool CheckFlags(NetSegment.Flags flags) => flags.CheckFlags(Required, Forbidden);
Exemplo n.º 12
0
        private bool RayCastSegmentAndNode(NetInfo connectedType, Segment3 ray, float snapElevation, bool nameOnly, ItemClass.Service service, ItemClass.Service service2, ItemClass.SubService subService, ItemClass.SubService subService2, ItemClass.Layer itemLayers, ItemClass.Layer itemLayers2, NetNode.Flags ignoreNodeFlags, NetSegment.Flags ignoreSegmentFlags, out Vector3 hit, out ushort nodeIndex, out ushort segmentIndex)
        {
            var bounds = new Bounds(new Vector3(0f, 512f, 0f), new Vector3(17280f, 1152f, 17280f));

            if (ray.Clip(bounds))
            {
                Vector3 vector = ray.b - ray.a;
                var     num    = (int)((ray.a.x / 64f) + 135f);
                var     num2   = (int)((ray.a.z / 64f) + 135f);
                var     num3   = (int)((ray.b.x / 64f) + 135f);
                var     num4   = (int)((ray.b.z / 64f) + 135f);
                var     num5   = Mathf.Abs(vector.x);
                var     num6   = Mathf.Abs(vector.z);
                int     num7;
                int     num8;
                if (num5 >= num6)
                {
                    num7 = ((vector.x <= 0f) ? -1 : 1);
                    num8 = 0;
                    if (num5 > 0.001f)
                    {
                        vector *= 64f / num5;
                    }
                }
                else
                {
                    num7 = 0;
                    num8 = ((vector.z <= 0f) ? -1 : 1);
                    if (num6 > 0.001f)
                    {
                        vector *= 64f / num6;
                    }
                }
                var     num9    = 2f;
                var     num10   = 16f;
                var     num11   = 2f;
                var     num12   = 16f;
                ushort  num13   = 0;
                ushort  num14   = 0;
                ushort  num15   = 0;
                Vector3 vector2 = ray.a;
                Vector3 vector3 = ray.a;
                var     num16   = num;
                var     num17   = num2;
                do
                {
                    Vector3 vector4 = vector3 + vector;
                    int     num18;
                    int     num19;
                    int     num20;
                    int     num21;
                    if (num7 != 0)
                    {
                        if ((num16 == num && num7 > 0) || (num16 == num3 && num7 < 0))
                        {
                            num18 = Mathf.Max((int)(((vector4.x - 64f) / 64f) + 135f), 0);
                        }
                        else
                        {
                            num18 = Mathf.Max(num16, 0);
                        }
                        if ((num16 == num && num7 < 0) || (num16 == num3 && num7 > 0))
                        {
                            num19 = Mathf.Min((int)(((vector4.x + 64f) / 64f) + 135f), 269);
                        }
                        else
                        {
                            num19 = Mathf.Min(num16, 269);
                        }
                        num20 = Mathf.Max((int)(((Mathf.Min(vector2.z, vector4.z) - 64f) / 64f) + 135f), 0);
                        num21 = Mathf.Min((int)(((Mathf.Max(vector2.z, vector4.z) + 64f) / 64f) + 135f), 269);
                    }
                    else
                    {
                        if ((num17 == num2 && num8 > 0) || (num17 == num4 && num8 < 0))
                        {
                            num20 = Mathf.Max((int)(((vector4.z - 64f) / 64f) + 135f), 0);
                        }
                        else
                        {
                            num20 = Mathf.Max(num17, 0);
                        }
                        if ((num17 == num2 && num8 < 0) || (num17 == num4 && num8 > 0))
                        {
                            num21 = Mathf.Min((int)(((vector4.z + 64f) / 64f) + 135f), 269);
                        }
                        else
                        {
                            num21 = Mathf.Min(num17, 269);
                        }
                        num18 = Mathf.Max((int)(((Mathf.Min(vector2.x, vector4.x) - 64f) / 64f) + 135f), 0);
                        num19 = Mathf.Min((int)(((Mathf.Max(vector2.x, vector4.x) + 64f) / 64f) + 135f), 269);
                    }
                    for (var i = num20; i <= num21; i++)
                    {
                        for (var j = num18; j <= num19; j++)
                        {
                            var num22 = Singleton <NetManager> .instance.m_nodeGrid[(i * 270) + j];
                            var num23 = 0;
                            while (num22 != 0)
                            {
                                NetNode.Flags flags           = NodeBuffer[num22].m_flags;
                                NetInfo       info            = NodeBuffer[num22].Info;
                                ItemClass     connectionClass = info.GetConnectionClass();
                                if ((((service == ItemClass.Service.None || connectionClass.m_service == service) && (subService == ItemClass.SubService.None || connectionClass.m_subService == subService) && (itemLayers == ItemClass.Layer.None || (connectionClass.m_layer & itemLayers) != ItemClass.Layer.None)) || (info.m_intersectClass != null && (service == ItemClass.Service.None || info.m_intersectClass.m_service == service) && (subService == ItemClass.SubService.None || info.m_intersectClass.m_subService == subService) && (itemLayers == ItemClass.Layer.None || (info.m_intersectClass.m_layer & itemLayers) != ItemClass.Layer.None)) || (info.m_netAI.CanIntersect(connectedType) && connectionClass.m_service == service2 && (subService2 == ItemClass.SubService.None || connectionClass.m_subService == subService2) && (itemLayers2 == ItemClass.Layer.None || (connectionClass.m_layer & itemLayers2) != ItemClass.Layer.None))) && (flags & ignoreNodeFlags) == NetNode.Flags.None && (connectedType == null || (info.m_netAI.CanConnect(connectedType) && connectedType.m_netAI.CanConnect(info))))
                                {
                                    var flag = false;
                                    if ((flags & (NetNode.Flags.Middle | NetNode.Flags.Untouchable)) == (NetNode.Flags.Middle | NetNode.Flags.Untouchable) && NodeBuffer[num22].CountSegments(NetSegment.Flags.Untouchable, 0) >= 2)
                                    {
                                        flag = true;
                                    }
                                    if (!flag && NodeBuffer[num22].RayCast(ray, snapElevation, out var num24, out var num25) && (num25 < num12 || (num25 == num12 && num24 < num11)))
                                    {
                                        num11 = num24;
                                        num12 = num25;
                                        num14 = num22;
                                    }
                                }
                                num22 = NodeBuffer[num22].m_nextGridNode;
                                if (++num23 > 32768)
                                {
                                    CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                                    break;
                                }
                            }
                        }
                    }
                    for (var k = num20; k <= num21; k++)
                    {
                        for (var l = num18; l <= num19; l++)
                        {
                            var num26 = Singleton <NetManager> .instance.m_segmentGrid[(k * 270) + l];
                            var num27 = 0;
                            while (num26 != 0)
                            {
                                NetSegment.Flags flags2           = SegmentBuffer[num26].m_flags;
                                NetInfo          info2            = SegmentBuffer[num26].Info;
                                ItemClass        connectionClass2 = info2.GetConnectionClass();
                                if (((service == ItemClass.Service.None || connectionClass2.m_service == service) && (subService == ItemClass.SubService.None || connectionClass2.m_subService == subService) && (itemLayers == ItemClass.Layer.None || (connectionClass2.m_layer & itemLayers) != ItemClass.Layer.None || nameOnly)) || (info2.m_intersectClass != null && (service == ItemClass.Service.None || info2.m_intersectClass.m_service == service) && (subService == ItemClass.SubService.None || info2.m_intersectClass.m_subService == subService) && (itemLayers == ItemClass.Layer.None || (info2.m_intersectClass.m_layer & itemLayers) != ItemClass.Layer.None || nameOnly)) || (info2.m_netAI.CanIntersect(connectedType) && connectionClass2.m_service == service2 && (subService2 == ItemClass.SubService.None || connectionClass2.m_subService == subService2) && (itemLayers2 == ItemClass.Layer.None || (connectionClass2.m_layer & itemLayers2) != ItemClass.Layer.None || nameOnly)))
                                {
                                    var flag2 = (flags2 & ignoreSegmentFlags) != NetSegment.Flags.None && !nameOnly;
                                    if ((flags2 & ignoreSegmentFlags) == NetSegment.Flags.None && (connectedType == null || (info2.m_netAI.CanConnect(connectedType) && connectedType.m_netAI.CanConnect(info2))) && SegmentBuffer[num26].RayCast(num26, ray, snapElevation, nameOnly, out var num28, out var num29) && (num29 < num10 || (num29 == num10 && num28 < num9)))
                                    {
                                        var     startNode = SegmentBuffer[num26].m_startNode;
                                        var     endNode   = SegmentBuffer[num26].m_endNode;
                                        Vector3 position  = NodeBuffer[startNode].m_position;
                                        Vector3 position2 = NodeBuffer[endNode].m_position;
                                        var     num30     = NodeBuffer[startNode].Info.GetMinNodeDistance();
                                        var     num31     = NodeBuffer[endNode].Info.GetMinNodeDistance();
                                        num10 = num29;
                                        num9  = num28;
                                        Vector3       a      = ray.a + ((ray.b - ray.a) * num28);
                                        NetNode.Flags flags3 = NodeBuffer[startNode].m_flags;
                                        if ((flags3 & NetNode.Flags.End) != NetNode.Flags.None)
                                        {
                                            flags3 &= ~NetNode.Flags.Moveable;
                                        }
                                        NetNode.Flags flags4 = NodeBuffer[endNode].m_flags;
                                        if ((flags4 & NetNode.Flags.End) != NetNode.Flags.None)
                                        {
                                            flags4 &= ~NetNode.Flags.Moveable;
                                        }
                                        if (flag2)
                                        {
                                            num30 = 1000f;
                                            num31 = 1000f;
                                        }
                                        var flag3 = (flags3 & (NetNode.Flags.Moveable | ignoreNodeFlags)) == NetNode.Flags.None;
                                        var flag4 = (flags4 & (NetNode.Flags.Moveable | ignoreNodeFlags)) == NetNode.Flags.None;
                                        var num32 = VectorUtils.LengthSqrXZ(a - position) / (num30 * num30);
                                        var num33 = VectorUtils.LengthSqrXZ(a - position2) / (num31 * num31);
                                        if (flag3 && num32 < 1f && (!flag4 || num32 < num33) && !nameOnly)
                                        {
                                            num13 = startNode;
                                            if (!flag2)
                                            {
                                                num15 = num26;
                                            }
                                        }
                                        else if (flag4 && num33 < 1f && !nameOnly)
                                        {
                                            num13 = endNode;
                                            if (!flag2)
                                            {
                                                num15 = num26;
                                            }
                                        }
                                        else if (!flag2)
                                        {
                                            num13 = 0;
                                            num15 = num26;
                                        }
                                    }
                                }
                                num26 = SegmentBuffer[num26].m_nextGridSegment;
                                if (++num27 > 36864)
                                {
                                    CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace);

                                    break;
                                }
                            }
                        }
                    }
                    vector2 = vector3;
                    vector3 = vector4;
                    num16  += num7;
                    num17  += num8;
                }while ((num16 <= num3 || num7 <= 0) && (num16 >= num3 || num7 >= 0) && (num17 <= num4 || num8 <= 0) && (num17 >= num4 || num8 >= 0));
                if (num12 < num10 || (num12 == num10 && num11 < num9))
                {
                    num9  = num11;
                    num13 = num14;
                }
                if (num9 != 2f)
                {
                    hit          = ray.Position(num9);
                    nodeIndex    = num13;
                    segmentIndex = num15;
                    return(true);
                }
            }
            hit          = Vector3.zero;
            nodeIndex    = 0;
            segmentIndex = 0;
            return(false);
        }
Exemplo n.º 13
0
 public static bool CheckFlags(this NetSegment.Flags value, NetSegment.Flags required, NetSegment.Flags forbidden = 0) => (value & (required | forbidden)) == required;
 public static bool CheckFlags(this NetSegment.Flags value, NetSegment.Flags required, NetSegment.Flags forbidden)
 {
     return((value & (required | forbidden)) == required);
 }
Exemplo n.º 15
0
        /// <summary>
        /// Redraw the text to be drawn later with a mesh. Use sparingly, as
        /// this is an expensive task.
        /// </summary>
        private void RenderText()
        {
            DistrictManager districtManager = DistrictManager.instance;
            NetManager      netManager      = NetManager.instance;

            if (districtManager.m_properties.m_areaNameFont != null)
            {
                UIFontManager.Invalidate(districtManager.m_properties.m_areaNameFont);

                foreach (RouteContainer route in RouteManager.Instance().m_routeDict.Values)
                {
                    if (route.m_segmentId != 0)
                    {
                        string routeStr = route.m_route;

                        if (routeStr != null)
                        {
                            NetSegment       netSegment   = netManager.m_segments.m_buffer[route.m_segmentId];
                            NetSegment.Flags segmentFlags = netSegment.m_flags;

                            if (segmentFlags.IsFlagSet(NetSegment.Flags.Created))
                            {
                                //Load a route shield type ( generic motorway shield should be default value )
                                RouteShieldInfo shieldInfo = RouteShieldConfig.Instance().GetRouteShieldInfo(route.m_routePrefix);

                                NetNode startNode         = netManager.m_nodes.m_buffer[netSegment.m_startNode];
                                NetNode endNode           = netManager.m_nodes.m_buffer[netSegment.m_endNode];
                                Vector3 startNodePosition = startNode.m_position;

                                if (!SpriteUtils.m_textureStore.ContainsKey(shieldInfo.textureName))
                                {
                                    LoggerUtils.Log("WTF, No texture found for route shield" + shieldInfo.textureName);
                                }
                                Material mat = SpriteUtils.m_textureStore[shieldInfo.textureName];
                                route.m_shieldObject.GetComponent <Renderer>().material = mat;

                                //TODO: Make mesh size dependent on text size
                                route.m_shieldMesh.mesh = MeshUtils.CreateRectMesh(mat.mainTexture.width, mat.mainTexture.height);
                                route.m_shieldMesh.transform.position = startNodePosition;

                                route.m_shieldMesh.transform.LookAt(endNode.m_position, Vector3.up);
                                route.m_shieldMesh.transform.Rotate(90f, 0f, 90f);

                                //TODO: Bind the elevation of the mesh to the text z offset
                                route.m_shieldMesh.transform.position  += (Vector3.up * (0.5f));
                                route.m_shieldMesh.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
                                route.m_shieldObject.GetComponent <Renderer>().sortingOrder = 1000;

                                route.m_numMesh.anchor = TextAnchor.MiddleCenter;

                                route.m_numMesh.font = FontUtils.m_fontStore.ContainsKey("Highway Gothic") ? FontUtils.m_fontStore["Highway Gothic"] : districtManager.m_properties.m_areaNameFont.baseFont;
                                route.m_numMesh.GetComponent <Renderer>().material = route.m_numMesh.font.material;
                                if (ShaderUtils.m_shaderStore.ContainsKey("font"))
                                {
                                    route.m_numMesh.GetComponent <Renderer>().material.shader = ShaderUtils.m_shaderStore["font"];
                                }
                                else
                                {
                                    route.m_numMesh.GetComponent <Renderer>().material.shader = ShaderUtils.m_shaderStore["fallback"];
                                }
                                //TODO: Tie the font size to the font size option
                                route.m_numMesh.fontSize           = 50;
                                route.m_numMesh.transform.position = startNode.m_position;
                                route.m_numMesh.transform.parent   = route.m_shieldObject.transform;

                                route.m_numMesh.transform.LookAt(endNode.m_position, Vector3.up);
                                route.m_numMesh.transform.Rotate(90f, 0f, 90f);

                                route.m_numMesh.transform.position = route.m_shieldObject.GetComponent <Renderer>().bounds.center;
                                //Just a hack, to make sure the text actually shows up above the shield
                                route.m_numMesh.offsetZ = 0.001f;
                                //TODO: Definitely get a map of the texture to the required text offsets
                                route.m_numMesh.transform.localPosition += (Vector3.up * shieldInfo.upOffset);
                                route.m_numMesh.transform.localPosition += (Vector3.left * shieldInfo.leftOffset);
                                //TODO: Figure out a better ratio for route markers
                                route.m_numMesh.transform.localScale = new Vector3(shieldInfo.textScale, shieldInfo.textScale, shieldInfo.textScale);
                                route.m_numMesh.GetComponent <Renderer>().material.color = shieldInfo.textColor;
                                route.m_numMesh.text = route.m_route.ToString();
                            }
                        }
                    }
                }

                foreach (SignContainer sign in RouteManager.Instance().m_signList)
                {
                    Vector3      position     = new Vector3(sign.x, sign.y, sign.z);
                    string       signPropType = (sign.m_exitNum == null || !m_signPropDict.ContainsKey(sign.m_exitNum)) ? "hwysign" : sign.m_exitNum;
                    SignPropInfo signPropInfo = SignPropConfig.signPropInfoDict[signPropType];
                    int          numSignProps = signPropInfo.isDoubleGantry ? 2 : 1;

                    sign.m_sign.GetComponent <Renderer>().material = m_signPropDict[signPropType].m_material;
                    //TODO: Make mesh size dependent on text size
                    sign.m_sign.mesh = m_signPropDict[signPropType].m_mesh;
                    sign.m_sign.transform.position = position;

                    if (sign.m_routePrefix != null)
                    {
                        RouteShieldInfo shieldInfo = RouteShieldConfig.Instance().GetRouteShieldInfo(sign.m_routePrefix);
                        Material        mat        = SpriteUtils.m_textureStore[shieldInfo.textureName];
                        sign.m_shieldObject.GetComponent <Renderer>().material = mat;

                        //TODO: Make mesh size dependent on text size
                        sign.m_shieldMesh.mesh = MeshUtils.CreateRectMesh(mat.mainTexture.width, mat.mainTexture.height);
                        sign.m_shieldMesh.transform.position = position;

                        //TODO: Bind the elevation of the mesh to the text z offset
                        sign.m_shieldMesh.transform.position  += (Vector3.up * (0.5f));
                        sign.m_shieldMesh.transform.localScale = signPropInfo.shieldScale;
                        sign.m_shieldObject.GetComponent <Renderer>().sortingOrder = 1000;

                        sign.m_numMesh.anchor = TextAnchor.MiddleCenter;
                        sign.m_numMesh.font   = FontUtils.m_fontStore.ContainsKey("Highway Gothic") ? FontUtils.m_fontStore["Highway Gothic"] : districtManager.m_properties.m_areaNameFont.baseFont;
                        sign.m_numMesh.GetComponent <Renderer>().material = sign.m_numMesh.font.material;
                        if (ShaderUtils.m_shaderStore.ContainsKey("font"))
                        {
                            sign.m_numMesh.GetComponent <Renderer>().material.shader = ShaderUtils.m_shaderStore["font"];
                        }
                        else
                        {
                            sign.m_numMesh.GetComponent <Renderer>().material.shader = ShaderUtils.m_shaderStore["fallback"];
                        }
                        //TODO: Tie the font size to the font size option
                        sign.m_numMesh.fontSize           = 50;
                        sign.m_numMesh.transform.position = position;
                        sign.m_numMesh.transform.parent   = sign.m_shieldObject.transform;

                        sign.m_numMesh.transform.position = sign.m_shieldObject.GetComponent <Renderer>().bounds.center;
                        //Just a hack, to make sure the text actually shows up above the shield
                        sign.m_numMesh.offsetZ = 0.01f;
                        //TODO: Definitely get a map of the texture to the required text offsets ds
                        sign.m_numMesh.transform.localPosition += (Vector3.up * shieldInfo.upOffset);
                        sign.m_numMesh.transform.localPosition += (Vector3.left * shieldInfo.leftOffset);
                        //TODO: Figure out a better ratio for route markers
                        sign.m_numMesh.transform.localScale = new Vector3(shieldInfo.textScale, shieldInfo.textScale, shieldInfo.textScale);
                        sign.m_numMesh.GetComponent <Renderer>().material.color = shieldInfo.textColor;
                        sign.m_numMesh.text = sign.m_route.ToString();
                        sign.m_numMesh.TE

                        sign.m_shieldMesh.transform.parent = sign.m_sign.transform;

                        sign.m_shieldMesh.transform.localPosition = signPropInfo.shieldOffset;
                    }


                    string[] destinationStrings = sign.m_destination.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);

                    for (int i = 0; i < numSignProps; i++)
                    {
                        sign.m_destinationMesh[i].anchor = TextAnchor.MiddleCenter;
                        sign.m_destinationMesh[i].font   = FontUtils.m_fontStore.ContainsKey(signPropInfo.fontType) ? FontUtils.m_fontStore[signPropInfo.fontType] : districtManager.m_properties.m_areaNameFont.baseFont;
                        sign.m_destinationMesh[i].font.material.SetColor("Text Color", Color.white);

                        if (ShaderUtils.m_shaderStore.ContainsKey("font"))
                        {
                            sign.m_destinationMesh[i].font.material.shader = ShaderUtils.m_shaderStore["font"];
                        }
                        else
                        {
                            sign.m_destinationMesh[i].font.material.shader = ShaderUtils.m_shaderStore["fallback"];
                        }

                        sign.m_destinationMesh[i].GetComponent <Renderer>().material = sign.m_destinationMesh[i].font.material;
                        //TODO: Tie the font size to the font size option
                        sign.m_destinationMesh[i].fontSize           = 50;
                        sign.m_destinationMesh[i].transform.position = position;
                        sign.m_destinationMesh[i].transform.parent   = sign.m_sign.transform;

                        sign.m_destinationMesh[i].transform.position = position;
                        //Just a hack, to make sure the text actually shows up above the shield
                        sign.m_destinationMesh[i].offsetZ = 0.001f;
                        //TODO: Definitely get a map of the texture to the required text offsets
                        //TODO: Figure out a better ratio for route markers
                        sign.m_destinationMesh[i].transform.localScale = signPropInfo.textScale;
                        sign.m_destinationMesh[i].text = signPropInfo.isDoubleGantry ? destinationStrings[i] : sign.m_destination;

                        sign.m_destinationMesh[i].transform.localPosition = sign.m_routePrefix == null ? signPropInfo.textOffsetNoSign[i] : signPropInfo.textOffsetSign[i];
                    }
                }

                foreach (DynamicSignContainer sign in RouteManager.Instance().m_dynamicSignList)
                {
                    Vector3 position = new Vector3(sign.x, sign.y, sign.z);

                    sign.m_sign.GetComponent <Renderer>().material = m_signPropDict["electronic_sign_gantry"].m_material;
                    //TODO: Make mesh size dependent on text size
                    sign.m_sign.mesh = m_signPropDict["electronic_sign_gantry"].m_mesh;
                    sign.m_sign.transform.position = position;

                    sign.m_messageTextMesh.anchor = TextAnchor.MiddleLeft;
                    sign.m_messageTextMesh.font   = FontUtils.m_fontStore.ContainsKey("Electronic Highway Sign") ? FontUtils.m_fontStore["Electronic Highway Sign"] : districtManager.m_properties.m_areaNameFont.baseFont;

                    if (ShaderUtils.m_shaderStore.ContainsKey("font"))
                    {
                        sign.m_messageTextMesh.font.material.shader = ShaderUtils.m_shaderStore["font"];
                    }
                    else
                    {
                        sign.m_numMesh.GetComponent <Renderer>().material.shader = ShaderUtils.m_shaderStore["fallback"];
                    }
                    sign.m_messageTextMesh.color = (new Color(1, 0.77f, 0.56f, 1f));
                    sign.m_messageTextMesh.font.material.SetColor("Text Color", new Color(1, 0.77f, 0.56f, 1f));

                    sign.m_messageTextMesh.GetComponent <Renderer>().material = sign.m_messageTextMesh.font.material;
                    //TODO: Tie the font size to the font size option
                    sign.m_messageTextMesh.fontSize           = 50;
                    sign.m_messageTextMesh.transform.position = position;
                    sign.m_messageTextMesh.transform.parent   = sign.m_sign.transform;

                    sign.m_messageTextMesh.transform.position = position;
                    //Just a hack, to make sure the text actually shows up above the shield
                    sign.m_messageTextMesh.offsetZ = 0.001f;
                    //TODO: Definitely get a map of the texture to the required text odffsets
                    //TODO: Figure out a better ratio for route markers
                    sign.m_messageTextMesh.transform.localScale = new Vector3(0.25f, 0.25f, 0.25f);

                    String msgText = (sign.m_route == null ? "Traffic" : (sign.m_routePrefix + '-' + sign.m_route)) +
                                     " moving smoothly";
                    sign.m_messageTextMesh.text = msgText;

                    sign.m_messageTextMesh.transform.localPosition = new Vector3(0.7f, 8.4f, -19.7f);
                }
            }
        }
        private bool SnapToOneSide(Vector3 refPos, out Vector3 pos, out Vector3 dir, float maxDistance)
        {
            bool result = false;

            pos = refPos;
            dir = Vector3.forward;
            float minX    = refPos.x - maxDistance - 100f;
            float minZ    = refPos.z - maxDistance - 100f;
            float maxX    = refPos.x + maxDistance + 100f;
            float maxZ    = refPos.z + maxDistance + 100f;
            int   minXint = Mathf.Max((int)(minX / 64f + 135f), 0);
            int   minZint = Mathf.Max((int)(minZ / 64f + 135f), 0);
            int   maxXint = Mathf.Max((int)(maxX / 64f + 135f), 269);
            int   maxZint = Mathf.Max((int)(maxZ / 64f + 135f), 269);

            Array16 <NetSegment> segments = Singleton <NetManager> .instance.m_segments;

            ushort[] segmentGrid = Singleton <NetManager> .instance.m_segmentGrid;
            for (int i = minZint; i <= maxZint; i++)
            {
                for (int j = minXint; j <= maxXint; j++)
                {
                    ushort segmentGridZX = segmentGrid[i * 270 + j];
                    int    iterator      = 0;
                    while (segmentGridZX != 0)
                    {
                        NetSegment.Flags flags = segments.m_buffer[(int)segmentGridZX].m_flags;
                        if ((flags & (NetSegment.Flags.Created | NetSegment.Flags.Deleted)) == NetSegment.Flags.Created)
                        {
                            NetInfo info = segments.m_buffer[(int)segmentGridZX].Info;
                            if (info.m_class.m_service == ItemClass.Service.Road)
                            {
                                Vector3 min = segments.m_buffer[(int)segmentGridZX].m_bounds.min;
                                Vector3 max = segments.m_buffer[(int)segmentGridZX].m_bounds.max;
                                if (min.x < maxX && min.z < maxZ && max.x > minX && max.z > minZ)
                                {
                                    Vector3 centerPos;
                                    Vector3 centerDirection;
                                    segments.m_buffer[(int)segmentGridZX].GetClosestPositionAndDirection(refPos, out centerPos, out centerDirection);

                                    float distanceToRoad = Vector3.Distance(centerPos, refPos) - info.m_halfWidth;
                                    if (distanceToRoad < maxDistance)
                                    {
                                        if (info.m_lanes.Length == 9 || info.m_halfWidth == 20)
                                        {
                                            if (this.m_rotation == 0 || this.m_rotation == 180)
                                            {
                                                Vector3 vector2 = new Vector3(centerDirection.z, 0f, -centerDirection.x);
                                                dir = vector2.normalized;
                                                float delta = Vector3.Dot(centerPos - refPos, dir);
                                                if (delta > info.m_halfWidth / 2f && delta > 0 || delta < 0 && delta > -info.m_halfWidth / 2f)
                                                {
                                                    if (this.m_rotation == 0)
                                                    {
                                                        dir = -dir;
                                                    }
                                                }
                                            }
                                            else if (this.m_rotation == 90 || this.m_rotation == 270)
                                            {
                                                Vector3 vector2 = new Vector3(centerDirection.x, 0f, centerDirection.z);
                                                dir = vector2.normalized;
                                                float delta = Vector3.Dot(centerPos - refPos, dir);
                                                if (delta > info.m_halfWidth / 2f && delta > 0 || delta < 0 && delta > -info.m_halfWidth / 2f)
                                                {
                                                    if (this.m_rotation == 90)
                                                    {
                                                        dir = -dir;
                                                    }
                                                }
                                            }
                                        }
                                        else if (info.m_lanes.Length == 13 || info.m_halfWidth == 29)
                                        {
                                            if (this.m_rotation == 0 || this.m_rotation == 180)
                                            {
                                                Vector3 vector2 = new Vector3(centerDirection.z, 0f, -centerDirection.x);
                                                dir = vector2.normalized;
                                                float delta = Vector3.Dot(centerPos - refPos, dir);
                                                if (delta > 2f * info.m_halfWidth / 3f && delta > 0 || delta > 0 && delta < info.m_halfWidth / 3f || delta < -info.m_halfWidth / 3f && delta > -2f * info.m_halfWidth / 3f)
                                                {
                                                    if (this.m_rotation == 0)
                                                    {
                                                        dir = -dir;
                                                    }
                                                }
                                            }
                                            else if (this.m_rotation == 90 || this.m_rotation == 270)
                                            {
                                                Vector3 vector2 = new Vector3(centerDirection.x, 0f, centerDirection.z);
                                                dir = vector2.normalized;
                                                float delta = Vector3.Dot(centerPos - refPos, dir);
                                                if (delta > 2f * info.m_halfWidth / 3f && delta > 0 || delta > 0 && delta < info.m_halfWidth / 3f || delta < -info.m_halfWidth / 3f && delta > 2f * info.m_halfWidth / 3f)
                                                {
                                                    if (this.m_rotation == 90)
                                                    {
                                                        dir = -dir;
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            if (this.m_rotation == 0 || this.m_rotation == 180)
                                            {
                                                Vector3 vector2 = new Vector3(centerDirection.z, 0f, -centerDirection.x);
                                                dir = vector2.normalized;
                                                if (Vector3.Dot(centerPos - refPos, dir) > 0f)
                                                {
                                                    if (this.m_rotation == 0)
                                                    {
                                                        dir = -dir;
                                                    }
                                                }
                                            }
                                            else if (this.m_rotation == 90 || this.m_rotation == 270)
                                            {
                                                Vector3 vector2 = new Vector3(centerDirection.x, 0f, centerDirection.z);
                                                dir = vector2.normalized;
                                                if (Vector3.Dot(centerPos - refPos, dir) > 0f)
                                                {
                                                    if (this.m_rotation == 90)
                                                    {
                                                        dir = -dir;
                                                    }
                                                }
                                            }
                                        }

                                        Vector3 centerDirectionNormalized = centerDirection.normalized;

                                        float distanceDivisor = 100f;
                                        if (info.m_lanes.Length == 9 || info.m_halfWidth == 20)
                                        {
                                            float delta2 = Vector3.Dot(centerPos - refPos, dir);
                                            if (delta2 < -info.m_halfWidth / 2f)
                                            {
                                                pos = centerPos + dir * (9f + this.m_offset - (float)ModSettings.DistanceFromCurb / distanceDivisor);
                                            }
                                            else if (delta2 > -info.m_halfWidth / 2f && delta2 < 0)
                                            {
                                                pos = centerPos + dir * (9f - this.m_offset - (float)ModSettings.DistanceBetweenParkingStalls / distanceDivisor);
                                            }
                                            else if (delta2 < info.m_halfWidth)
                                            {
                                                pos = centerPos - dir * (9f - this.m_offset + (float)ModSettings.DistanceBetweenParkingStalls / distanceDivisor);
                                            }
                                            else
                                            {
                                                pos = centerPos - dir * (9f + this.m_offset - (float)ModSettings.DistanceFromCurb / distanceDivisor);
                                            }
                                        }
                                        else if (info.m_lanes.Length == 13 || info.m_halfWidth == 29)
                                        {
                                            float delta2 = Vector3.Dot(centerPos - refPos, dir);
                                            if (delta2 < -2f * info.m_halfWidth / 3f)
                                            {
                                                pos = centerPos + dir * (18f + this.m_offset - (float)ModSettings.DistanceFromCurb / distanceDivisor);
                                            }
                                            else if (delta2 < -info.m_halfWidth / 3f)
                                            {
                                                pos = centerPos + dir * (18f - this.m_offset - (float)ModSettings.DistanceBetweenParkingStalls / distanceDivisor);
                                            }
                                            else if (delta2 < 0f)
                                            {
                                                pos = centerPos + dir * (this.m_offset - (float)ModSettings.DistanceBetweenParkingStalls / distanceDivisor);
                                            }
                                            else if (delta2 < info.m_halfWidth / 3f)
                                            {
                                                pos = centerPos - dir * (this.m_offset + (float)ModSettings.DistanceBetweenParkingStalls / distanceDivisor);
                                            }
                                            else if (delta2 < 2f * info.m_halfWidth / 3f)
                                            {
                                                pos = centerPos - dir * (18f - this.m_offset + (float)ModSettings.DistanceBetweenParkingStalls / distanceDivisor);
                                            }
                                            else
                                            {
                                                pos = centerPos - dir * (18f + this.m_offset - (float)ModSettings.DistanceFromCurb / distanceDivisor);
                                            }
                                        }
                                        else if (info.m_lanes.Length == 4 || info.m_halfWidth == 8)
                                        {
                                            if (Vector3.Dot(centerPos - refPos, dir) < 0f)
                                            {
                                                pos = centerPos + dir * (this.m_offset - 3f - (float)ModSettings.DistanceFromCurb / distanceDivisor);
                                            }
                                            else
                                            {
                                                pos = centerPos - dir * (this.m_offset - 3f - (float)ModSettings.DistanceFromCurb / distanceDivisor);
                                            }
                                        }
                                        else
                                        {
                                            if (Vector3.Dot(centerPos - refPos, dir) < 0f)
                                            {
                                                pos = centerPos + dir * (this.m_offset - (float)ModSettings.DistanceFromCurb / distanceDivisor);
                                            }
                                            else
                                            {
                                                pos = centerPos - dir * (this.m_offset - (float)ModSettings.DistanceFromCurb / distanceDivisor);
                                            }
                                        }

                                        maxDistance = distanceToRoad;
                                        result      = true;
                                    }
                                }
                            }
                        }
                        segmentGridZX = segments.m_buffer[(int)segmentGridZX].m_nextGridSegment;
                        if (++iterator >= 32768)
                        {
                            Debug.Log("[APL].PSAAI.SnapToRoad Invalid List Detected!!!");
                            break;
                        }
                    }
                }
            }

            return(result);
        }
        private bool SnapToRoad(Vector3 refPos, out Vector3 pos, out Vector3 dir, float maxDistance, Building currentBuilding)
        {
            bool result = false;

            pos = refPos;
            dir = Vector3.forward;
            float minX    = refPos.x - maxDistance - 100f;
            float minZ    = refPos.z - maxDistance - 100f;
            float maxX    = refPos.x + maxDistance + 100f;
            float maxZ    = refPos.z + maxDistance + 100f;
            int   minXint = Mathf.Max((int)(minX / 64f + 135f), 0);
            int   minZint = Mathf.Max((int)(minZ / 64f + 135f), 0);
            int   maxXint = Mathf.Max((int)(maxX / 64f + 135f), 269);
            int   maxZint = Mathf.Max((int)(maxZ / 64f + 135f), 269);

            Array16 <NetSegment> segments = Singleton <NetManager> .instance.m_segments;

            ushort[] segmentGrid = Singleton <NetManager> .instance.m_segmentGrid;
            for (int i = minZint; i <= maxZint; i++)
            {
                for (int j = minXint; j <= maxXint; j++)
                {
                    ushort segmentGridZX = segmentGrid[i * 270 + j];
                    int    iterator      = 0;
                    while (segmentGridZX != 0)
                    {
                        NetSegment.Flags flags = segments.m_buffer[(int)segmentGridZX].m_flags;
                        if ((flags & (NetSegment.Flags.Created | NetSegment.Flags.Deleted)) == NetSegment.Flags.Created)
                        {
                            NetInfo info = segments.m_buffer[(int)segmentGridZX].Info;
                            if (info.m_class.m_service == ItemClass.Service.Road)
                            {
                                Vector3 min = segments.m_buffer[(int)segmentGridZX].m_bounds.min;
                                Vector3 max = segments.m_buffer[(int)segmentGridZX].m_bounds.max;
                                if (min.x < maxX && min.z < maxZ && max.x > minX && max.z > minZ)
                                {
                                    Vector3 centerPos;
                                    Vector3 centerDirection;
                                    segments.m_buffer[(int)segmentGridZX].GetClosestPositionAndDirection(refPos, out centerPos, out centerDirection);

                                    float distanceToRoad = Vector3.Distance(centerPos, refPos) - info.m_halfWidth;
                                    //Debug.Log("[APL].PSAAI.Snap to Road info.lanes = " + info.m_lanes.Length.ToString());
                                    //Debug.Log("[APL].PSAAI.Snap to Road info.m_halfwidth = " + info.m_halfWidth.ToString());
                                    if (distanceToRoad < maxDistance)
                                    {
                                        Vector3 vector2 = new Vector3(centerDirection.z, 0f, -centerDirection.x);
                                        dir = vector2.normalized;
                                        if (Vector3.Dot(centerPos - refPos, dir) < 0f)
                                        {
                                            dir = -dir;
                                        }

                                        if (info.m_halfWidth == 20 || info.m_lanes.Length == 9)
                                        {
                                            if (this.m_rotation == 0 || this.m_rotation == 180)
                                            {
                                                if (Vector3.Dot(centerPos - refPos, dir) > 0f)
                                                {
                                                    if (this.m_rotation == 0)
                                                    {
                                                        dir = -dir;
                                                    }
                                                }
                                            }
                                            else if (this.m_rotation == 90 || this.m_rotation == 270)
                                            {
                                                if (Vector3.Dot(centerPos - refPos, dir) > 0f)
                                                {
                                                    if (this.m_rotation == 90)
                                                    {
                                                        dir = -dir;
                                                    }
                                                }
                                            }
                                            Vector3 centerDirectionNormalized = centerDirection.normalized;
                                            if (Vector3.Dot(centerPos - refPos, dir) < 0f)
                                            {
                                                pos = centerPos + dir * (9f);
                                            }
                                            else
                                            {
                                                pos = centerPos - dir * (9f);
                                            }
                                        }
                                        else if (info.m_halfWidth == 29 || info.m_lanes.Length == 13)
                                        {
                                            pos = centerPos;
                                            if (this.m_rotation == 0 || this.m_rotation == 180)
                                            {
                                                if (Vector3.Dot(centerPos - refPos, dir) > 0f)
                                                {
                                                    if (this.m_rotation == 0)
                                                    {
                                                        dir = -dir;
                                                    }
                                                }
                                            }
                                            else if (this.m_rotation == 90 || this.m_rotation == 270)
                                            {
                                                if (Vector3.Dot(centerPos - refPos, dir) > 0f)
                                                {
                                                    if (this.m_rotation == 90)
                                                    {
                                                        dir = -dir;
                                                    }
                                                }
                                            }
                                            Vector3 centerDirectionNormalized = centerDirection.normalized;
                                            if (Vector3.Dot(centerPos - refPos, dir) < -11f)
                                            {
                                                pos = centerPos + dir * 18f;
                                            }
                                            else if ((Vector3.Dot(centerPos - refPos, dir) > 11f))
                                            {
                                                pos = centerPos - dir * 18f;
                                            }
                                        }
                                        else
                                        {
                                            float  angle = Mathf.Atan2(dir.x, -dir.z);
                                            ushort adjacentParkingAssetID = CheckForParkingSpaces(centerPos, angle, currentBuilding.m_width, currentBuilding.m_length);
                                            bool   snappedToParkingAsset  = false;

                                            /*
                                             * if (adjacentParkingAssetID != 0) {
                                             *  Building adjacentParkingAsset = BuildingManager.instance.m_buildings.m_buffer[adjacentParkingAssetID];
                                             *  if (adjacentParkingAsset.m_angle == angle)
                                             *  {
                                             *      Debug.Log("[APL].PSAAi.SnapToRoad Snap to this asset id = " + adjacentParkingAssetID.ToString());
                                             *      Vector3 centerDirectionNormalized = centerDirection.normalized;
                                             *
                                             *      float dist1 = Vector3.Dot(centerPos - adjacentParkingAsset.m_position, centerDirectionNormalized);
                                             *      Debug.Log("[APL].PSAAi.SnapToRoad Dot Product equals " + dist1.ToString());
                                             *      pos = centerPos - (adjacentParkingAsset.Width*4f-dist1)*centerDirectionNormalized + currentBuilding.m_width*4f* centerDirectionNormalized;
                                             *      snappedToParkingAsset = true;
                                             *
                                             *      //snappedToParkingAsset = true;
                                             *  }
                                             * }
                                             */
                                            if (snappedToParkingAsset == false)
                                            {
                                                pos = centerPos;
                                            }
                                        }
                                        maxDistance = distanceToRoad;
                                        result      = true;
                                    }
                                }
                            }
                        }
                        segmentGridZX = segments.m_buffer[(int)segmentGridZX].m_nextGridSegment;
                        if (++iterator >= 32768)
                        {
                            Debug.Log("[APL].PSAAI.SnapToRoad Invalid List Detected!!!");
                            break;
                        }
                    }
                }
            }

            return(result);
        }
 internal static bool IsFlagSet(this NetSegment.Flags value, NetSegment.Flags flag) => (value & flag) != 0;
Exemplo n.º 19
0
        /// <summary>
        /// Perform actual network replacement.
        /// </summary>
        /// <param name="target">Target netInfo</param>
        /// <param name="replacement">Replacement netInfo</param>
        /// <param name="segmentList">Array of segment IDs</param>
        internal static void ReplaceNets(NetInfo target, NetInfo replacement, List <ushort> segmentList)
        {
            try
            {
                // Ensure segment list is valid..
                if (segmentList == null || segmentList.Count == 0)
                {
                    Logging.Message("no selected networks for replacing");
                    return;
                }

                // Input checks.
                if (target?.name == null || replacement?.name == null)
                {
                    Logging.Error("null parameter passed to ReplaceNets");
                    return;
                }

                // Local references.
                NetManager   netManager    = Singleton <NetManager> .instance;
                Randomizer   randomizer    = new Randomizer();
                NetSegment[] segmentBuffer = netManager.m_segments.m_buffer;

                // Copy segment IDs from segment list to avoid concurrency issues while replacing.
                ushort[] segmentIDs = new ushort[segmentList.Count];
                segmentList.CopyTo(segmentIDs, 0);

                // Initialize undo buffer.
                undoBuffer = new List <ushort>();
                undoPrefab = target;

                // Iterate through each segment ID in our prepared list.
                for (int i = 0; i < segmentIDs.Length; ++i)
                {
                    // Local references.
                    ushort     segmentID = segmentIDs[i];
                    NetSegment segment   = segmentBuffer[segmentID];

                    // Null check, just in case.
                    NetInfo segmentInfo = segment.Info;
                    if (segmentInfo != null)
                    {
                        // Check that this is an active network before we do actual replacement.
                        if (segment.m_flags != NetSegment.Flags.None)
                        {
                            // Get segment name and prority.
                            bool   priority       = netManager.IsPriorityRoad(segmentID, out bool _);
                            ushort nameSeed       = segment.m_nameSeed;
                            bool   customNameFlag = (segment.m_flags & NetSegment.Flags.CustomName) != 0;
                            string segmentName    = netManager.GetSegmentName(segmentID);

                            NetSegment.Flags flags = segment.m_flags & NetSegment.Flags.Original;

                            // Get segment 'original' status.
                            NetSegment.Flags originalFlag = segment.m_flags & NetSegment.Flags.Original;

                            // Active network segment - replace segment.
                            ushort newSegmentID = ReplaceNet(segmentID, segmentBuffer, replacement, ref randomizer);

                            // Set nameseed and priority of new segment to match original.
                            segmentBuffer[newSegmentID].m_nameSeed = nameSeed;
                            netManager.SetPriorityRoad(newSegmentID, priority);

                            // Set 'original' status of new segment.
                            segmentBuffer[newSegmentID].m_flags |= originalFlag;

                            // Restore any custom name.
                            if (customNameFlag && segmentName != null)
                            {
                                netManager.SetSegmentNameImpl(newSegmentID, segmentName);
                            }

                            // Add new segment ID to undo buffer.
                            undoBuffer.Add(newSegmentID);
                        }
                        else
                        {
                            // Inactive network segment - just replace info directly..
                            segmentBuffer[segmentID].Info = replacement;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // Don't care too much - just want to make sure that we set the status flag correctly and not hang in the 'processing' state indefinitely.
                Logging.LogException(e, "network replacement exception");
            }

            // All done - let replacer panel know we're finished (if its still open).
            if (ReplacerPanel.Panel != null)
            {
                ReplacerPanel.Panel.replacingDone = true;
            }
        }
Exemplo n.º 20
0
 public bool CheckFlags(
     NetNodeExt.Flags nodeFlags, NetSegmentEnd.Flags segmentEndFlags,
     NetSegmentExt.Flags segmentFlags, NetSegment.Flags vanillaSegmentFlags) =>
 NodeFlags.CheckFlags(nodeFlags) && SegmentEndFlags.CheckFlags(segmentEndFlags) &&
 SegmentFlags.CheckFlags(segmentFlags) && VanillaSegmentFlags.CheckFlags(vanillaSegmentFlags);
Exemplo n.º 21
0
        private OSMWay CreateWay(int index, NetSegment segment, ushort segmentId)
        {
            OSMWay returnWay = null;

            NetSegment.Flags segmentFlags = segment.m_flags;
            NetManager       netManager   = Singleton <NetManager> .instance;
            List <OSMWayND>  wayPaths     = new List <OSMWayND>();
            List <OSMWayTag> wayTags;
            ushort           startNodeId = segment.m_startNode, endNodeId = segment.m_endNode;

            if (startNodeId != 0 && endNodeId != 0)
            {
                Vector3 startNodeDirection = segment.m_startDirection;
                Vector3 endNodeDirection   = segment.m_endDirection;

                if (segmentFlags.IsFlagSet(NetSegment.Flags.Invert))
                {
                    startNodeId        = segment.m_endNode;
                    endNodeId          = segment.m_startNode;
                    startNodeDirection = segment.m_endDirection;
                    endNodeDirection   = segment.m_startDirection;
                }

                NetNode startNode         = netManager.m_nodes.m_buffer[startNodeId];
                NetNode endNode           = netManager.m_nodes.m_buffer[endNodeId];
                Vector3 startNodePosition = startNode.m_position;
                Vector3 endNodePosition   = endNode.m_position;

                wayPaths.Add(new OSMWayND {
                    @ref = startNodeId
                });

                if (Vector3.Angle(startNodeDirection, -endNodeDirection) > 3f)
                {
                    Vector3 midPointA = Vector3.zero, midPointB = Vector3.zero;
                    NetSegment.CalculateMiddlePoints(startNodePosition, startNodeDirection, endNodePosition, endNodeDirection, false, false, out midPointA, out midPointB);
                    Bezier3 bezier = new Bezier3(startNodePosition, midPointA, midPointB, endNodePosition);

                    osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.25f)));
                    osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.5f)));
                    osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.75f)));

                    wayPaths.Add(new OSMWayND {
                        @ref = (uint)unindexedNodeOffset - 3
                    });
                    wayPaths.Add(new OSMWayND {
                        @ref = (uint)unindexedNodeOffset - 2
                    });
                    wayPaths.Add(new OSMWayND {
                        @ref = (uint)unindexedNodeOffset - 1
                    });
                }

                wayPaths.Add(new OSMWayND {
                    @ref = endNodeId
                });

                if (Tagger.CreateWayTags(segment, out wayTags))
                {
                    if (haveRoadNamerMod)
                    {
                        // If road namer mod is available, then attempt to get the name asscociated with the segment, if any
                        string roadName = RoadNamerManager.Instance().getSegmentName((ushort)(segmentId));
                        if (roadName != null)
                        {
                            //If a name is available, add a name tag
                            wayTags.Add(new OSMWayTag {
                                k = "name", v = StringUtilities.RemoveTags(roadName)
                            });
                        }
                    }
                    returnWay = new OSMWay {
                        changeset = 50000000, id = (uint)index, timestamp = DateTime.Now, user = "******", nd = wayPaths.ToArray(), tag = wayTags.ToArray(), version = 1
                    };
                }
                else
                {
                    UniqueLogger.AddLog("Road names missing from search", segment.Info.name, "");
                }
            }

            return(returnWay);
        }