public bool IsMonorailSegment(NetInfo segmentInfo)
        {
            ItemClass connectionClass = segmentInfo.GetConnectionClass();

            return(connectionClass.m_service == ItemClass.Service.PublicTransport &&
                   connectionClass.m_subService == ItemClass.SubService.PublicTransportMonorail);
        }
        private static bool FindConnectNode(FastList <ushort> buffer, Vector3 pos, NetInfo info2, out NetTool.ControlPoint point)
        {
            point = default(NetTool.ControlPoint);
            NetManager instance = Singleton <NetManager> .instance;

            ItemClass.Service    service     = info2.m_class.m_service;
            ItemClass.SubService subService  = info2.m_class.m_subService;
            ItemClass.Layer      layer       = info2.m_class.m_layer;
            ItemClass.Service    service2    = ItemClass.Service.None;
            ItemClass.SubService subService2 = ItemClass.SubService.None;
            ItemClass.Layer      layer2      = ItemClass.Layer.Default;
            if (info2.m_intersectClass != null)
            {
                service2    = info2.m_intersectClass.m_service;
                subService2 = info2.m_intersectClass.m_subService;
                layer2      = info2.m_intersectClass.m_layer;
            }
            if (info2.m_netAI.SupportUnderground() || info2.m_netAI.IsUnderground())
            {
                layer  |= (ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels);
                layer2 |= (ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels);
            }
            for (int i = 0; i < buffer.m_size; i++)
            {
                ushort num = buffer.m_buffer[i];
                if (Vector3.SqrMagnitude(pos - instance.m_nodes.m_buffer[(int)num].m_position) < 0.001f)
                {
                    NetInfo   info3           = instance.m_nodes.m_buffer[(int)num].Info;
                    ItemClass connectionClass = info3.GetConnectionClass();
                    if (((service == ItemClass.Service.None || connectionClass.m_service == service) && (subService == ItemClass.SubService.None || connectionClass.m_subService == subService) && (layer == ItemClass.Layer.None || (connectionClass.m_layer & layer) != ItemClass.Layer.None)) || (info3.m_intersectClass != null && (service == ItemClass.Service.None || info3.m_intersectClass.m_service == service) && (subService == ItemClass.SubService.None || info3.m_intersectClass.m_subService == subService) && (layer == ItemClass.Layer.None || (info3.m_intersectClass.m_layer & layer) != ItemClass.Layer.None)) || (connectionClass.m_service == service2 && (subService2 == ItemClass.SubService.None || connectionClass.m_subService == subService2) && (layer2 == ItemClass.Layer.None || (connectionClass.m_layer & layer2) != ItemClass.Layer.None)))
                    {
                        point.m_position  = instance.m_nodes.m_buffer[(int)num].m_position;
                        point.m_direction = Vector3.zero;
                        point.m_node      = num;
                        point.m_segment   = 0;
                        if (info3.m_netAI.IsUnderground())
                        {
                            point.m_elevation = (float)(-(float)instance.m_nodes.m_buffer[(int)num].m_elevation);
                        }
                        else
                        {
                            point.m_elevation = (float)instance.m_nodes.m_buffer[(int)num].m_elevation;
                        }
                        return(true);
                    }
                }
            }
            return(false);
        }
        public Dictionary <NetInfo, ushort> GetDefaultSpeedLimits()
        {
            Dictionary <NetInfo, ushort> ret = new Dictionary <NetInfo, ushort>();
            int numLoaded = PrefabCollection <NetInfo> .LoadedCount();

            for (uint i = 0; i < numLoaded; ++i)
            {
                NetInfo info = PrefabCollection <NetInfo> .GetLoaded(i);

                ushort defaultSpeedLimit = GetAverageDefaultCustomSpeedLimit(info, NetInfo.Direction.Forward);
                ret.Add(info, defaultSpeedLimit);
                Log._Debug($"Loaded NetInfo: {info.name}, connectionClass.service: {info.GetConnectionClass().m_service.ToString()}, connectionClass.subService: {info.GetConnectionClass().m_subService.ToString()}, avg. default speed limit: {defaultSpeedLimit}");
            }
            return(ret);
        }
 private static bool RequireFixedHeight(BuildingInfo buildingInfo, NetInfo info2, Vector3 pos)
 {
     if (info2.m_useFixedHeight)
     {
         return(true);
     }
     ItemClass.Service    service     = info2.m_class.m_service;
     ItemClass.SubService subService  = info2.m_class.m_subService;
     ItemClass.Layer      layer       = info2.m_class.m_layer;
     ItemClass.Service    service2    = ItemClass.Service.None;
     ItemClass.SubService subService2 = ItemClass.SubService.None;
     ItemClass.Layer      layer2      = ItemClass.Layer.Default;
     if (info2.m_intersectClass != null)
     {
         service2    = info2.m_intersectClass.m_service;
         subService2 = info2.m_intersectClass.m_subService;
         layer2      = info2.m_intersectClass.m_layer;
     }
     if (info2.m_netAI.SupportUnderground() || info2.m_netAI.IsUnderground())
     {
         layer  |= (ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels);
         layer2 |= (ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels);
     }
     for (int i = 0; i < buildingInfo.m_paths.Length; i++)
     {
         BuildingInfo.PathInfo pathInfo = buildingInfo.m_paths[i];
         if (pathInfo.m_finalNetInfo != null && pathInfo.m_finalNetInfo.m_useFixedHeight && pathInfo.m_nodes != null && pathInfo.m_nodes.Length != 0)
         {
             for (int j = 0; j < pathInfo.m_nodes.Length; j++)
             {
                 if (Vector3.SqrMagnitude(pos - pathInfo.m_nodes[j]) < 0.001f)
                 {
                     NetInfo   finalNetInfo    = pathInfo.m_finalNetInfo;
                     ItemClass connectionClass = finalNetInfo.GetConnectionClass();
                     if (((service == ItemClass.Service.None || connectionClass.m_service == service) && (subService == ItemClass.SubService.None || connectionClass.m_subService == subService) && (layer == ItemClass.Layer.None || (connectionClass.m_layer & layer) != ItemClass.Layer.None)) || (finalNetInfo.m_intersectClass != null && (service == ItemClass.Service.None || finalNetInfo.m_intersectClass.m_service == service) && (subService == ItemClass.SubService.None || finalNetInfo.m_intersectClass.m_subService == subService) && (layer == ItemClass.Layer.None || (finalNetInfo.m_intersectClass.m_layer & layer) != ItemClass.Layer.None)) || (finalNetInfo.m_netAI.CanIntersect(info2) && connectionClass.m_service == service2 && (subService2 == ItemClass.SubService.None || connectionClass.m_subService == subService2) && (layer2 == ItemClass.Layer.None || (connectionClass.m_layer & layer2) != ItemClass.Layer.None)))
                     {
                         return(true);
                     }
                 }
             }
         }
     }
     return(false);
 }
        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);
        }
Example #6
0
        public bool IsRoadSegment(NetInfo segmentInfo)
        {
            ItemClass connectionClass = segmentInfo.GetConnectionClass();

            return(connectionClass.m_service == ItemClass.Service.Road);
        }
        private bool drawVehicleRestrictionHandles(ushort segmentId, bool viewOnly, out bool stateUpdated)
        {
            stateUpdated = false;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    ++y;
                }

                ++x;
            }

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

            return(hovered);
        }
Example #8
0
        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);
        }
Example #9
0
        public static void CSURUpdateEndSegments(ref NetSegment __instance, ushort segmentID)
        {
            NetManager instance = Singleton <NetManager> .instance;
            NetInfo    info     = __instance.Info;

            if (info == null)
            {
                return;
            }
            ItemClass connectionClass = info.GetConnectionClass();
            float     num             = -4f;
            float     num2            = -4f;
            ushort    endLeftSegment  = 0;
            ushort    endRightSegment = 0;

            for (int i = 0; i < 8; i++)
            {
                ushort segment = instance.m_nodes.m_buffer[(int)__instance.m_endNode].GetSegment(i);
                if (segment != 0 && segment != segmentID)
                {
                    NetInfo info2 = instance.m_segments.m_buffer[(int)segment].Info;
                    if (info2 != null)
                    {
                        ItemClass connectionClass2 = info2.GetConnectionClass();
                        if (connectionClass.m_service == connectionClass2.m_service)
                        {
                            //Non-stock code begin
                            Vector3 vector = instance.m_lanes.m_buffer[instance.m_segments.m_buffer[(int)segment].m_lanes].m_bezier.Position(0.5f) - instance.m_lanes.m_buffer[instance.m_segments.m_buffer[(int)segmentID].m_lanes].m_bezier.Position(0.5f);
                            vector = VectorUtils.NormalizeXZ(vector);
                            //Non-stock code end
                            float num3 = __instance.m_endDirection.x * vector.x + __instance.m_endDirection.z * vector.z;
                            if (vector.z * __instance.m_endDirection.x - vector.x * __instance.m_endDirection.z < 0f)
                            {
                                if (num3 > num)
                                {
                                    num            = num3;
                                    endLeftSegment = segment;
                                }
                                num3 = -2f - num3;
                                if (num3 > num2)
                                {
                                    num2            = num3;
                                    endRightSegment = segment;
                                }
                            }
                            else
                            {
                                if (num3 > num2)
                                {
                                    num2            = num3;
                                    endRightSegment = segment;
                                }
                                num3 = -2f - num3;
                                if (num3 > num)
                                {
                                    num            = num3;
                                    endLeftSegment = segment;
                                }
                            }
                        }
                    }
                }
            }
            __instance.m_endLeftSegment  = endLeftSegment;
            __instance.m_endRightSegment = endRightSegment;
        }
        private bool drawSignHandles(bool debug,
                                     ushort nodeId,
                                     ref NetNode node,
                                     bool viewOnly,
                                     bool handleClick,
                                     ref Vector3 camPos,
                                     out bool stateUpdated)
        {
            bool hovered = false;

            stateUpdated = false;

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

            // NetManager netManager = Singleton<NetManager>.instance;
            Color   guiColor = GUI.color;
            Vector3 nodePos  = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].m_position;
            IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager;

            for (int i = 0; i < 8; ++i)
            {
                ushort segmentId = node.GetSegment(i);

                if (segmentId == 0)
                {
                    continue;
                }

                bool startNode = (bool)Constants.ServiceFactory.NetService.IsStartNode(segmentId, nodeId);
                bool incoming  = segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, startNode)].incoming;

                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 * (numSignsPerRow - 1) * f * xu); // "top left"
                if (viewOnly)
                {
                    if (Constants.ServiceFactory.SimulationService.TrafficDrivesOnLeft)
                    {
                        zero -= xu * 8f;
                    }
                    else
                    {
                        zero += xu * 8f;
                    }
                }

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

                // draw "lane-changing when going straight allowed" sign at (0; 0)
                bool allowed =
                    JunctionRestrictionsManager.Instance.IsLaneChangingAllowedWhenGoingStraight(
                        segmentId,
                        startNode);

                bool configurable =
                    Constants.ManagerFactory.JunctionRestrictionsManager
                    .IsLaneChangingAllowedWhenGoingStraightConfigurable(
                        segmentId,
                        startNode,
                        ref node);

                if (debug ||
                    (configurable &&
                     (!viewOnly ||
                      (allowed != Constants.ManagerFactory
                       .JunctionRestrictionsManager
                       .GetDefaultLaneChangingAllowedWhenGoingStraight(
                           segmentId,
                           startNode,
                           ref node)))))
                {
                    DrawSign(
                        viewOnly,
                        !configurable,
                        ref camPos,
                        ref xu,
                        ref yu,
                        f,
                        ref zero,
                        x,
                        y,
                        guiColor,
                        allowed
                            ? JunctionRestrictions.LaneChangeAllowed
                            : JunctionRestrictions.LaneChangeForbidden,
                        out signHovered);

                    if (signHovered && handleClick)
                    {
                        hovered = true;
                        if (MainTool.CheckClicked())
                        {
                            JunctionRestrictionsManager.Instance.ToggleLaneChangingAllowedWhenGoingStraight(
                                segmentId,
                                startNode);
                            stateUpdated = true;
                        }
                    }

                    ++x;
                    hasSignInPrevRow = true;
                }

                // draw "u-turns allowed" sign at (1; 0)
                allowed      = JunctionRestrictionsManager.Instance.IsUturnAllowed(segmentId, startNode);
                configurable =
                    Constants.ManagerFactory.JunctionRestrictionsManager.IsUturnAllowedConfigurable(
                        segmentId,
                        startNode,
                        ref node);
                if (debug ||
                    (configurable &&
                     (!viewOnly ||
                      (allowed != Constants.ManagerFactory
                       .JunctionRestrictionsManager
                       .GetDefaultUturnAllowed(
                           segmentId,
                           startNode,
                           ref node)))))
                {
                    DrawSign(
                        viewOnly,
                        !configurable,
                        ref camPos,
                        ref xu,
                        ref yu,
                        f,
                        ref zero,
                        x,
                        y,
                        guiColor,
                        allowed
                            ? JunctionRestrictions.UturnAllowed
                            : JunctionRestrictions.UturnForbidden,
                        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;
                            }
                        }
                    }

                    x++;
                    hasSignInPrevRow = true;
                }

                x = 0;
                if (hasSignInPrevRow)
                {
                    ++y;
                    hasSignInPrevRow = false;
                }

                // draw "entering blocked junctions allowed" sign at (0; 1)
                allowed = JunctionRestrictionsManager.Instance.IsEnteringBlockedJunctionAllowed(
                    segmentId,
                    startNode);
                configurable =
                    Constants.ManagerFactory.JunctionRestrictionsManager
                    .IsEnteringBlockedJunctionAllowedConfigurable(
                        segmentId,
                        startNode,
                        ref node);

                if (debug ||
                    (configurable &&
                     (!viewOnly ||
                      (allowed != Constants.ManagerFactory
                       .JunctionRestrictionsManager
                       .GetDefaultEnteringBlockedJunctionAllowed(
                           segmentId,
                           startNode,
                           ref node)))))
                {
                    DrawSign(
                        viewOnly,
                        !configurable,
                        ref camPos,
                        ref xu,
                        ref yu,
                        f,
                        ref zero,
                        x,
                        y,
                        guiColor,
                        allowed
                            ? JunctionRestrictions.EnterBlockedJunctionAllowed
                            : JunctionRestrictions.EnterBlockedJunctionForbidden,
                        out signHovered);

                    if (signHovered && handleClick)
                    {
                        hovered = true;

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

                    ++x;
                    hasSignInPrevRow = true;
                }

                // draw "pedestrian crossing allowed" sign at (1; 1)
                allowed = JunctionRestrictionsManager.Instance.IsPedestrianCrossingAllowed(
                    segmentId,
                    startNode);
                configurable =
                    Constants.ManagerFactory.JunctionRestrictionsManager
                    .IsPedestrianCrossingAllowedConfigurable(
                        segmentId,
                        startNode,
                        ref node);

                if (debug ||
                    (configurable &&
                     (!viewOnly || !allowed)))
                {
                    DrawSign(
                        viewOnly,
                        !configurable,
                        ref camPos,
                        ref xu,
                        ref yu,
                        f,
                        ref zero,
                        x,
                        y,
                        guiColor,
                        allowed
                            ? JunctionRestrictions.PedestrianCrossingAllowed
                            : JunctionRestrictions.PedestrianCrossingForbidden,
                        out signHovered);

                    if (signHovered && handleClick)
                    {
                        hovered = true;

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

                    x++;
                    hasSignInPrevRow = true;
                }

                x = 0;

                if (hasSignInPrevRow)
                {
                    ++y;
                    hasSignInPrevRow = false;
                }

                if (!Options.turnOnRedEnabled)
                {
                    continue;
                }

                //--------------------------------
                // TURN ON RED ENABLED
                //--------------------------------
                IJunctionRestrictionsManager junctionRestrictionsManager =
                    Constants.ManagerFactory.JunctionRestrictionsManager;
                bool lht = Constants.ServiceFactory.SimulationService.TrafficDrivesOnLeft;

                // draw "turn-left-on-red allowed" sign at (2; 0)
                allowed      = junctionRestrictionsManager.IsTurnOnRedAllowed(lht, segmentId, startNode);
                configurable = junctionRestrictionsManager.IsTurnOnRedAllowedConfigurable(
                    lht,
                    segmentId,
                    startNode,
                    ref node);

                if (debug ||
                    (configurable &&
                     (!viewOnly ||
                      (allowed != junctionRestrictionsManager
                       .GetDefaultTurnOnRedAllowed(
                           lht,
                           segmentId,
                           startNode,
                           ref node)))))
                {
                    DrawSign(
                        viewOnly,
                        !configurable,
                        ref camPos,
                        ref xu,
                        ref yu,
                        f,
                        ref zero,
                        x,
                        y,
                        guiColor,
                        allowed
                            ? JunctionRestrictions.LeftOnRedAllowed
                            : JunctionRestrictions.LeftOnRedForbidden,
                        out signHovered);

                    if (signHovered && handleClick)
                    {
                        hovered = true;

                        if (MainTool.CheckClicked())
                        {
                            junctionRestrictionsManager.ToggleTurnOnRedAllowed(
                                lht,
                                segmentId,
                                startNode);
                            stateUpdated = true;
                        }
                    }

                    hasSignInPrevRow = true;
                }

                x++;

                // draw "turn-right-on-red allowed" sign at (2; 1)
                allowed = junctionRestrictionsManager.IsTurnOnRedAllowed(
                    !lht,
                    segmentId,
                    startNode);
                configurable = junctionRestrictionsManager.IsTurnOnRedAllowedConfigurable(
                    !lht,
                    segmentId,
                    startNode,
                    ref node);

                if (debug ||
                    (configurable &&
                     (!viewOnly ||
                      (allowed != junctionRestrictionsManager
                       .GetDefaultTurnOnRedAllowed(
                           !lht,
                           segmentId,
                           startNode,
                           ref node)))))
                {
                    DrawSign(
                        viewOnly,
                        !configurable,
                        ref camPos,
                        ref xu,
                        ref yu,
                        f,
                        ref zero,
                        x,
                        y,
                        guiColor,
                        allowed
                            ? JunctionRestrictions.RightOnRedAllowed
                            : JunctionRestrictions.RightOnRedForbidden,
                        out signHovered);

                    if (signHovered && handleClick)
                    {
                        hovered = true;

                        if (MainTool.CheckClicked())
                        {
                            junctionRestrictionsManager.ToggleTurnOnRedAllowed(
                                !lht,
                                segmentId,
                                startNode);
                            stateUpdated = true;
                        }
                    }

                    hasSignInPrevRow = true;
                }
            }

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

            return(hovered);
        }
Example #11
0
        public void RefreshJunctionData(ushort nodeID, int segmentIndex, ushort nodeSegment, Vector3 centerPos, ref uint instanceIndex, ref RenderManager.Instance data)
        {
            NetNode    thisNode = NetManager.instance.m_nodes.m_buffer[nodeID];
            NetManager instance = Singleton <NetManager> .instance;

            data.m_position    = thisNode.m_position;
            data.m_rotation    = Quaternion.identity;
            data.m_initialized = true;
            float      vScale          = 0.05f;
            Vector3    zero            = Vector3.zero;
            Vector3    zero2           = Vector3.zero;
            Vector3    zero3           = Vector3.zero;
            Vector3    zero4           = Vector3.zero;
            Vector3    vector          = Vector3.zero;
            Vector3    vector2         = Vector3.zero;
            Vector3    a               = Vector3.zero;
            Vector3    a2              = Vector3.zero;
            Vector3    zero5           = Vector3.zero;
            Vector3    zero6           = Vector3.zero;
            Vector3    zero7           = Vector3.zero;
            Vector3    zero8           = Vector3.zero;
            NetSegment netSegment      = instance.m_segments.m_buffer[(int)nodeSegment];
            NetInfo    info            = netSegment.Info;
            ItemClass  connectionClass = info.GetConnectionClass();
            Vector3    vector3         = (nodeID != netSegment.m_startNode) ? netSegment.m_endDirection : netSegment.m_startDirection;
            float      num             = -4f;
            float      num2            = -4f;
            ushort     num3            = 0;
            ushort     num4            = 0;

            for (int i = 0; i < 8; i++)
            {
                ushort segment = thisNode.GetSegment(i);
                if (segment != 0 && segment != nodeSegment)
                {
                    NetInfo   info2            = instance.m_segments.m_buffer[(int)segment].Info;
                    ItemClass connectionClass2 = info2.GetConnectionClass();
                    if (connectionClass.m_service == connectionClass2.m_service)
                    {
                        NetSegment netSegment2 = instance.m_segments.m_buffer[(int)segment];
                        Vector3    vector4     = (nodeID != netSegment2.m_startNode) ? netSegment2.m_endDirection : netSegment2.m_startDirection;
                        float      num5        = vector3.x * vector4.x + vector3.z * vector4.z;
                        if (vector4.z * vector3.x - vector4.x * vector3.z < 0f)
                        {
                            if (num5 > num)
                            {
                                num  = num5;
                                num3 = segment;
                            }
                            num5 = -2f - num5;
                            if (num5 > num2)
                            {
                                num2 = num5;
                                num4 = segment;
                            }
                        }
                        else
                        {
                            if (num5 > num2)
                            {
                                num2 = num5;
                                num4 = segment;
                            }
                            num5 = -2f - num5;
                            if (num5 > num)
                            {
                                num  = num5;
                                num3 = segment;
                            }
                        }
                    }
                }
            }
            bool start = netSegment.m_startNode == nodeID;
            bool flag;

            netSegment.CalculateCorner(nodeSegment, true, start, false, out zero, out zero3, out flag);
            netSegment.CalculateCorner(nodeSegment, true, start, true, out zero2, out zero4, out flag);
            if (num3 != 0 && num4 != 0)
            {
                float num6 = info.m_pavementWidth / info.m_halfWidth * 0.5f;
                float y    = 1f;
                if (num3 != 0)
                {
                    NetSegment netSegment3 = instance.m_segments.m_buffer[(int)num3];
                    NetInfo    info3       = netSegment3.Info;
                    start = (netSegment3.m_startNode == nodeID);
                    netSegment3.CalculateCorner(num3, true, start, true, out vector, out a, out flag);
                    netSegment3.CalculateCorner(num3, true, start, false, out vector2, out a2, out flag);
                    float num7 = info3.m_pavementWidth / info3.m_halfWidth * 0.5f;
                    num6 = (num6 + num7) * 0.5f;
                    y    = 2f * info.m_halfWidth / (info.m_halfWidth + info3.m_halfWidth);
                }
                float num8 = info.m_pavementWidth / info.m_halfWidth * 0.5f;
                float w    = 1f;
                if (num4 != 0)
                {
                    NetSegment netSegment4 = instance.m_segments.m_buffer[(int)num4];
                    NetInfo    info4       = netSegment4.Info;
                    start = (netSegment4.m_startNode == nodeID);
                    netSegment4.CalculateCorner(num4, true, start, true, out zero5, out zero7, out flag);
                    netSegment4.CalculateCorner(num4, true, start, false, out zero6, out zero8, out flag);
                    float num9 = info4.m_pavementWidth / info4.m_halfWidth * 0.5f;
                    num8 = (num8 + num9) * 0.5f;
                    w    = 2f * info.m_halfWidth / (info.m_halfWidth + info4.m_halfWidth);
                }
                Vector3 vector5;
                Vector3 vector6;
                NetSegment.CalculateMiddlePoints(zero, -zero3, vector, -a, true, true, out vector5, out vector6);
                Vector3 vector7;
                Vector3 vector8;
                NetSegment.CalculateMiddlePoints(zero2, -zero4, vector2, -a2, true, true, out vector7, out vector8);
                Vector3 vector9;
                Vector3 vector10;
                NetSegment.CalculateMiddlePoints(zero, -zero3, zero5, -zero7, true, true, out vector9, out vector10);
                Vector3 vector11;
                Vector3 vector12;
                NetSegment.CalculateMiddlePoints(zero2, -zero4, zero6, -zero8, true, true, out vector11, out vector12);

                data.m_dataMatrix0             = NetSegment.CalculateControlMatrix(zero, vector5, vector6, vector, zero, vector5, vector6, vector, thisNode.m_position, vScale);
                data.m_extraData.m_dataMatrix2 = NetSegment.CalculateControlMatrix(zero2, vector7, vector8, vector2, zero2, vector7, vector8, vector2, thisNode.m_position, vScale);
                data.m_extraData.m_dataMatrix3 = NetSegment.CalculateControlMatrix(zero, vector9, vector10, zero5, zero, vector9, vector10, zero5, thisNode.m_position, vScale);
                data.m_dataMatrix1             = NetSegment.CalculateControlMatrix(zero2, vector11, vector12, zero6, zero2, vector11, vector12, zero6, thisNode.m_position, vScale);
                data.m_dataVector0             = new Vector4(0.5f / info.m_halfWidth, 1f / info.m_segmentLength, 0.5f - info.m_pavementWidth / info.m_halfWidth * 0.5f, info.m_pavementWidth / info.m_halfWidth * 0.5f);
                data.m_dataVector1             = centerPos - data.m_position;

                if ((thisNode.m_flags & NetNode.Flags.Junction) == NetNode.Flags.None)
                {
                    data.m_dataVector1.w = (data.m_dataMatrix0.m33 + data.m_extraData.m_dataMatrix2.m33 + data.m_extraData.m_dataMatrix3.m33 + data.m_dataMatrix1.m33) * 0.25f;
                }
                else
                {
                    data.m_dataVector1.w = 0.01f;
                }

                data.m_dataVector2             = new Vector4(num6, y, num8, w);
                data.m_extraData.m_dataVector4 = RenderManager.GetColorLocation(65536u + (uint)nodeID);
            }
            else
            {
                centerPos.x = (zero.x + zero2.x) * 0.5f;
                centerPos.z = (zero.z + zero2.z) * 0.5f;
                vector      = zero2;
                vector2     = zero;
                a           = zero4;
                a2          = zero3;
                float   d        = Mathf.Min(info.m_halfWidth * 1.33333337f, 16f);
                Vector3 vector13 = zero - zero3 * d;
                Vector3 vector14 = vector - a * d;
                Vector3 vector15 = zero2 - zero4 * d;
                Vector3 vector16 = vector2 - a2 * d;
                Vector3 vector17 = zero + zero3 * d;
                Vector3 vector18 = vector + a * d;
                Vector3 vector19 = zero2 + zero4 * d;
                Vector3 vector20 = vector2 + a2 * d;
                data.m_dataMatrix0             = NetSegment.CalculateControlMatrix(zero, vector13, vector14, vector, zero, vector13, vector14, vector, thisNode.m_position, vScale);
                data.m_extraData.m_dataMatrix2 = NetSegment.CalculateControlMatrix(zero2, vector19, vector20, vector2, zero2, vector19, vector20, vector2, thisNode.m_position, vScale);
                data.m_extraData.m_dataMatrix3 = NetSegment.CalculateControlMatrix(zero, vector17, vector18, vector, zero, vector17, vector18, vector, thisNode.m_position, vScale);
                data.m_dataMatrix1             = NetSegment.CalculateControlMatrix(zero2, vector15, vector16, vector2, zero2, vector15, vector16, vector2, thisNode.m_position, vScale);
                data.m_dataMatrix0.SetRow(3, data.m_dataMatrix0.GetRow(3) + new Vector4(0.2f, 0.2f, 0.2f, 0.2f));
                data.m_extraData.m_dataMatrix2.SetRow(3, data.m_extraData.m_dataMatrix2.GetRow(3) + new Vector4(0.2f, 0.2f, 0.2f, 0.2f));
                data.m_extraData.m_dataMatrix3.SetRow(3, data.m_extraData.m_dataMatrix3.GetRow(3) + new Vector4(0.2f, 0.2f, 0.2f, 0.2f));
                data.m_dataMatrix1.SetRow(3, data.m_dataMatrix1.GetRow(3) + new Vector4(0.2f, 0.2f, 0.2f, 0.2f));
                data.m_dataVector0             = new Vector4(0.5f / info.m_halfWidth, 1f / info.m_segmentLength, 0.5f - info.m_pavementWidth / info.m_halfWidth * 0.5f, info.m_pavementWidth / info.m_halfWidth * 0.5f);
                data.m_dataVector1             = centerPos - data.m_position;
                data.m_dataVector1.w           = (data.m_dataMatrix0.m33 + data.m_extraData.m_dataMatrix2.m33 + data.m_extraData.m_dataMatrix3.m33 + data.m_dataMatrix1.m33) * 0.25f;
                data.m_dataVector2             = new Vector4(info.m_pavementWidth / info.m_halfWidth * 0.5f, 1f, info.m_pavementWidth / info.m_halfWidth * 0.5f, 1f);
                data.m_extraData.m_dataVector4 = RenderManager.GetColorLocation(65536u + (uint)nodeID);
            }
            data.m_dataInt0     = segmentIndex;
            data.m_dataColor0   = info.m_color;
            data.m_dataColor0.a = 0f;
            if (info.m_requireSurfaceMaps)
            {
                Singleton <TerrainManager> .instance.GetSurfaceMapping(data.m_position, out data.m_dataTexture0, out data.m_dataTexture1, out data.m_dataVector3);
            }
            instanceIndex = (uint)data.m_nextInstance;
        }
Example #12
0
    // Token: 0x060034D0 RID: 13520 RVA: 0x0023E078 File Offset: 0x0023C478
    public static void CalculateNode(ref NetNode This, ushort nodeID)
    {
        if (This.m_flags == NetNode.Flags.None)
        {
            return;
        }
        NetManager netMan                      = Singleton <NetManager> .instance;
        Vector3    DirFirst                    = Vector3.zero;
        int        iSegment                    = 0;
        int        ConnectCount                = 0;
        bool       hasSegments                 = false;
        bool       canBeMiddle                 = false;
        bool       bCompatibleButNodeMiddle    = false;
        bool       isAsymForward               = false;
        bool       isAsymBackward              = false;
        bool       needsJunctionFlag           = false;
        bool       hasCurvedSegment            = false;
        bool       hasStraightSegment          = false;
        bool       bCompatibleAndStart2End     = false;
        bool       allConnectedSegmentsAreFlat = true;
        bool       CanModify                   = true;
        bool       bHasDetailMapping           = Singleton <TerrainManager> .instance.HasDetailMapping(This.m_position);

        NetInfo prevInfo = null;
        int     prev_backwardVehicleLaneCount  = 0;
        int     prev_m_forwardVehicleLaneCount = 0;
        NetInfo infoNode = null;
        float   num5     = -1E+07f;

        for (int i = 0; i < 8; i++)
        {
            ushort segmentID = This.GetSegment(i);
            if (segmentID != 0)
            {
                NetInfo infoSegment      = netMan.m_segments.m_buffer[segmentID].Info;
                float   nodeInfoPriority = infoSegment.m_netAI.GetNodeInfoPriority(segmentID, ref netMan.m_segments.m_buffer[segmentID]);
                if (nodeInfoPriority > num5)
                {
                    infoSegment = infoSegment;
                    num5        = nodeInfoPriority;
                }
            }
        }
        if (infoNode == null)
        {
            infoNode = This.Info;
        }
        if (infoNode != This.Info)
        {
            This.Info = infoNode;
            Singleton <NetManager> .instance.UpdateNodeColors(nodeID);

            if (!infoNode.m_canDisable)
            {
                This.m_flags &= ~NetNode.Flags.Disabled;
            }
        }
        bool bStartNodeFirst = false;

        for (int j = 0; j < 8; j++)
        {
            ushort segmentID = This.GetSegment(j);
            if (segmentID != 0)
            {
                iSegment++;
                ushort    startNodeID     = netMan.m_segments.m_buffer[segmentID].m_startNode;
                ushort    endNodeID       = netMan.m_segments.m_buffer[segmentID].m_endNode;
                Vector3   startDirection  = netMan.m_segments.m_buffer[segmentID].m_startDirection;
                Vector3   endDirection    = netMan.m_segments.m_buffer[segmentID].m_endDirection;
                bool      bStartNode      = nodeID == startNodeID;
                Vector3   currentDir      = (!bStartNode) ? endDirection : startDirection;
                NetInfo   infoSegment     = netMan.m_segments.m_buffer[segmentID].Info;
                ItemClass connectionClass = infoSegment.GetConnectionClass();
                if (!infoSegment.m_netAI.CanModify())
                {
                    CanModify = false;
                }
                int backwardVehicleLaneCount;
                int forwardVehicleLaneCount;
                if (bStartNode == ((netMan.m_segments.m_buffer[segmentID].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None))
                {
                    backwardVehicleLaneCount = infoSegment.m_backwardVehicleLaneCount;
                    forwardVehicleLaneCount  = infoSegment.m_forwardVehicleLaneCount;
                }
                else
                {
                    backwardVehicleLaneCount = infoSegment.m_forwardVehicleLaneCount;
                    forwardVehicleLaneCount  = infoSegment.m_backwardVehicleLaneCount;
                }
                for (int k = j + 1; k < 8; k++)
                {
                    ushort segmentID2 = This.GetSegment(k);
                    if (segmentID2 != 0)
                    {
                        NetInfo   infoSegment2     = netMan.m_segments.m_buffer[segmentID2].Info;
                        ItemClass connectionClass2 = infoSegment2.GetConnectionClass();
                        if (connectionClass2.m_service == connectionClass.m_service || (infoSegment2.m_nodeConnectGroups & infoSegment.m_connectGroup) != NetInfo.ConnectGroup.None || (infoSegment.m_nodeConnectGroups & infoSegment2.m_connectGroup) != NetInfo.ConnectGroup.None)
                        {
                            bool    bStartNode2   = nodeID == netMan.m_segments.m_buffer[segmentID2].m_startNode;
                            Vector3 dir2          = (!bStartNode2) ? netMan.m_segments.m_buffer[segmentID2].m_endDirection : netMan.m_segments.m_buffer[segmentID2].m_startDirection;
                            float   dot2          = currentDir.x * dir2.x + currentDir.z * dir2.z;
                            float   turnThreshold = 0.01f - Mathf.Min(infoSegment.m_maxTurnAngleCos, infoSegment2.m_maxTurnAngleCos);
                            if (dot2 < turnThreshold)
                            {
                                if ((infoSegment.m_requireDirectRenderers && (infoSegment.m_nodeConnectGroups == NetInfo.ConnectGroup.None || (infoSegment.m_nodeConnectGroups & infoSegment2.m_connectGroup) != NetInfo.ConnectGroup.None)) || (infoSegment2.m_requireDirectRenderers && (infoSegment2.m_nodeConnectGroups == NetInfo.ConnectGroup.None || (infoSegment2.m_nodeConnectGroups & infoSegment.m_connectGroup) != NetInfo.ConnectGroup.None)))
                                {
                                    ConnectCount++;
                                }
                            }
                            else
                            {
                                needsJunctionFlag = true;
                            }
                        }
                        else
                        {
                            needsJunctionFlag = true;
                        }
                    }
                }

                if (netMan.m_nodes.m_buffer[startNodeID].m_elevation != netMan.m_nodes.m_buffer[endNodeID].m_elevation)
                {
                    allConnectedSegmentsAreFlat = false;
                }

                Vector3 startPos = netMan.m_nodes.m_buffer[startNodeID].m_position;
                Vector3 endPos   = netMan.m_nodes.m_buffer[endNodeID].m_position;
                if (bStartNode)
                {
                    bHasDetailMapping = (bHasDetailMapping && Singleton <TerrainManager> .instance.HasDetailMapping(endPos));
                }
                else
                {
                    bHasDetailMapping = (bHasDetailMapping && Singleton <TerrainManager> .instance.HasDetailMapping(startPos));
                }

                if (NetSegment.IsStraight(startPos, startDirection, endPos, endDirection))
                {
                    hasStraightSegment = true;
                }
                else
                {
                    hasCurvedSegment = true;
                }

                if (iSegment == 1)
                {
                    bStartNodeFirst = bStartNode;
                    DirFirst        = currentDir;
                    hasSegments     = true;
                }
                else if (iSegment == 2 && infoSegment.IsCombatible(prevInfo) && infoSegment.IsCombatible(infoNode) && (backwardVehicleLaneCount != 0) == (prev_m_forwardVehicleLaneCount != 0) && (forwardVehicleLaneCount != 0) == (prev_backwardVehicleLaneCount != 0))
                {
                    float dot = DirFirst.x * currentDir.x + DirFirst.z * currentDir.z;
                    if (backwardVehicleLaneCount != prev_m_forwardVehicleLaneCount || forwardVehicleLaneCount != prev_backwardVehicleLaneCount)
                    {
                        if (backwardVehicleLaneCount > forwardVehicleLaneCount)
                        {
                            isAsymForward = true;
                        }
                        else
                        {
                            isAsymBackward = true;
                        }
                        bCompatibleButNodeMiddle = true;
                    }
                    else if (dot < -0.999f) // straight.
                    {
                        canBeMiddle = true;
                    }
                    else
                    {
                        bCompatibleButNodeMiddle = true;
                    }
                    bCompatibleAndStart2End = (bStartNode != bStartNodeFirst);
                }
                else
                {
                    needsJunctionFlag = true;
                }
                prevInfo = infoSegment;
                prev_backwardVehicleLaneCount  = backwardVehicleLaneCount;
                prev_m_forwardVehicleLaneCount = forwardVehicleLaneCount;
            }
        }
        if (!infoNode.m_enableMiddleNodes && canBeMiddle)
        {
            bCompatibleButNodeMiddle = true;
        }
        if (!infoNode.m_enableBendingNodes && bCompatibleButNodeMiddle)
        {
            needsJunctionFlag = true;
        }
        if (infoNode.m_requireContinuous && (This.m_flags & NetNode.Flags.Untouchable) != NetNode.Flags.None)
        {
            needsJunctionFlag = true;
        }
        if (infoNode.m_requireContinuous && !bCompatibleAndStart2End && (canBeMiddle || bCompatibleButNodeMiddle))
        {
            needsJunctionFlag = true;
        }
        NetNode.Flags flags = This.m_flags & ~(NetNode.Flags.End | NetNode.Flags.Middle | NetNode.Flags.Bend | NetNode.Flags.Junction | NetNode.Flags.Moveable | NetNode.Flags.AsymForward | NetNode.Flags.AsymBackward);
        if ((flags & NetNode.Flags.Outside) != NetNode.Flags.None)
        {
            This.m_flags = flags;
        }
        else if (needsJunctionFlag)
        {
            This.m_flags = (flags | NetNode.Flags.Junction);
        }
        else if (bCompatibleButNodeMiddle)
        {
            if (isAsymForward)
            {
                flags |= NetNode.Flags.AsymForward;
            }
            if (isAsymBackward)
            {
                flags |= NetNode.Flags.AsymBackward;
            }
            This.m_flags = (flags | NetNode.Flags.Bend);
        }
        else if (canBeMiddle)
        {
            if ((!hasCurvedSegment || !hasStraightSegment) && (This.m_flags & (NetNode.Flags.Untouchable | NetNode.Flags.Double)) == NetNode.Flags.None && allConnectedSegmentsAreFlat && CanModify)
            {
                flags |= NetNode.Flags.Moveable;
            }
            This.m_flags = (flags | NetNode.Flags.Middle);
        }
        else if (hasSegments)
        {
            if ((This.m_flags & NetNode.Flags.Untouchable) == NetNode.Flags.None && allConnectedSegmentsAreFlat && CanModify && infoNode.m_enableMiddleNodes)
            {
                flags |= NetNode.Flags.Moveable;
            }
            This.m_flags = (flags | NetNode.Flags.End);
        }
        else
        {
            This.m_flags = flags;
        }
        This.m_heightOffset = (byte)((!bHasDetailMapping && infoNode.m_requireSurfaceMaps) ? 64 : 0);
        This.m_connectCount = (byte)ConnectCount;
        BuildingInfo newBuilding;
        float        heightOffset;

        infoNode.m_netAI.GetNodeBuilding(nodeID, ref This, out newBuilding, out heightOffset);
        This.UpdateBuilding(nodeID, newBuilding, heightOffset);
    }
Example #13
0
    // NetNode
    // Token: 0x060034C6 RID: 13510 RVA: 0x0023D1EC File Offset: 0x0023B5EC

    /// <param name="centerPos">position between left corner and right corner of segmentID (or something like that).</param>
    private static void RefreshJunctionData(ref NetNode This, ushort nodeID, int segmentIndex, ushort SegmentID, Vector3 centerPos, ref uint instanceIndex, ref RenderManager.Instance data)
    {
        Vector3 cornerPos_right = Vector3.zero, cornerDir_right = Vector3.zero, cornerPos_left = Vector3.zero, cornerDir_left = Vector3.zero,
                cornerPosA_right = Vector3.zero, cornerDirA_right = Vector3.zero, cornerPosA_left = Vector3.zero, cornerDirA_left = Vector3.zero,
                cornerPosB_right = Vector3.zero, cornerDirB_right = Vector3.zero, cornerPosB_left = Vector3.zero, cornerDirB_left = Vector3.zero;

        NetManager instance = Singleton <NetManager> .instance;

        data.m_position    = This.m_position;
        data.m_rotation    = Quaternion.identity;
        data.m_initialized = true;
        NetSegment segment         = SegmentID.ToSegment();
        NetInfo    info            = segment.Info;
        float      vscale          = info.m_netAI.GetVScale();
        ItemClass  connectionClass = info.GetConnectionClass();
        bool       bStartNode      = nodeID == segment.m_startNode;
        Vector3    dir             = !bStartNode ? segment.m_endDirection : segment.m_startDirection;
        float      dot_A           = -4f;
        float      dot_B           = -4f;
        ushort     segmentID_A     = 0;
        ushort     segmentID_B     = 0;

        for (int i = 0; i < 8; i++)
        {
            ushort segmentID2 = This.GetSegment(i);
            if (segmentID2 != 0 && segmentID2 != SegmentID)
            {
                NetInfo   info2            = instance.m_segments.m_buffer[(int)segmentID2].Info;
                ItemClass connectionClass2 = info2.GetConnectionClass();
                if (connectionClass.m_service == connectionClass2.m_service)
                {
                    NetSegment segment2    = segmentID2.ToSegment();
                    bool       bStartNode2 = nodeID != segment2.m_startNode;
                    Vector3    dir2        = !bStartNode2 ? segment2.m_endDirection : segment2.m_startDirection;
                    float      dot         = dir.x * dir2.x + dir.z * dir2.z;
                    float      determinent = dir2.z * dir.x - dir2.x * dir.z;
                    bool       bRight      = determinent > 0;
                    bool       bWide       = dot < 0;
                    // 180 -> det=0 dot=-1
                    if (!bRight)
                    {
                        if (dot > dot_A) // most accute
                        {
                            dot_A       = dot;
                            segmentID_A = segmentID2;
                        }
                        dot = -2f - dot;
                        if (dot > dot_B) // widest
                        {
                            dot_B       = dot;
                            segmentID_B = segmentID2;
                        }
                    }
                    else
                    {
                        if (dot > dot_B) // most accute
                        {
                            dot_B       = dot;
                            segmentID_B = segmentID2;
                        }
                        dot = -2f - dot;
                        if (dot > dot_A) // widest
                        {
                            dot_A       = dot;
                            segmentID_A = segmentID2;
                        }
                    }
                }
            }
        }
        segment.CalculateCorner(SegmentID, true, bStartNode, false, out cornerPos_right, out cornerDir_right, out _);
        segment.CalculateCorner(SegmentID, true, bStartNode, true, out cornerPos_left, out cornerDir_left, out _);
        if (segmentID_A != 0 && segmentID_B != 0)
        {
            float pavementRatio_avgA = info.m_pavementWidth / info.m_halfWidth * 0.5f;
            float averageWidthA      = 1f;
            if (segmentID_A != 0)
            {
                NetSegment segment_A = instance.m_segments.m_buffer[(int)segmentID_A];
                NetInfo    infoA     = segment_A.Info;
                bStartNode = (segment_A.m_startNode == nodeID);
                segment_A.CalculateCorner(segmentID_A, true, bStartNode, true, out cornerPosA_right, out cornerDirA_right, out _);
                segment_A.CalculateCorner(segmentID_A, true, bStartNode, false, out cornerPosA_left, out cornerDirA_left, out _);
                float pavementRatioA = infoA.m_pavementWidth / infoA.m_halfWidth * 0.5f;
                pavementRatio_avgA = (pavementRatio_avgA + pavementRatioA) * 0.5f;
                averageWidthA      = 2f * info.m_halfWidth / (info.m_halfWidth + infoA.m_halfWidth);
            }
            float pavementRatio_avgB = info.m_pavementWidth / info.m_halfWidth * 0.5f;
            float averageWithB       = 1f;
            if (segmentID_B != 0)
            {
                NetSegment segment_B = instance.m_segments.m_buffer[(int)segmentID_B];
                NetInfo    infoB     = segment_B.Info;
                bStartNode = (segment_B.m_startNode == nodeID);
                segment_B.CalculateCorner(segmentID_B, true, bStartNode, true, out cornerPosB_right, out cornerDirB_right, out _);
                segment_B.CalculateCorner(segmentID_B, true, bStartNode, false, out cornerPosB_left, out cornerDirB_left, out _);
                float pavementRatioB = infoB.m_pavementWidth / infoB.m_halfWidth * 0.5f;
                pavementRatio_avgB = (pavementRatio_avgB + pavementRatioB) * 0.5f;
                averageWithB       = 2f * info.m_halfWidth / (info.m_halfWidth + infoB.m_halfWidth);
            }

            Bezier3 bezierA_right = new Bezier3
            {
                a = cornerPos_right,
                d = cornerPosA_right,
            };

            NetSegment.CalculateMiddlePoints(bezierA_right.a, -cornerDir_right, bezierA_right.d, -cornerDirA_right, true, true, out bezierA_right.b, out bezierA_right.c);
            NetSegment.CalculateMiddlePoints(cornerPos_left, -cornerDir_left, cornerPosA_left, -cornerDirA_left, true, true, out var cpoint2_Aleft, out var cpoint3_Aleft);
            NetSegment.CalculateMiddlePoints(cornerPos_right, -cornerDir_right, cornerPosB_right, -cornerDirB_right, true, true, out var cpoint2_Bright, out var cpoint3_Bright);
            NetSegment.CalculateMiddlePoints(cornerPos_left, -cornerDir_left, cornerPosB_left, -cornerDirB_left, true, true, out var cpoint2_Bleft, out var cpoint3_Bleft);

            data.m_dataMatrix0             = NetSegment.CalculateControlMatrix(bezierA_right.a, bezierA_right.b, bezierA_right.c, bezierA_right.d, bezierA_right.a, bezierA_right.b, bezierA_right.c, bezierA_right.d, This.m_position, vscale);
            data.m_extraData.m_dataMatrix2 = NetSegment.CalculateControlMatrix(cornerPos_left, cpoint2_Aleft, cpoint3_Aleft, cornerPosA_left, cornerPos_left, cpoint2_Aleft, cpoint3_Aleft, cornerPosA_left, This.m_position, vscale);
            data.m_extraData.m_dataMatrix3 = NetSegment.CalculateControlMatrix(cornerPos_right, cpoint2_Bright, cpoint3_Bright, cornerPosB_right, cornerPos_right, cpoint2_Bright, cpoint3_Bright, cornerPosB_right, This.m_position, vscale);
            data.m_dataMatrix1             = NetSegment.CalculateControlMatrix(cornerPos_left, cpoint2_Bleft, cpoint3_Bleft, cornerPosB_left, cornerPos_left, cpoint2_Bleft, cpoint3_Bleft, cornerPosB_left, This.m_position, vscale);

            // Vector4(1/width | 1/length | 0.5 - pavement/width | pavement/width )
            data.m_dataVector0   = new Vector4(0.5f / info.m_halfWidth, 1f / info.m_segmentLength, 0.5f - info.m_pavementWidth / info.m_halfWidth * 0.5f, info.m_pavementWidth / info.m_halfWidth * 0.5f);
            data.m_dataVector1   = centerPos - data.m_position;
            data.m_dataVector1.w = (data.m_dataMatrix0.m31 + data.m_dataMatrix0.m32 + data.m_extraData.m_dataMatrix2.m31 + data.m_extraData.m_dataMatrix2.m32 + data.m_extraData.m_dataMatrix3.m31 + data.m_extraData.m_dataMatrix3.m32 + data.m_dataMatrix1.m31 + data.m_dataMatrix1.m32) * 0.125f;
            data.m_dataVector2   = new Vector4(pavementRatio_avgA, averageWidthA, pavementRatio_avgB, averageWithB);
        }
        else
        {
            centerPos.x = (cornerPos_right.x + cornerPos_left.x) * 0.5f;
            centerPos.z = (cornerPos_right.z + cornerPos_left.z) * 0.5f;
            var cornerPos_left_prev  = cornerPos_left;
            var cornerPos_right_prev = cornerPos_right;
            cornerDirB_right = cornerDir_left;
            cornerDirB_left  = cornerDir_right;
            float   d        = info.m_netAI.GetEndRadius() * 1.33333337f;
            Vector3 vector13 = cornerPos_right - cornerDir_right * d;
            Vector3 vector14 = cornerPos_left_prev - cornerDirB_right * d;
            Vector3 vector15 = cornerPos_left - cornerDir_left * d;
            Vector3 vector16 = cornerPos_right_prev - cornerDirB_left * d;
            Vector3 vector17 = cornerPos_right + cornerDir_right * d;
            Vector3 vector18 = cornerPos_left_prev + cornerDirB_right * d;
            Vector3 vector19 = cornerPos_left + cornerDir_left * d;
            Vector3 vector20 = cornerPos_right_prev + cornerDirB_left * d;
            data.m_dataMatrix0             = NetSegment.CalculateControlMatrix(cornerPos_right, vector13, vector14, cornerPos_left_prev, cornerPos_right, vector13, vector14, cornerPos_left_prev, This.m_position, vscale);
            data.m_extraData.m_dataMatrix2 = NetSegment.CalculateControlMatrix(cornerPos_left, vector19, vector20, cornerPos_right_prev, cornerPos_left, vector19, vector20, cornerPos_right_prev, This.m_position, vscale);
            data.m_extraData.m_dataMatrix3 = NetSegment.CalculateControlMatrix(cornerPos_right, vector17, vector18, cornerPos_left_prev, cornerPos_right, vector17, vector18, cornerPos_left_prev, This.m_position, vscale);
            data.m_dataMatrix1             = NetSegment.CalculateControlMatrix(cornerPos_left, vector15, vector16, cornerPos_right_prev, cornerPos_left, vector15, vector16, cornerPos_right_prev, This.m_position, vscale);
            data.m_dataMatrix0.SetRow(3, data.m_dataMatrix0.GetRow(3) + new Vector4(0.2f, 0.2f, 0.2f, 0.2f));
            data.m_extraData.m_dataMatrix2.SetRow(3, data.m_extraData.m_dataMatrix2.GetRow(3) + new Vector4(0.2f, 0.2f, 0.2f, 0.2f));
            data.m_extraData.m_dataMatrix3.SetRow(3, data.m_extraData.m_dataMatrix3.GetRow(3) + new Vector4(0.2f, 0.2f, 0.2f, 0.2f));
            data.m_dataMatrix1.SetRow(3, data.m_dataMatrix1.GetRow(3) + new Vector4(0.2f, 0.2f, 0.2f, 0.2f));
            data.m_dataVector0   = new Vector4(0.5f / info.m_halfWidth, 1f / info.m_segmentLength, 0.5f - info.m_pavementWidth / info.m_halfWidth * 0.5f, info.m_pavementWidth / info.m_halfWidth * 0.5f);
            data.m_dataVector1   = centerPos - data.m_position;
            data.m_dataVector1.w = (data.m_dataMatrix0.m31 + data.m_dataMatrix0.m32 + data.m_extraData.m_dataMatrix2.m31 + data.m_extraData.m_dataMatrix2.m32 + data.m_extraData.m_dataMatrix3.m31 + data.m_extraData.m_dataMatrix3.m32 + data.m_dataMatrix1.m31 + data.m_dataMatrix1.m32) * 0.125f;
            data.m_dataVector2   = new Vector4(info.m_pavementWidth / info.m_halfWidth * 0.5f, 1f, info.m_pavementWidth / info.m_halfWidth * 0.5f, 1f);
        }
        Vector4 colorLocation;
        Vector4 vector21;

        if (NetNode.BlendJunction(nodeID))
        {
            colorLocation = RenderManager.GetColorLocation(86016u + (uint)nodeID);
            vector21      = colorLocation;
        }
        else
        {
            colorLocation = RenderManager.GetColorLocation((uint)(49152 + SegmentID));
            vector21      = RenderManager.GetColorLocation(86016u + (uint)nodeID);
        }
        data.m_extraData.m_dataVector4 = new Vector4(colorLocation.x, colorLocation.y, vector21.x, vector21.y);
        data.m_dataInt0     = segmentIndex;
        data.m_dataColor0   = info.m_color;
        data.m_dataColor0.a = 0f;
        data.m_dataFloat0   = Singleton <WeatherManager> .instance.GetWindSpeed(data.m_position);

        if (info.m_requireSurfaceMaps)
        {
            Singleton <TerrainManager> .instance.GetSurfaceMapping(data.m_position, out data.m_dataTexture0, out data.m_dataTexture1, out data.m_dataVector3);
        }
        instanceIndex = (uint)data.m_nextInstance;
    }