public static bool FindPathPosition(Vector3 position, ItemClass.Service service, NetInfo.LaneType laneType, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, bool requireConnect, float maxDistance, out PathUnit.Position pathPos, RoadManager.VehicleType vehicleType) { PathUnit.Position position2; float num; float num2; return CustomPathManager.FindPathPosition(position, service, laneType, vehicleTypes, allowUnderground, requireConnect, maxDistance, out pathPos, out position2, out num, out num2, vehicleType); }
public static NetInfo[] GetSubPrefabs(NetInfo prefab) { var subPrefabs = new NetInfo[NET_TYPE_NAMES.Length]; if (prefab.m_netAI is TrainTrackAI) { var netAI = (TrainTrackAI) prefab.m_netAI; subPrefabs[(int)NetType.Tunnel] = netAI.m_tunnelInfo; subPrefabs[(int)NetType.Ground] = netAI.m_info; subPrefabs[(int)NetType.Elevated] = netAI.m_elevatedInfo; subPrefabs[(int)NetType.Bridge] = netAI.m_bridgeInfo; } else if (prefab.m_netAI is RoadAI) { var netAI = (RoadAI) prefab.m_netAI; subPrefabs[(int)NetType.Tunnel] = netAI.m_tunnelInfo; subPrefabs[(int)NetType.Ground] = netAI.m_info; subPrefabs[(int)NetType.Elevated] = netAI.m_elevatedInfo; subPrefabs[(int)NetType.Bridge] = netAI.m_bridgeInfo; } else if (prefab.m_netAI is PedestrianPathAI) { var netAI = (PedestrianPathAI) prefab.m_netAI; subPrefabs[(int)NetType.Tunnel] = netAI.m_tunnelInfo; subPrefabs[(int)NetType.Ground] = netAI.m_info; subPrefabs[(int)NetType.Elevated] = netAI.m_elevatedInfo; subPrefabs[(int)NetType.Bridge] = netAI.m_bridgeInfo; } return subPrefabs; }
/// <summary> /// Determines the allowed vehicle types for the given segment and lane. /// </summary> /// <param name="segmentId"></param> /// <param name="laneIndex"></param> /// <param name="laneId"></param> /// <param name="laneInfo"></param> /// <returns></returns> internal static ExtVehicleType GetAllowedVehicleTypes(ushort segmentId, uint laneIndex, uint laneId, NetInfo.Lane laneInfo) { if (Flags.IsInitDone()) { ExtVehicleType?[] fastArray = Flags.laneAllowedVehicleTypesArray[segmentId]; if (fastArray != null && fastArray.Length > laneIndex && fastArray[laneIndex] != null) { return (ExtVehicleType)fastArray[laneIndex]; } } ExtVehicleType ret = ExtVehicleType.None; if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Bicycle) != VehicleInfo.VehicleType.None) ret |= ExtVehicleType.Bicycle; if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Tram) != VehicleInfo.VehicleType.None) ret |= ExtVehicleType.Tram; if ((laneInfo.m_laneType & NetInfo.LaneType.TransportVehicle) != NetInfo.LaneType.None) ret |= ExtVehicleType.RoadPublicTransport | ExtVehicleType.Emergency; else if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None) ret |= ExtVehicleType.RoadVehicle; if ((laneInfo.m_vehicleType & (VehicleInfo.VehicleType.Train | VehicleInfo.VehicleType.Metro)) != VehicleInfo.VehicleType.None) ret |= ExtVehicleType.RailVehicle; if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Ship) != VehicleInfo.VehicleType.None) ret |= ExtVehicleType.Ship; if ((laneInfo.m_vehicleType & VehicleInfo.VehicleType.Plane) != VehicleInfo.VehicleType.None) ret |= ExtVehicleType.Plane; return ret; }
public new bool CreatePath(out uint unit, ref Randomizer randomizer, uint buildIndex, PathUnit.Position startPosA, PathUnit.Position startPosB, PathUnit.Position endPosA, PathUnit.Position endPosB, PathUnit.Position vehiclePosition, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, float maxLength, bool isHeavyVehicle, bool ignoreBlocked, bool stablePath, bool skipQueue, ItemClass.Service vehicleService) { while (!Monitor.TryEnter(this.m_bufferLock, SimulationManager.SYNCHRONIZE_TIMEOUT)) { } uint num; try { if (!this.m_pathUnits.CreateItem(out num, ref randomizer)) { unit = 0u; bool result = false; return result; } this.m_pathUnitCount = (int)(this.m_pathUnits.ItemCount() - 1u); } finally { Monitor.Exit(this.m_bufferLock); } unit = num; byte simulationFlags = createSimulationFlag(isHeavyVehicle, ignoreBlocked, stablePath, vehicleService); assignPathProperties(unit, buildIndex, startPosA, startPosB, endPosA, endPosB, vehiclePosition, laneTypes, vehicleTypes, maxLength, simulationFlags); return findShortestPath(unit, skipQueue); }
/// <summary> /// Determines the currently set speed limit for the given segment and lane direction in terms of discrete speed limit levels. /// An in-game speed limit of 2.0 (e.g. on highway) is hereby translated into a discrete speed limit value of 100 (km/h). /// </summary> /// <param name="segmentId"></param> /// <param name="dir"></param> /// <returns></returns> public static ushort GetCustomSpeedLimit(ushort segmentId, NetInfo.Direction dir) { // calculate the currently set mean speed limit if (segmentId == 0) return 0; if ((Singleton<NetManager>.instance.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Created) == NetSegment.Flags.None) return 0; var segmentInfo = Singleton<NetManager>.instance.m_segments.m_buffer[segmentId].Info; uint curLaneId = Singleton<NetManager>.instance.m_segments.m_buffer[segmentId].m_lanes; int laneIndex = 0; float meanSpeedLimit = 0f; uint validLanes = 0; while (laneIndex < segmentInfo.m_lanes.Length && curLaneId != 0u) { NetInfo.Direction d = segmentInfo.m_lanes[laneIndex].m_direction; if ((segmentInfo.m_lanes[laneIndex].m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) == NetInfo.LaneType.None || d != dir) goto nextIter; ushort? setSpeedLimit = Flags.getLaneSpeedLimit(curLaneId); if (setSpeedLimit != null) meanSpeedLimit += ToGameSpeedLimit((ushort)setSpeedLimit); // custom speed limit else meanSpeedLimit += segmentInfo.m_lanes[laneIndex].m_speedLimit; // game default ++validLanes; nextIter: curLaneId = Singleton<NetManager>.instance.m_lanes.m_buffer[curLaneId].m_nextLane; laneIndex++; } if (validLanes > 0) meanSpeedLimit /= (float)validLanes; return ToCustomSpeedLimit(meanSpeedLimit); }
public static bool CreateSegment(NetManager _this, out ushort segmentID, ref Randomizer randomizer, NetInfo info, ushort startNode, ushort endNode, Vector3 startDirection, Vector3 endDirection, uint buildIndex, uint modifiedIndex, bool invert) { var ai = info.m_netAI as RoadAI; if (ai != null && ai.m_enableZoning) { var caller = new System.Diagnostics.StackFrame(1).GetMethod().Name; switch (caller) { case "MoveMiddleNode": // segment that was modified because user added network, apply style of previous segment newBlockColumnCount = MoveMiddleNode_releasedColumnCount >= 0 ? MoveMiddleNode_releasedColumnCount : InputThreadingExtension.userSelectedColumnCount; break; case "SplitSegment": // segment that was split by new node, apply style of previous segment newBlockColumnCount = SplitSegment_releasedColumnCount >= 0 ? SplitSegment_releasedColumnCount : InputThreadingExtension.userSelectedColumnCount; break; default: // unknown caller (e.g. new road placed), set to depth selected by user newBlockColumnCount = InputThreadingExtension.userSelectedColumnCount; SplitSegment_releasedColumnCount = -1; MoveMiddleNode_releasedColumnCount = -1; break; } } // Call original method CreateSegmentRedirector.Revert(); var success = _this.CreateSegment(out segmentID, ref randomizer, info, startNode, endNode, startDirection, endDirection, buildIndex, modifiedIndex, invert); CreateSegmentRedirector.Apply(); return success; }
public void BuildUp(NetInfo info, NetInfoVersion version) { /////////////////////////// // Texturing // /////////////////////////// SetupTextures(info, version); /////////////////////////// // Set up // /////////////////////////// info.m_createGravel = false; info.m_createPavement = true; info.m_setVehicleFlags = 0; /////////////////////////// // AI // /////////////////////////// var playerNetAI = info.GetComponent<PlayerNetAI>(); if (playerNetAI != null) { playerNetAI.m_constructionCost = playerNetAI.m_constructionCost * 3 / 2; playerNetAI.m_maintenanceCost = playerNetAI.m_maintenanceCost * 3 / 2; } }
// from CitizenAI public static bool FindPathPosition(ushort instanceID, ref CitizenInstance citizenData, Vector3 pos, NetInfo.LaneType laneTypes, VehicleInfo.VehicleType vehicleTypes, bool allowUnderground, out PathUnit.Position position) { position = default(PathUnit.Position); float num = 1E+10f; PathUnit.Position position2; PathUnit.Position position3; float num2; float num3; if (CustomPathManager.FindPathPosition(pos, ItemClass.Service.Road, laneTypes, vehicleTypes, allowUnderground, 32f, out position2, out position3, out num2, out num3, RoadManager.VehicleType.PassengerCar) && num2 < num) { num = num2; position = position2; } PathUnit.Position position4; PathUnit.Position position5; float num4; float num5; if (CustomPathManager.FindPathPosition(pos, ItemClass.Service.Beautification, laneTypes, vehicleTypes, allowUnderground, 32f, out position4, out position5, out num4, out num5, RoadManager.VehicleType.PassengerCar) && num4 < num) { num = num4; position = position4; } PathUnit.Position position6; PathUnit.Position position7; float num6; float num7; if ((citizenData.m_flags & CitizenInstance.Flags.CannotUseTransport) == CitizenInstance.Flags.None && CustomPathManager.FindPathPosition(pos, ItemClass.Service.PublicTransport, laneTypes, vehicleTypes, allowUnderground, 32f, out position6, out position7, out num6, out num7, RoadManager.VehicleType.PassengerCar) && num6 < num) { position = position6; } return position.m_segment != 0; }
public float GetActiveTreeDistance(NetInfo prefab, LanePosition position) { var segmentData = SegmentDataManager.Instance.GetActiveOptions(prefab); var result = 0f; if (segmentData != null && segmentData.Features.IsFlagSet(SegmentData.FeatureFlags.RepeatDistances)) { switch (position) { case LanePosition.Left: result = segmentData.RepeatDistances.x; break; case LanePosition.Middle: result = segmentData.RepeatDistances.y; break; case LanePosition.Right: result = segmentData.RepeatDistances.z; break; default: throw new ArgumentOutOfRangeException(nameof(position)); } } return result > 0f ? result : GetDefaultTreeDistance(prefab, position); }
//Test public static void AdjustElevation(ushort startNode, Vector3 vector, NetInfo netInfo) { NetManager nm = NetManager.instance; var node = nm.m_nodes.m_buffer[startNode]; float elevation = NetSegment.SampleTerrainHeight(netInfo, vector, false); byte ele = (byte)Mathf.Clamp(Mathf.RoundToInt(Math.Max(node.m_elevation, elevation)), 0, 255); float terrain = TerrainManager.instance.SampleRawHeightSmoothWithWater(node.m_position, false, 0f); node.m_elevation = ele; node.m_position = new Vector3(node.m_position.x, ele + terrain, node.m_position.z); if (elevation < 11f) { node.m_flags |= NetNode.Flags.OnGround; } else { node.m_flags &= ~NetNode.Flags.OnGround; UpdateSegment(node.m_segment0, elevation); UpdateSegment(node.m_segment1, elevation); UpdateSegment(node.m_segment2, elevation); UpdateSegment(node.m_segment3, elevation); UpdateSegment(node.m_segment4, elevation); UpdateSegment(node.m_segment5, elevation); UpdateSegment(node.m_segment6, elevation); UpdateSegment(node.m_segment7, elevation); } nm.m_nodes.m_buffer[startNode] = node; //Singleton<NetManager>.instance.UpdateNode(startNode); }
public SegmentData GetActiveOptions(NetInfo prefab) { var options = _assetMode ? _assetSegmentOptions : _selectedSegmentOptions; SegmentData segmentData; options.TryGetValue(prefab, out segmentData); return segmentData; }
public bool Populate(NetInfo prefab) { Populating = true; SelectedPrefab = prefab; var result = PopulateImpl(); Populating = false; return result; }
protected override bool IsServiceValid(NetInfo info) { if (info.GetService() == this.service) return true; if (this.isMapEditor) return info.GetService() == ItemClass.Service.PublicTransport; return false; }
public static void CalculateGuideLines(NetInfo netInfo, NetTool.ControlPoint startPoint, NetTool.ControlPoint endPoint, IList<GuideLine> resultList) { lock (SegmentCache) { var startPosition = startPoint.m_position; var endPosition = endPoint.m_position; //var segments = NetManager.instance.m_segments; //NetManager.instance.GetClosestSegments(endPosition, SegmentCache, out _segmentCacheCount); NetUtil.GetClosestSegments(netInfo, endPosition, SegmentCache, out _segmentCacheCount); SnapController.DebugPrint = String.Format("Closest Segment Count: {0}", _segmentCacheCount); var c = _segmentCacheCount; for (ushort i = 0; i < c; i++) { var segmentId = SegmentCache[i]; var s = NetManager.instance.m_segments.m_buffer[segmentId]; // Ensure they are part of the same network if (!NetUtil.AreSimilarClass(s.Info, netInfo)) continue; if ( Vector3Extensions.DistanceSquared(NetManager.instance.m_nodes.m_buffer[s.m_startNode].m_position, endPosition) > Settings.MaxGuideLineQueryDistanceSqr) continue; // Test the start and end of the segment // Check if the node can branch in the guide direction (angles less than 45deg or so should be discarded) if (CanNodeBranchInDirection(s.m_endNode, s.m_startDirection)) { var endNode = NetManager.instance.m_nodes.m_buffer[s.m_endNode]; TestLine(s.Info, startPosition, endPosition, endNode.m_position, endNode.m_position + s.m_startDirection.Flatten(), resultList, segmentId, s.m_endNode); } if (CanNodeBranchInDirection(s.m_startNode, s.m_endDirection)) { var startNode = NetManager.instance.m_nodes.m_buffer[s.m_startNode]; TestLine(s.Info, startPosition, endPosition, startNode.m_position, startNode.m_position + s.m_endDirection.Flatten(), resultList, segmentId, s.m_startNode); } } } }
public static bool AreSimilarClass(NetInfo i1, NetInfo i2) { if (i1 == i2) return true; if (i1 != null && i2 != null && i1.m_class.m_service == i2.m_class.m_service) return true; return false; }
public static void CreatePavement(NetInfo prefab) { if (prefab == null) { return; } prefab.m_createGravel = false; prefab.m_createRuining = false; prefab.m_createPavement = true; }
public static NetInfo ClonePrefab(NetInfo originalPrefab, string newName, Transform parentTransform) { var instance = Object.Instantiate(originalPrefab.gameObject); instance.name = newName; instance.transform.SetParent(parentTransform); instance.transform.localPosition = new Vector3(-7500, -7500, -7500); var newPrefab = instance.GetComponent<NetInfo>(); instance.SetActive(false); newPrefab.m_prefabInitialized = false; return newPrefab; }
public static void MakePedestrianLanesNarrow(NetInfo prefab) { if (prefab?.m_lanes == null) { return; } foreach (var lane in prefab.m_lanes.Where(lane => lane != null && lane.m_laneType == NetInfo.LaneType.Pedestrian)) { lane.m_width = 2; lane.m_position = Math.Sign(lane.m_position) * (4 + .5f * lane.m_width); } }
public static void SetHighwayProps(this NetInfo info, NetInfo highwayInfoTemplate) { var leftHwLane = highwayInfoTemplate .m_lanes .Where(l => l != null && l.m_laneProps != null && l.m_laneProps.name != null && l.m_laneProps.m_props != null) .FirstOrDefault(l => l.m_laneProps.name.ToLower().Contains("left")); var rightHwLane = highwayInfoTemplate .m_lanes .Where(l => l != null && l.m_laneProps != null && l.m_laneProps.name != null && l.m_laneProps.m_props != null) .FirstOrDefault(l => l.m_laneProps.name.ToLower().Contains("right")); foreach (var lane in info.m_lanes) { if (lane.m_laneProps != null && lane.m_laneProps.name != null) { if (leftHwLane != null) { if (lane.m_laneProps.name.ToLower().Contains("left")) { var newProps = ScriptableObject.CreateInstance<NetLaneProps>(); newProps.name = "Highway6L Left Props"; newProps.m_props = leftHwLane .m_laneProps .m_props .Select(p => p.ShallowClone()) .ToArray(); lane.m_laneProps = newProps; } } if (rightHwLane != null) { if (lane.m_laneProps.name.ToLower().Contains("right")) { var newProps = ScriptableObject.CreateInstance<NetLaneProps>(); newProps.name = "Highway6L Right Props"; newProps.m_props = rightHwLane .m_laneProps .m_props .Select(p => p.ShallowClone()) .ToArray(); lane.m_laneProps = newProps; } } } } }
public PropInfo GetActiveStreetLight(NetInfo prefab) { var segmentData = SegmentDataManager.Instance.GetActiveOptions(prefab); if (segmentData == null || !segmentData.Features.IsFlagSet(SegmentData.FeatureFlags.StreetLight)) { return GetDefaultStreetLight(prefab); } else { return segmentData.StreetLightPrefab; } }
public float GetActiveStreetLightDistance(NetInfo prefab) { var segmentData = SegmentDataManager.Instance.GetActiveOptions(prefab); if (segmentData != null && segmentData.Features.IsFlagSet(SegmentData.FeatureFlags.RepeatDistances) && segmentData.RepeatDistances.w > 0f) { return segmentData.RepeatDistances.w; } else { return GetDefaultStreetLightDistance(prefab); } }
public void BuildUp(NetInfo info, NetInfoVersion version) { /////////////////////////// // 3DModeling // /////////////////////////// info.Setup8mNoSwWoodMesh(version); /////////////////////////// // Texturing // /////////////////////////// if (version == NetInfoVersion.Ground) { info.SetupGroundNakedTextures(version); } else { info.SetupElevatedBoardWalkTextures(version); } /////////////////////////// // Set up // /////////////////////////// info.m_createGravel = true; info.m_createPavement = false; info.SetupTinyPed(version); if (version == NetInfoVersion.Ground) { info.m_setVehicleFlags = Vehicle.Flags.OnGravel; } /////////////////////////// // AI // /////////////////////////// var pedestrianVanilla = Prefabs.Find<NetInfo>(NetInfos.Vanilla.PED_PAVEMENT); switch (version) { case NetInfoVersion.Ground: { var vanillaplayerNetAI = pedestrianVanilla.GetComponent<PlayerNetAI>(); var playerNetAI = info.GetComponent<PlayerNetAI>(); if (playerNetAI != null) { playerNetAI.m_constructionCost = vanillaplayerNetAI.m_constructionCost; playerNetAI.m_maintenanceCost = vanillaplayerNetAI.m_maintenanceCost; } } break; } }
private bool IsRoadEligibleToPublicTransport(NetInfo info) { if (this.category == "PublicTransportTrain" && (info.m_vehicleTypes & VehicleInfo.VehicleType.Train) != VehicleInfo.VehicleType.None || this.category == "PublicTransportMetro" && (info.m_vehicleTypes & VehicleInfo.VehicleType.Metro) != VehicleInfo.VehicleType.None || this.category == "PublicTransportBus" && (info.m_laneTypes & NetInfo.LaneType.TransportVehicle) != NetInfo.LaneType.None) return true; if (this.category == "PublicTransportTram") return (info.m_vehicleTypes & VehicleInfo.VehicleType.Tram) != VehicleInfo.VehicleType.None; //begin mod if (this.category == "PublicTransportPlane") return (info.m_vehicleTypes & VehicleInfo.VehicleType.Plane) != VehicleInfo.VehicleType.None; if (this.category == "PublicTransportShip") return (info.m_vehicleTypes & VehicleInfo.VehicleType.Ship) != VehicleInfo.VehicleType.None; //end mod return false; }
public static NetInfo.Lane FindLane(this NetInfo info, NetInfo.LaneType predicate, bool crashOnNotFound = true) { var lane = info .m_lanes .FirstOrDefault(l => l.m_laneType == NetInfo.LaneType.Vehicle); if (lane == null) { if (crashOnNotFound) { throw new Exception("TFW: Lane not found"); } } return lane; }
void CopyAttributes(NetInfo.Lane lane) { this.m_position = lane.m_position; this.m_width = lane.m_width; this.m_verticalOffset = lane.m_verticalOffset; this.m_stopOffset = lane.m_stopOffset; this.m_speedLimit = lane.m_speedLimit; this.m_direction = lane.m_direction; this.m_laneType = lane.m_laneType; this.m_vehicleType = lane.m_vehicleType; this.m_laneProps = lane.m_laneProps; this.m_allowStop = lane.m_allowStop; this.m_useTerrainHeight = lane.m_useTerrainHeight; this.m_finalDirection = lane.m_finalDirection; this.m_similarLaneIndex = lane.m_similarLaneIndex; this.m_similarLaneCount = lane.m_similarLaneCount; }
/// <summary> /// Determines the average default speed limit for a given NetInfo object in terms of discrete speed limit levels. /// An in-game speed limit of 2.0 (e.g. on highway) is hereby translated into a discrete speed limit value of 100 (km/h). /// </summary> /// <param name="segmentInfo"></param> /// <param name="dir"></param> /// <returns></returns> public static ushort GetAverageDefaultCustomSpeedLimit(NetInfo segmentInfo, NetInfo.Direction? dir=null) { // calculate the currently set mean speed limit float meanSpeedLimit = 0f; uint validLanes = 0; for (int i = 0; i < segmentInfo.m_lanes.Length; ++i) { NetInfo.Direction d = segmentInfo.m_lanes[i].m_direction; if ((segmentInfo.m_lanes[i].m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) == NetInfo.LaneType.None || (dir != null && d != dir)) continue; meanSpeedLimit += segmentInfo.m_lanes[i].m_speedLimit; ++validLanes; } if (validLanes > 0) meanSpeedLimit /= (float)validLanes; return ToCustomSpeedLimit(meanSpeedLimit); }
public TreeInfo GetActiveTree(NetInfo prefab, LanePosition position) { var segmentData = SegmentDataManager.Instance.GetActiveOptions(prefab); if (segmentData == null || !segmentData.Features.IsFlagSet(position.ToTreeFeatureFlag())) { return GetDefaultTree(prefab, position); } else { switch (position) { case LanePosition.Left: return segmentData.TreeLeftPrefab; case LanePosition.Middle: return segmentData.TreeMiddlePrefab; case LanePosition.Right: return segmentData.TreeRightPrefab; default: throw new ArgumentOutOfRangeException(nameof(position)); } } }
public static void HandleAsymComplementarySegmentsFlags(NetInfo.Segment fSegment, NetInfo.Segment bSegment, LanesLayoutStyle lanesLayoutStyle) { switch (lanesLayoutStyle) { case LanesLayoutStyle.AsymL1R2: case LanesLayoutStyle.AsymL1R3: fSegment.m_forwardForbidden |= NetSegment.Flags.Invert; fSegment.m_backwardRequired |= NetSegment.Flags.Invert; bSegment.m_forwardRequired |= NetSegment.Flags.Invert; bSegment.m_backwardForbidden |= NetSegment.Flags.Invert; break; case LanesLayoutStyle.AsymL3R1: fSegment.m_forwardRequired |= NetSegment.Flags.Invert; fSegment.m_backwardForbidden |= NetSegment.Flags.Invert; bSegment.m_forwardForbidden |= NetSegment.Flags.Invert; bSegment.m_backwardRequired |= NetSegment.Flags.Invert; break; } }
private static void SetupTextures(NetInfo info, NetInfoVersion version) { switch (version) { case NetInfoVersion.Ground: info.SetAllSegmentsTexture( new TextureSet (null, @"Roads\Common\Textures\Plain\Ground_Segment__AlphaMap.png"), new LODTextureSet (@"Roads\Common\Textures\Plain\Ground_Segment_LOD__MainTex.png", @"Roads\Common\Textures\Plain\Ground_Segment_LOD__AlphaMap.png", @"Roads\Common\Textures\Plain\Ground_Segment_LOD__XYSMap.png")); foreach (var node in info.m_nodes) { if (node.m_flagsRequired == NetNode.Flags.Transition) { node.SetTextures( new TextureSet (null, @"Roads\Common\Textures\Plain\Ground_Trans__AlphaMap.png"), new LODTextureSet (@"Roads\Common\Textures\Plain\Ground_Trans_LOD__MainTex.png", @"Roads\Common\Textures\Plain\Ground_Trans_LOD__AlphaMap.png", @"Roads\Common\Textures\Plain\Ground_Trans_LOD__XYSMap.png")); } else { node.SetTextures( new TextureSet (null, @"Roads\Common\Textures\Plain\Ground_Segment__AlphaMap.png"), new LODTextureSet (@"Roads\Common\Textures\Plain\Ground_Node_LOD__MainTex.png", @"Roads\Common\Textures\Plain\Ground_Node_LOD__AlphaMap.png", @"Roads\Common\Textures\Plain\Ground_Node_LOD__XYSMap.png")); } } break; } }
public void Update() { var prefab = GetToolPrefab(); var alwaysVisible = Options.OptionsHolder.Options.alwaysVisible; if (prefab == null && !alwaysVisible) { NoPillarsUI.Hide(); if (currentPrefab == null && currentAlwaysVisible == alwaysVisible) { return; } Reset(); currentPrefab = null; if (Options.OptionsHolder.Options.resetOnHide) { NoPillarsUI.Reset(); } currentAlwaysVisible = alwaysVisible; } else { currentAlwaysVisible = alwaysVisible; NoPillarsUI.Show(); var collide = NoPillarsUI.Collide; var pillars = NoPillarsUI.Pillars; if (currentCollide == collide && currentPillars == pillars) { return; } Reset(); currentPrefab = prefab; currentPillars = pillars; currentCollide = collide; savedMetadata = new List<NetInfoExtensions.Metadata>(); foreach (var prefabToModify in Util.GetAllPrefabs()) { savedMetadata.Add(prefabToModify.GetMetadata()); prefabToModify.SetMetadata(collide, pillars); } } }
public static void HideCrossings0(Material material, Material segMaterial, NetInfo info, bool lod = false) { if (material == null) { throw new ArgumentNullException("material"); } //if (segMaterial == null) throw new ArgumentNullException("segMaterial"); if (info == null) { throw new ArgumentNullException("info"); } Texture2D tex, tex2; bool dump = false; #if DEBUG dump = false; #endif if (dump) { DumpUtils.Dump(info); } tex = material.TryGetTexture2D(ID_Defuse); Log.Debug($"material={material} tex={tex} h={tex?.height} w={tex?.width}"); if (tex != null) { if (dump) { DumpUtils.Dump(tex, info); } if (TextureCache.Contains(tex)) { tex = TextureCache[tex] as Texture2D; Log.Info("Texture cache hit: " + tex.name); } else { Log.Info("processing Defuse texture for " + tex.name); tex = tex.GetReadableCopy(); tex.CropAndStrech(); if (dump) { DumpUtils.Dump(tex, info); } tex.Finalize(lod); TextureCache[material.GetTexture(ID_Defuse)] = tex; } if (dump) { DumpUtils.Dump(tex, info); } material.SetTexture(ID_Defuse, tex); //Log.Info($"material={material} tex={tex} h={tex.height} w={tex.width}"); if (dump) { DumpUtils.Dump(tex, DumpUtils.GetFilePath(ID_Defuse, "node-processed", info)); } } tex = material.TryGetTexture2D(ID_APRMap); if (tex != null && tex.name != "RoadSmallNode-default-apr" && tex.name != "BasicRoad2_Junction-apr") { segMaterial = segMaterial ?? GetSegmentMaterial(info, ID_APRMap); tex2 = segMaterial?.TryGetTexture2D(ID_APRMap); if (tex != null && tex2 != null) { if (dump) { DumpUtils.Dump(tex, info); } if (dump) { DumpUtils.Dump(tex2, info); } if (TextureCache.Contains(tex)) { tex = TextureCache[tex] as Texture2D; Log.Info("Texture cache hit: " + tex.name); } else { Log.Info("processing APR texture for " + tex.name); bool linear = lod && !info.IsNExt(); tex = tex.GetReadableCopy(linear: linear); tex2 = tex2.GetReadableCopy(linear: linear); if (tex2.width == tex.width * 2) { tex2 = TextureUtils.CutToSize(tex2, tex.width, tex.height); if (dump) { DumpUtils.Dump(tex2, info); } } tex.CropAndStrech(); if (dump) { DumpUtils.Dump(tex, info); } if (info.m_netAI is RoadAI) { if (info.isAsym() && !info.isOneWay()) { tex2.Mirror(); if (dump) { DumpUtils.Dump(tex2, info); } } tex2.Scale(info.ScaleRatio()); if (info.ScaleRatio() != 1f && dump) { DumpUtils.Dump(tex2, info); } } tex.MeldDiff(tex2); if (dump) { DumpUtils.Dump(tex, info); } tex.Finalize(lod); TextureCache[material.GetTexture(ID_APRMap)] = tex; } material.SetTexture(ID_APRMap, tex); if (dump) { DumpUtils.Dump(tex, DumpUtils.GetFilePath(ID_APRMap, "node-processed", info)); } } // end if cache } // end if tex } // end if category
/// <summary> /// This methods skips our detour by calling the original method from the game, allowing the creation of the needed /// segment. /// </summary> /// <param name="segment"></param> /// <param name="randomizer"></param> /// <param name="info"></param> /// <param name="startNode"></param> /// <param name="endNode"></param> /// <param name="startDirection"></param> /// <param name="endDirection"></param> /// <param name="buildIndex"></param> /// <param name="modifiedIndex"></param> /// <param name="invert"></param> /// <returns></returns> private static bool CreateSegmentOriginal(out ushort segment, ref Randomizer randomizer, NetInfo info, ushort startNode, ushort endNode, Vector3 startDirection, Vector3 endDirection, uint buildIndex, uint modifiedIndex, bool invert) { Revert(); var result = NetManager.instance.CreateSegment(out segment, ref randomizer, info, startNode, endNode, startDirection, endDirection, buildIndex, modifiedIndex, invert); Deploy(); return(result); }
public static Material HideCrossings(Material material, Material segMaterial, NetInfo info, bool lod = false) { try { if (MaterialCache == null) { return(material); // program is loading/unloading } if (MaterialCache.Contains(material)) { return((Material)MaterialCache[material]); } var ticks = System.Diagnostics.Stopwatch.StartNew(); Material ret = new Material(material); HideCrossings0(ret, segMaterial, info, lod); MaterialCache[material] = ret; Log.Info($"Cached new texture for {info.name} ticks=" + ticks.ElapsedTicks.ToString("E2")); return(ret); } catch (Exception e) { material.GetHashCode(); Log.Info(e.ToString()); MaterialCache[material] = material; // do not repeat the same mistake! return(material); } }
public static void TrimNonHighwayProps(this NetInfo info, bool removeRightStreetLights = false, bool removeLeftStreetLights = true) { var randomProp = Prefabs.Find <PropInfo>("Random Street Prop", false); var streetLight = Prefabs.Find <PropInfo>("New Street Light", false); var streetLightHw = Prefabs.Find <PropInfo>("New Street Light Highway", false); var manhole = Prefabs.Find <PropInfo>("Manhole", false); foreach (var laneProps in info.m_lanes.Select(l => l.m_laneProps).Where(lpi => lpi != null)) { var remainingProp = new List <NetLaneProps.Prop>(); foreach (var prop in laneProps.m_props.Where(p => p.m_prop != null)) { var newProp = prop.ShallowClone(); if (prop.m_prop == randomProp) { continue; } if (prop.m_prop == manhole) { continue; } if (removeLeftStreetLights) { if (prop.m_prop == streetLight && laneProps.name.Contains("Left")) { prop.m_probability = 0; //continue; } if (prop.m_prop == streetLightHw && laneProps.name.Contains("Left")) { prop.m_probability = 0; //continue; } } if (removeRightStreetLights) { if (prop.m_prop == streetLight && laneProps.name.Contains("Right")) { prop.m_probability = 0; //continue; } if (prop.m_prop == streetLightHw && laneProps.name.Contains("Right")) { prop.m_probability = 0; //continue; } } remainingProp.Add(prop); } laneProps.m_props = remainingProp.ToArray(); } }
protected override void EndRenderingImpl(RenderManager.CameraInfo cameraInfo) { FastList <RenderGroup> renderedGroups = Singleton <RenderManager> .instance.m_renderedGroups; this.m_nameInstanceBuffer.Clear(); this.m_visibleRoadNameSegment = 0; this.m_visibleTrafficLightNode = 0; for (int groupIndex = 0; groupIndex < renderedGroups.m_size; groupIndex++) { RenderGroup renderGroup = renderedGroups.m_buffer[groupIndex]; if (renderGroup.m_instanceMask != 0) { const int resolutionRatio = NODEGRID_RESOLUTION / RenderManager.GROUP_RESOLUTION; // = 270/45 = 6 int net_x0 = renderGroup.m_x * resolutionRatio; int net_z0 = renderGroup.m_z * resolutionRatio; int net_x1 = (renderGroup.m_x + 1) * resolutionRatio - 1; // = net_x + 5 int net_z1 = (renderGroup.m_z + 1) * resolutionRatio - 1; // = net_z + 5 for (int net_z = net_z0; net_z <= net_z1; net_z++) { for (int net_x = net_x0; net_x <= net_x1; net_x++) { int gridIndex = net_z * NODEGRID_RESOLUTION + net_x; ushort nodeID = this.m_nodeGrid[gridIndex]; int watchdog = 0; while (nodeID != 0) { nodeID.ToNode().RenderInstance(cameraInfo, nodeID, renderGroup.m_instanceMask); nodeID = nodeID.ToNode().m_nextGridNode; if (++watchdog >= 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } } for (int net_z = net_z0; net_z <= net_z1; net_z++) { for (int net_x = net_x0; net_x <= net_x1; net_x++) { int gridIndex = net_z * 270 + net_x; ushort segmentID = this.m_segmentGrid[gridIndex]; int watchdog = 0; while (segmentID != 0) { this.m_segments.m_buffer[(int)segmentID].RenderInstance(cameraInfo, segmentID, renderGroup.m_instanceMask); segmentID = this.m_segments.m_buffer[(int)segmentID].m_nextGridSegment; if (++watchdog >= 36864) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } } } } this.m_lastVisibleRoadNameSegment = this.m_visibleRoadNameSegment; this.m_lastVisibleTrafficLightNode = this.m_visibleTrafficLightNode; int num11 = PrefabCollection <NetInfo> .PrefabCount(); for (int n = 0; n < num11; n++) { NetInfo prefab = PrefabCollection <NetInfo> .GetPrefab((uint)n); if (prefab != null) { if (prefab.m_segments != null) { for (int num12 = 0; num12 < prefab.m_segments.Length; num12++) { NetInfo.Segment segment = prefab.m_segments[num12]; NetInfo.LodValue combinedLod = segment.m_combinedLod; if (combinedLod != null && combinedLod.m_lodCount != 0) { NetSegment.RenderLod(cameraInfo, combinedLod); } } } if (prefab.m_nodes != null) { for (int num13 = 0; num13 < prefab.m_nodes.Length; num13++) { NetInfo.Node node = prefab.m_nodes[num13]; NetInfo.LodValue combinedLod2 = node.m_combinedLod; if (combinedLod2 != null && combinedLod2.m_lodCount != 0) { if (node.m_directConnect) { NetSegment.RenderLod(cameraInfo, combinedLod2); } else { NetNode.RenderLod(cameraInfo, combinedLod2); } } } } } } }
protected override void OnToolUpdate() { base.OnToolUpdate(); Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastInput input = new RaycastInput(ray, Camera.main.farClipPlane); input.m_ignoreSegmentFlags = NetSegment.Flags.None; input.m_ignoreNodeFlags = NetNode.Flags.All; input.m_ignoreParkFlags = DistrictPark.Flags.All; input.m_ignorePropFlags = PropInstance.Flags.All; input.m_ignoreTreeFlags = TreeInstance.Flags.All; input.m_ignoreCitizenFlags = CitizenInstance.Flags.All; input.m_ignoreVehicleFlags = Vehicle.Flags.Created; input.m_ignoreBuildingFlags = Building.Flags.All; input.m_ignoreDisasterFlags = DisasterData.Flags.All; input.m_ignoreTransportFlags = TransportLine.Flags.All; input.m_ignoreParkedVehicleFlags = VehicleParked.Flags.All; input.m_ignoreTerrain = true; RayCast(input, out RaycastOutput output); m_hover = output.m_netSegment; if (Input.GetKeyDown(KeyCode.Escape)) { enabled = false; ToolsModifierControl.SetTool <DefaultTool>(); } if (m_hover != 0) { m_netInfo = GetSegment(m_hover).Info; if (Input.GetMouseButtonUp(0)) { instance.enabled = false; if (Singleton <UnlockManager> .instance.Unlocked(m_netInfo.m_UnlockMilestone)) { // you know when you make a bugfix just to mess with people? well this is that bugfix. enjoy. UIView.Find("E2A").Unfocus(); UIView.Find("TSCloseButton").SimulateClick(); enabled = false; m_netTool = ToolsModifierControl.SetTool <NetTool>(); m_netInfo = FindDefaultElevation(m_netInfo); // If we don't load UI, stuff happens, whatever. List <UIComponent> reveal = null; ElektrixModsConfiguration config = Configuration <ElektrixModsConfiguration> .Load(); if (config.NP_OpenUI) { reveal = FindRoadInPanel(m_netInfo.name); } m_netTool.Prefab = m_netInfo; if (reveal != null) { UIView.Find("TSCloseButton").SimulateClick(); Db.l("[Net Picker] Attempting to open panel " + reveal[1].parent.parent.parent.parent.name.Replace("Panel", "")); UIButton rb = UIView.Find("MainToolstrip").Find <UIButton>(reveal[1].parent.parent.parent.parent.name.Replace("Panel", "")); rb.SimulateClick(); reveal[0].SimulateClick(); reveal[1].SimulateClick(); if (!UIView.Find("TSCloseButton").isVisible) { Db.l("Failed"); } } else if (config.NP_OpenUI) { ThrowError("This net type is hidden and won't work properly if used by non-advanced users. In order to use this net, disable 'open ui' in Net Picker settings. If this net *isn't* actually hidden, please tweet your net type (and what menu it can be found in) to @cosigncosine. Thanks!"); ToolsModifierControl.SetTool <DefaultTool>(); UIView.Find("ElectricityPanel").Hide(); } m_fakeNetTool = true; //Debug.LogError(NetworkSkins.modPath); ushort segmentId = m_hover; NetInfo prefab = m_netInfo; try { Type segmentDataManagerType = Type.GetType("NetworkSkins.Data.SegmentDataManager, NetworkSkins"); object segmentDataManager = segmentDataManagerType.GetField("Instance").GetValue(null); object[] SegmentToSegmentDataMap = (object[])segmentDataManagerType.GetField("SegmentToSegmentDataMap").GetValue(segmentDataManager); var segmentData = SegmentToSegmentDataMap[segmentId]; segmentDataManagerType.GetMethod("SetActiveOptions").Invoke(segmentDataManager, new object[] { prefab, segmentData }); } catch (Exception e) { Debug.Log("Network skins isn't installed."); } if (config.CloseWindow) { UIView.Find("ElektrixModsPanel").Hide(); } } else { ThrowError("This net type isn't unlocked yet! Wait until this unlock/milestone: " + m_netInfo.m_UnlockMilestone.m_name); } } } else { m_netInfo = default(NetInfo); } }
public static NetInfo Setup16m3mSW3mBikelaneMesh(this NetInfo info, NetInfoVersion version, LanesLayoutStyle lanesLayoutStyle = LanesLayoutStyle.Symmetrical) { var highwayInfo = Prefabs.Find <NetInfo>(NetInfos.Vanilla.HIGHWAY_3L); var highwaySlopeInfo = Prefabs.Find <NetInfo>(NetInfos.Vanilla.HIGHWAY_3L_SLOPE); var defaultMaterial = highwayInfo.m_nodes[0].m_material; switch (version) { case NetInfoVersion.Ground: case NetInfoVersion.GroundGrass: case NetInfoVersion.GroundTrees: { var segment0 = info.m_segments[0].ShallowClone(); var segment1 = info.m_segments[1].ShallowClone(); var segment2 = info.m_segments[2].ShallowClone(); var segment3 = info.m_segments[1].ShallowClone(); var node0 = info.m_nodes[0].ShallowClone(); segment0 .SetMeshes (@"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Ground.obj", @"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Ground_LOD.obj"); segment1 .SetMeshes (@"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Ground.obj", @"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Ground_LOD.obj"); segment2 .SetMeshes (@"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Ground.obj", @"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Ground_LOD.obj"); segment3 .SetMeshes (@"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Ground.obj", @"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Ground_LOD.obj"); node0 .SetMeshes (@"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Ground_Node.obj", @"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Ground_Node_LOD.obj"); RoadHelper.HandleAsymSegmentFlags(segment0); RoadHelper.HandleAsymSegmentFlags(segment2); info.m_segments = new[] { segment0, segment1, segment2, segment3 }; info.m_nodes = new[] { node0 }; break; } case NetInfoVersion.Elevated: case NetInfoVersion.Bridge: { var segment0 = info.m_segments[0].ShallowClone(); var node0 = info.m_nodes[0].ShallowClone(); segment0 .SetFlagsDefault() .SetMeshes (@"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Elevated.obj", @"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Elevated_LOD.obj"); node0. SetMeshes (@"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Elevated_Node.obj", @"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Elevated_Node_LOD.obj"); RoadHelper.HandleAsymSegmentFlags(segment0); info.m_segments = new[] { segment0 }; info.m_nodes = new[] { node0 }; break; } case NetInfoVersion.Slope: { var segment0 = info.m_segments[0].ShallowClone(); var segment1 = highwaySlopeInfo.m_segments[1].ShallowClone(); var segment2 = info.m_segments[1].ShallowClone(); var node0 = info.m_nodes[0].ShallowClone(); var node1 = info.m_nodes[1].ShallowClone(); var node2 = node0.ShallowClone(); //segment0 // .SetFlagsDefault() // **ToDo segment2 .SetFlagsDefault() .SetMeshes (@"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Slope.obj", @"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Slope_LOD.obj"); node1 .SetMeshes (@"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Slope_Node.obj", @"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Slope_Node_LOD.obj"); node2 .SetFlags(NetNode.Flags.Underground, NetNode.Flags.None) .SetMeshes (@"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Slope_U_Node.obj", @"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Slope_U_Node_LOD.obj"); RoadHelper.HandleAsymSegmentFlags(segment2); node2.m_material = defaultMaterial; info.m_segments = new[] { segment0, segment1, segment2 }; info.m_nodes = new[] { node0, node1, node2 }; break; } case NetInfoVersion.Tunnel: { var segment0 = info.m_segments[0].ShallowClone(); var segment1 = segment0.ShallowClone(); var node0 = info.m_nodes[0].ShallowClone(); var node1 = node0.ShallowClone(); segment1 .SetFlagsDefault() .SetMeshes (@"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Tunnel.obj", @"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Tunnel_LOD.obj"); node1 .SetFlags(NetNode.Flags.None, NetNode.Flags.None) .SetMeshes (@"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Tunnel_Node.obj", @"Roads\Common\Meshes\16m\3mSW3mBikeLanes\Tunnel_Node_LOD.obj"); RoadHelper.HandleAsymSegmentFlags(segment1); segment1.m_material = defaultMaterial; node1.m_material = defaultMaterial; info.m_segments = new[] { segment0, segment1 }; info.m_nodes = new[] { node0, node1 }; break; } } return(info); }
public static NetInfo Setup32m3mSW2mMdnMesh(this NetInfo info, NetInfoVersion version) { var highwayInfo = Prefabs.Find <NetInfo>(NetInfos.Vanilla.ROAD_6L); var slopeInfo = Prefabs.Find <NetInfo>(NetInfos.Vanilla.ROAD_4L_SLOPE); var defaultMaterial = highwayInfo.m_nodes[0].m_material; switch (version) { case NetInfoVersion.Ground: { var segments0 = info.m_segments[0]; var nodes0 = info.m_nodes[0]; segments0 .SetFlagsDefault() .SetMeshes (@"Roads\Common\Meshes\32m\3mSW2mMdn\Ground.obj"); nodes0.SetMeshes (@"Roads\Common\Meshes\32m\3mSW2mMdn\Ground_Node.obj"); info.m_segments = new[] { segments0 }; info.m_nodes = new[] { nodes0 }; break; } case NetInfoVersion.Elevated: { var segments0 = info.m_segments[0]; var nodes0 = info.m_nodes[0]; segments0 .SetFlagsDefault() .SetMeshes (@"Roads\Common\Meshes\32m\3mSW2mMdn\Elevated.obj", @"Roads\Common\Meshes\32m\3mSW2mMdn\Elevated_LOD.obj"); nodes0 .SetMeshes (@"Roads\Common\Meshes\32m\3mSW2mMdn\Elevated_Node.obj", @"Roads\Common\Meshes\32m\3mSW2mMdn\Elevated_Node_LOD.obj"); info.m_segments = new[] { segments0 }; info.m_nodes = new[] { nodes0 }; break; } case NetInfoVersion.Bridge: { var segments0 = info.m_segments[0]; var segments1 = info.m_segments[1]; var nodes0 = info.m_nodes[0]; segments0 .SetFlagsDefault() .SetMeshes (@"Roads\Common\Meshes\32m\3mSW2mMdn\Elevated.obj", @"Roads\Common\Meshes\32m\3mSW2mMdn\Elevated_LOD.obj"); segments1 .SetFlagsDefault() .SetMeshes (@"Roads\Common\Meshes\32m\3mSW2mMdn\Bridge_Cables.obj", @"Roads\Common\Meshes\32m\3mSW2mMdn\Bridge_Cables_LOD.obj"); nodes0 .SetMeshes (@"Roads\Common\Meshes\32m\3mSW2mMdn\Elevated_Node.obj", @"Roads\Common\Meshes\32m\3mSW2mMdn\Elevated_Node_LOD.obj"); info.m_segments = new[] { segments0, segments1 }; info.m_nodes = new[] { nodes0 }; break; } case NetInfoVersion.Slope: { var segment0 = info.m_segments[0]; var segment1 = slopeInfo.m_segments[1].ShallowClone(); var segment2 = info.m_segments[1]; var node0 = info.m_nodes[0]; var node1 = info.m_nodes[1]; var node2 = node0.ShallowClone(); //segment0 // .SetFlagsDefault() // **ToDo segment2 .SetFlagsDefault() .SetMeshes (@"Roads\Common\Meshes\32m\3mSW2mMdn\Slope.obj", @"Roads\Common\Meshes\32m\3mSW2mMdn\Slope_LOD.obj"); node1 .SetMeshes (@"Roads\Common\Meshes\32m\3mSW2mMdn\Slope_Node.obj", @"Roads\Common\Meshes\32m\3mSW2mMdn\Slope_Node_LOD.obj"); node2 .SetMeshes (@"Roads\Common\Meshes\32m\3mSW2mMdn\Slope_U_Node.obj", @"Roads\Common\Meshes\32m\3mSW2mMdn\Slope_U_Node_LOD.obj"); node2.m_material = defaultMaterial; info.m_segments = new[] { segment0, segment1, segment2 }; info.m_nodes = new[] { node0, node1, node2 }; break; } case NetInfoVersion.Tunnel: { var segment0 = info.m_segments[0]; var segment1 = segment0.ShallowClone(); var node0 = info.m_nodes[0]; var node1 = node0.ShallowClone(); segment1 .SetFlagsDefault() .SetMeshes (@"Roads\Common\Meshes\32m\3mSW2mMdn\Tunnel.obj", @"Roads\Common\Meshes\32m\3mSW2mMdn\Tunnel_LOD.obj"); node1 .SetFlags(NetNode.Flags.None, NetNode.Flags.None) .SetMeshes (@"Roads\Common\Meshes\32m\3mSW2mMdn\Tunnel_Node.obj", @"Roads\Common\Meshes\32m\3mSW2mMdn\Tunnel_Node_LOD.obj"); segment1.m_material = defaultMaterial; node1.m_material = defaultMaterial; info.m_segments = new[] { segment0, segment1 }; info.m_nodes = new[] { node0, node1 }; break; } } return(info); }
/// <summary> /// Determines the average custom speed limit for a given NetInfo object in terms of discrete speed limit levels. /// An in-game speed limit of 2.0 (e.g. on highway) is hereby translated into a discrete speed limit value of 100 (km/h). /// </summary> /// <param name="segmentInfo"></param> /// <param name="finalDir"></param> /// <returns></returns> public ushort GetAverageCustomSpeedLimit(ushort segmentId, ref NetSegment segment, NetInfo segmentInfo, NetInfo.Direction?finalDir = null) { // calculate the currently set mean speed limit float meanSpeedLimit = 0f; uint validLanes = 0; uint curLaneId = segment.m_lanes; for (byte laneIndex = 0; laneIndex < segmentInfo.m_lanes.Length; ++laneIndex) { NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex]; NetInfo.Direction d = laneInfo.m_finalDirection; if (finalDir != null && d != finalDir) { continue; } if (!MayHaveCustomSpeedLimits(laneInfo)) { continue; } meanSpeedLimit += GetLockFreeGameSpeedLimit(segmentId, laneIndex, curLaneId, laneInfo); curLaneId = Singleton <NetManager> .instance.m_lanes.m_buffer[curLaneId].m_nextLane; ++validLanes; } if (validLanes > 0) { meanSpeedLimit /= (float)validLanes; } return((ushort)Mathf.Round(meanSpeedLimit)); }
public static bool segmentIsIncomingOneWay(int segmentid, ushort nodeID) { NetManager instance = Singleton <NetManager> .instance; var segment = instance.m_segments.m_buffer[segmentid]; var info = segment.Info; uint num2 = segment.m_lanes; int num3 = 0; NetInfo.Direction dir = NetInfo.Direction.Forward; if (segment.m_startNode == nodeID) { dir = NetInfo.Direction.Backward; } var dir2 = ((segment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? dir : NetInfo.InvertDirection(dir); var dir3 = TrafficPriority.leftHandDrive ? NetInfo.InvertDirection(dir2) : dir2; var isOneWay = true; while (num3 < info.m_lanes.Length && num2 != 0u) { if (info.m_lanes[num3].m_laneType != NetInfo.LaneType.Pedestrian && (info.m_lanes[num3].m_direction == dir3)) { isOneWay = false; } num2 = instance.m_lanes.m_buffer[(int)((UIntPtr)num2)].m_nextLane; num3++; } return(isOneWay); }
public override void RenderOverlay(RenderManager.CameraInfo cameraInfo, Color toolColor, Color despawnColor) { if (!isValid) { return; } ushort segment = id.NetSegment; NetInfo netInfo = segmentBuffer[segment].Info; ushort startNode = segmentBuffer[segment].m_startNode; ushort endNode = segmentBuffer[segment].m_endNode; bool smoothStart = ((nodeBuffer[startNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None); bool smoothEnd = ((nodeBuffer[endNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None); Bezier3 bezier; bezier.a = nodeBuffer[startNode].m_position; bezier.d = nodeBuffer[endNode].m_position; // NON-STOCK CODE STARTS if (MoveItTool.IsCSUROffset(netInfo)) { var tmpDir = segmentBuffer[segment].m_startDirection; if ((segmentBuffer[segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None) { tmpDir = -tmpDir; } tmpDir = new Vector3(tmpDir.z, tmpDir.y, -tmpDir.x); bezier.a = tmpDir * (netInfo.m_halfWidth + netInfo.m_pavementWidth) / 2f + bezier.a; tmpDir = segmentBuffer[segment].m_endDirection; if ((segmentBuffer[segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None) { tmpDir = -tmpDir; } tmpDir = new Vector3(-tmpDir.z, tmpDir.y, tmpDir.x); bezier.d = tmpDir * (netInfo.m_halfWidth + netInfo.m_pavementWidth) / 2f + bezier.d; } // NON-STOCK CODE ENDS NetSegment.CalculateMiddlePoints( bezier.a, segmentBuffer[segment].m_startDirection, bezier.d, segmentBuffer[segment].m_endDirection, smoothStart, smoothEnd, out bezier.b, out bezier.c); // NON-STOCK CODE STARTS if (MoveItTool.IsCSUROffset(netInfo)) { RenderManager.instance.OverlayEffect.DrawBezier(cameraInfo, toolColor, bezier, (netInfo.m_halfWidth - netInfo.m_pavementWidth) * 4f / 3f, 100000f, -100000f, -1f, 1280f, false, true); } else { RenderManager.instance.OverlayEffect.DrawBezier(cameraInfo, toolColor, bezier, netInfo.m_halfWidth * 4f / 3f, 100000f, -100000f, -1f, 1280f, false, true); } // NON-STOCK CODE ENDS Segment3 segment1, segment2; segment1.a = nodeBuffer[startNode].m_position; segment2.a = nodeBuffer[endNode].m_position; segment1.b = GetControlPoint(segment); segment2.b = segment1.b; // NON-STOCK CODE STARTS if (MoveItTool.IsCSUROffset(netInfo)) { var tmpDir = segmentBuffer[segment].m_startDirection; if ((segmentBuffer[segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None) { tmpDir = -tmpDir; } tmpDir = new Vector3(tmpDir.z, tmpDir.y, -tmpDir.x); segment1.a = tmpDir * (netInfo.m_halfWidth + netInfo.m_pavementWidth) / 2f + segment1.a; tmpDir = segmentBuffer[segment].m_endDirection; if ((segmentBuffer[segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None) { tmpDir = -tmpDir; } tmpDir = new Vector3(-tmpDir.z, tmpDir.y, tmpDir.x); segment2.a = tmpDir * (netInfo.m_halfWidth + netInfo.m_pavementWidth) / 2f + segment2.a; tmpDir = (segmentBuffer[segment].m_startDirection - segmentBuffer[segment].m_endDirection) / 2; if ((segmentBuffer[segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None) { tmpDir = -tmpDir; } tmpDir = new Vector3(tmpDir.z, tmpDir.y, -tmpDir.x); segment1.b = tmpDir * (netInfo.m_halfWidth + netInfo.m_pavementWidth) / 2f + segment1.b; segment2.b = segment1.b; } // NON-STOCK CODE ENDS toolColor.a = toolColor.a / 2; RenderManager.instance.OverlayEffect.DrawSegment(cameraInfo, toolColor, segment1, segment2, 0, 10f, -1f, 1280f, false, true); // NON-STOCK CODE STARTS if (MoveItTool.IsCSUROffset(netInfo)) { RenderManager.instance.OverlayEffect.DrawCircle(cameraInfo, toolColor, segment1.b, (netInfo.m_halfWidth - netInfo.m_pavementWidth) / 2f, -1f, 1280f, false, true); } else { RenderManager.instance.OverlayEffect.DrawCircle(cameraInfo, toolColor, segment1.b, netInfo.m_halfWidth / 2f, -1f, 1280f, false, true); } // NON-STOCK CODE ENDS }
public void OnBeforeSimulationStep(ushort segmentId, ref NetSegment segment) { GlobalConfig conf = GlobalConfig.Instance; // calculate traffic density NetInfo segmentInfo = segment.Info; int numLanes = segmentInfo.m_lanes.Length; if (LaneTrafficData[segmentId] == null || LaneTrafficData[segmentId].Length < numLanes) { LaneTrafficData[segmentId] = new LaneTrafficData[numLanes]; for (int i = 0; i < numLanes; ++i) { // laneTrafficData[segmentId][i] = new LaneTrafficData(); LaneTrafficData[segmentId][i].meanSpeed = REF_REL_SPEED; } } // calculate max./min. lane speed for (var i = 0; i < 2; ++i) { meanSpeeds[i] = 0; meanSpeedLanes[i] = 0; } uint curLaneId = segment.m_lanes; byte laneIndex = 0; while (laneIndex < numLanes && curLaneId != 0u) { NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex]; if ((laneInfo.m_laneType & LANE_TYPES) != NetInfo.LaneType.None && (laneInfo.m_vehicleType & VEHICLE_TYPES) != VehicleInfo.VehicleType.None) { int dirIndex = GetDirIndex(laneInfo.m_finalDirection); // calculate reported mean speed ushort newRelSpeed = CalcLaneRelativeMeanSpeed( segmentId, laneIndex, curLaneId, segment.Info.m_lanes[laneIndex]); meanSpeeds[dirIndex] += newRelSpeed; ++meanSpeedLanes[dirIndex]; LaneTrafficData[segmentId][laneIndex].meanSpeed = newRelSpeed; ushort trafficBuffer = LaneTrafficData[segmentId][laneIndex].trafficBuffer; // remember historic data LaneTrafficData[segmentId][laneIndex].lastTrafficBuffer = trafficBuffer; if (trafficBuffer > LaneTrafficData[segmentId][laneIndex].maxTrafficBuffer) { LaneTrafficData[segmentId][laneIndex].maxTrafficBuffer = trafficBuffer; } // reset buffers if (conf.AdvancedVehicleAI.MaxTrafficBuffer > 0) { if (LaneTrafficData[segmentId][laneIndex].trafficBuffer > conf.AdvancedVehicleAI.MaxTrafficBuffer) { LaneTrafficData[segmentId][laneIndex].accumulatedSpeeds /= LaneTrafficData[segmentId][laneIndex].trafficBuffer / conf.AdvancedVehicleAI.MaxTrafficBuffer; LaneTrafficData[segmentId][laneIndex].trafficBuffer = (ushort)conf.AdvancedVehicleAI.MaxTrafficBuffer; } else if (LaneTrafficData[segmentId][laneIndex].trafficBuffer == conf.AdvancedVehicleAI.MaxTrafficBuffer) { LaneTrafficData[segmentId][laneIndex].accumulatedSpeeds = 0; LaneTrafficData[segmentId][laneIndex].trafficBuffer = 0; } } else { LaneTrafficData[segmentId][laneIndex].accumulatedSpeeds = 0; LaneTrafficData[segmentId][laneIndex].trafficBuffer = 0; } } laneIndex++; curLaneId = Singleton <NetManager> .instance.m_lanes.m_buffer[curLaneId].m_nextLane; } for (int i = 0; i < 2; ++i) { int segDirIndex = i == 0 ? GetDirIndex(segmentId, NetInfo.Direction.Forward) : GetDirIndex(segmentId, NetInfo.Direction.Backward); if (meanSpeedLanes[i] > 0) { SegmentDirTrafficData[segDirIndex].meanSpeed = (ushort)Math.Min( REF_REL_SPEED, meanSpeeds[i] / meanSpeedLanes[i]); } else { SegmentDirTrafficData[segDirIndex].meanSpeed = REF_REL_SPEED; } } }
private static void SetupTextures(NetInfo info, NetInfoVersion version) { switch (version) { case NetInfoVersion.Ground: info.SetAllSegmentsTexture( new TextureSet (@"Roads\PedestrianRoads\Promenade\Textures\Ground_Segment__MainTex.png", @"Roads\PedestrianRoads\Promenade\Textures\Ground_Segment__AlphaMap.png", @"Roads\PedestrianRoads\Promenade\Textures\Ground_Segment__XYSMap.png"), new LODTextureSet (@"Roads\PedestrianRoads\Promenade\Textures\Ground_Segment_LOD__MainTex.png", @"Roads\PedestrianRoads\Promenade\Textures\Ground_Segment_LOD__AlphaMap.png", @"Roads\PedestrianRoads\Promenade\Textures\Ground_Segment_LOD__XYSMap.png")); for (int i = 0; i < info.m_nodes.Length; i++) { if (info.m_nodes[i].m_flagsRequired == NetNode.Flags.Transition) { info.m_nodes[i].SetTextures( new TextureSet (@"Roads\PedestrianRoads\Promenade\Textures\Ground_Trans__MainTex.png", @"Roads\PedestrianRoads\Promenade\Textures\Ground_Trans__AlphaMap.png", @"Roads\PedestrianRoads\Promenade\Textures\Ground_Node__XYSMap.png"), new LODTextureSet (@"Roads\PedestrianRoads\Common\Textures\Ground_Trans_LOD__MainTex.png", @"Roads\PedestrianRoads\Common\Textures\Ground_Trans_LOD__AlphaMap.png", @"Roads\PedestrianRoads\Common\Textures\Ground_Node_LOD__XYSMap.png")); } else { info.m_nodes[i].SetTextures( new TextureSet (@"Roads\PedestrianRoads\Promenade\Textures\Ground_Node__MainTex.png", @"Roads\PedestrianRoads\Promenade\Textures\Ground_Node__AlphaMap.png", @"Roads\PedestrianRoads\Promenade\Textures\Ground_Node__XYSMap.png"), new LODTextureSet (@"Roads\PedestrianRoads\Promenade\Textures\Ground_Node_LOD__MainTex.png", @"Roads\PedestrianRoads\Promenade\Textures\Ground_Node_LOD__AlphaMap.png", @"Roads\PedestrianRoads\Common\Textures\Ground_Node_LOD__XYSMap.png")); } } break; case NetInfoVersion.Elevated: info.SetAllSegmentsTexture( new TextureSet (@"Roads\PedestrianRoads\Promenade\Textures\Elevated_Segment__MainTex.png", @"Roads\PedestrianRoads\Promenade\Textures\Elevated_Segment__AlphaMap.png", @"Roads\PedestrianRoads\Promenade\Textures\Elevated_Segment__XYSMap.png"), new LODTextureSet (@"Roads\PedestrianRoads\Promenade\Textures\Elevated_Segment_LOD__MainTex.png", @"Roads\PedestrianRoads\Promenade\Textures\Elevated_Segment_LOD__AlphaMap.png", @"Roads\PedestrianRoads\Promenade\Textures\Elevated_Segment_LOD__XYSMap.png")); for (int i = 0; i < info.m_nodes.Length; i++) { if (info.m_nodes[i].m_flagsRequired == NetNode.Flags.Transition) { info.m_nodes[i].SetTextures( new TextureSet (@"Roads\PedestrianRoads\Promenade\Textures\Elevated_Trans__MainTex.png", @"Roads\PedestrianRoads\Promenade\Textures\Elevated_Trans__AlphaMap.png"), new LODTextureSet (@"Roads\PedestrianRoads\Common\Textures\Elevated_Trans_LOD__MainTex.png", @"Roads\PedestrianRoads\Common\Textures\Elevated_Trans_LOD__AlphaMap.png", @"Roads\PedestrianRoads\Promenade\Textures\Elevated_Node_LOD__XYSMap.png")); } else { info.m_nodes[i].SetTextures( new TextureSet (@"Roads\PedestrianRoads\Promenade\Textures\Elevated_Node__MainTex.png", @"Roads\PedestrianRoads\Promenade\Textures\Elevated_Node__AlphaMap.png", @"Roads\PedestrianRoads\Promenade\Textures\Elevated_Segment__XYSMap.png"), new LODTextureSet (@"Roads\PedestrianRoads\Common\Textures\Elevated_Trans_LOD__MainTex.png", @"Roads\PedestrianRoads\Promenade\Textures\Elevated_Node_LOD__AlphaMap.png", @"Roads\PedestrianRoads\Promenade\Textures\Elevated_Node_LOD__XYSMap.png")); } } break; } }
public void BuildUp(NetInfo info, NetInfoVersion version) { /////////////////////////// // Template // /////////////////////////// var roadInfo = Prefabs.Find <NetInfo>(NetInfos.Vanilla.ROAD_2L); var owRoadTunnelInfo = Prefabs.Find <NetInfo>(NetInfos.Vanilla.ONEWAY_2L_TUNNEL); /////////////////////////// // 3DModeling // /////////////////////////// info.Setup16m3mSWMesh(version, LanesLayoutStyle.AsymL1R2); /////////////////////////// // Texturing // /////////////////////////// SetupTextures(info, version); /////////////////////////// // Set up // /////////////////////////// info.m_hasParkingSpaces = false; info.m_class = roadInfo.m_class.Clone(NetInfoClasses.NEXT_SMALL3L_ROAD); info.m_pavementWidth = (version != NetInfoVersion.Slope && version != NetInfoVersion.Tunnel ? 3 : 6); info.m_halfWidth = (version != NetInfoVersion.Slope && version != NetInfoVersion.Tunnel ? 8 : 11); if (version == NetInfoVersion.Tunnel) { info.m_setVehicleFlags = Vehicle.Flags.Transition | Vehicle.Flags.Underground; info.m_setCitizenFlags = CitizenInstance.Flags.Transition | CitizenInstance.Flags.Underground; info.m_class = owRoadTunnelInfo.m_class.Clone(NetInfoClasses.NEXT_SMALL3L_ROAD_TUNNEL); } else { info.m_class = roadInfo.m_class.Clone(NetInfoClasses.NEXT_SMALL3L_ROAD); } // Setting up lanes info.SetRoadLanes(version, new LanesConfiguration { IsTwoWay = true, LanesToAdd = 1, LaneWidth = 3.3f, SpeedLimit = 1.0f, CenterLane = CenterLaneType.None, LayoutStyle = LanesLayoutStyle.AsymL1R2 }); var leftPedLane = info.GetLeftRoadShoulder(); var rightPedLane = info.GetRightRoadShoulder(); //Setting Up Props var leftRoadProps = leftPedLane.m_laneProps.m_props.ToList(); var rightRoadProps = rightPedLane.m_laneProps.m_props.ToList(); if (version == NetInfoVersion.Slope) { leftRoadProps.AddLeftWallLights(info.m_pavementWidth); rightRoadProps.AddRightWallLights(info.m_pavementWidth); } leftPedLane.m_laneProps.m_props = leftRoadProps.ToArray(); rightPedLane.m_laneProps.m_props = rightRoadProps.ToArray(); info.TrimAboveGroundProps(version); info.SetupNewSpeedLimitProps(50, 40); // AI var owPlayerNetAI = roadInfo.GetComponent <PlayerNetAI>(); var playerNetAI = info.GetComponent <PlayerNetAI>(); if (owPlayerNetAI != null && playerNetAI != null) { playerNetAI.m_constructionCost = owPlayerNetAI.m_constructionCost * 3 / 2; // Charge by the lane? playerNetAI.m_maintenanceCost = owPlayerNetAI.m_maintenanceCost * 3 / 2; // Charge by the lane? } var roadBaseAI = info.GetComponent <RoadBaseAI>(); if (roadBaseAI != null) { roadBaseAI.m_trafficLights = false; } }
public void BuildUp(NetInfo info, NetInfoVersion version) { /////////////////////////// // Texturing // /////////////////////////// switch (version) { case NetInfoVersion.Ground: { foreach (var segment in info.m_segments) { switch (segment.m_forwardRequired) { case NetSegment.Flags.StopLeft: case NetSegment.Flags.StopRight: segment.SetTextures( new TextureSet (@"Roads\BusRoads\Busway2L\Textures\Ground_Segment__MainTex.png", @"Roads\BusRoads\Busway2L\Textures\Ground_Segment__AlphaMap.png"), new LODTextureSet (@"Roads\BusRoads\Busway2L\Textures\Ground_SegmentLOD_Bus__MainTex.png", @"Roads\BusRoads\Busway2L\Textures\Ground_SegmentLOD_Bus__AlphaMap.png", @"Roads\BusRoads\Busway2L\Textures\Ground_SegmentLOD__XYSMap.png")); break; case NetSegment.Flags.StopBoth: segment.SetTextures( new TextureSet (@"Roads\BusRoads\Busway2L\Textures\Ground_Segment__MainTex.png", @"Roads\BusRoads\Busway2L\Textures\Ground_Segment__AlphaMap.png"), new LODTextureSet (@"Roads\BusRoads\Busway2L\Textures\Ground_SegmentLOD_BusBoth__MainTex.png", @"Roads\BusRoads\Busway2L\Textures\Ground_SegmentLOD_BusBoth__AlphaMap.png", @"Roads\BusRoads\Busway2L\Textures\Ground_SegmentLOD__XYSMap.png")); break; default: segment.SetTextures( new TextureSet (@"Roads\BusRoads\Busway2L\Textures\Ground_Segment__MainTex.png", @"Roads\BusRoads\Busway2L\Textures\Ground_Segment__AlphaMap.png"), new LODTextureSet (@"Roads\BusRoads\Busway2L\Textures\Ground_SegmentLOD__MainTex.png", @"Roads\BusRoads\Busway2L\Textures\Ground_SegmentLOD__AlphaMap.png", @"Roads\BusRoads\Busway2L\Textures\Ground_SegmentLOD__XYSMap.png")); break; } } } break; case NetInfoVersion.GroundGrass: case NetInfoVersion.GroundTrees: { foreach (var segment in info.m_segments) { switch (segment.m_forwardRequired) { case NetSegment.Flags.StopLeft: case NetSegment.Flags.StopRight: segment.SetTextures( new TextureSet (@"Roads\BusRoads\Busway2L\Textures_Grass\Ground_Segment__MainTex.png", @"Roads\BusRoads\Busway2L\Textures_Grass\Ground_Segment_Bus__AlphaMap.png"), new LODTextureSet (@"Roads\BusRoads\Busway2L\Textures_Grass\Ground_SegmentLOD_Bus__MainTex.png", @"Roads\BusRoads\Busway2L\Textures_Grass\Ground_SegmentLOD_Bus__AlphaMap.png", @"Roads\BusRoads\Busway2L\Textures_Grass\Ground_SegmentLOD__XYSMap.png")); break; case NetSegment.Flags.StopBoth: segment.SetTextures( new TextureSet (@"Roads\BusRoads\Busway2L\Textures_Grass\Ground_Segment__MainTex.png", @"Roads\BusRoads\Busway2L\Textures_Grass\Ground_Segment_BusBoth__AlphaMap.png"), new LODTextureSet (@"Roads\BusRoads\Busway2L\Textures_Grass\Ground_SegmentLOD_BusBoth__MainTex.png", @"Roads\BusRoads\Busway2L\Textures_Grass\Ground_SegmentLOD_BusBoth__AlphaMap.png", @"Roads\BusRoads\Busway2L\Textures_Grass\Ground_SegmentLOD__XYSMap.png")); break; default: segment.SetTextures( new TextureSet (@"Roads\BusRoads\Busway2L\Textures_Grass\Ground_Segment__MainTex.png", @"Roads\BusRoads\Busway2L\Textures_Grass\Ground_Segment__AlphaMap.png"), new LODTextureSet (@"Roads\BusRoads\Busway2L\Textures_Grass\Ground_SegmentLOD__MainTex.png", @"Roads\BusRoads\Busway2L\Textures_Grass\Ground_SegmentLOD__AlphaMap.png", @"Roads\BusRoads\Busway2L\Textures_Grass\Ground_SegmentLOD__XYSMap.png")); break; } } } break; case NetInfoVersion.Bridge: case NetInfoVersion.Elevated: { foreach (var segment in info.m_segments) { segment.SetTextures( new TextureSet (@"Roads\BusRoads\Busway2L\Textures\Elevated_Segment__MainTex.png", @"Roads\BusRoads\Busway2L\Textures\Elevated_Segment__AlphaMap.png"), new LODTextureSet (@"Roads\BusRoads\Busway2L\Textures\Elevated_SegmentLOD__MainTex.png", @"Roads\BusRoads\Busway2L\Textures\Elevated_SegmentLOD__AlphaMap.png", @"Roads\BusRoads\Busway2L\Textures\Elevated_SegmentLOD__XYSMap.png")); } } break; case NetInfoVersion.Slope: { foreach (var segment in info.m_segments) { segment.SetTextures( new TextureSet (@"Roads\BusRoads\Busway2L\Textures\Slope_Segment__MainTex.png", @"Roads\BusRoads\Busway2L\Textures\Slope_Segment__AlphaMap.png"), new LODTextureSet (@"Roads\BusRoads\Busway2L\Textures\Slope_SegmentLOD__MainTex.png", @"Roads\BusRoads\Busway2L\Textures\Slope_SegmentLOD__AlphaMap.png", @"Roads\BusRoads\Busway2L\Textures\Slope_SegmentLOD__XYS.png")); } } break; case NetInfoVersion.Tunnel: break; } /////////////////////////// // Templates // /////////////////////////// var highwayInfo = Prefabs.Find <NetInfo>(NetInfos.Vanilla.HIGHWAY_3L); /////////////////////////// // Set up // /////////////////////////// info.m_UnlockMilestone = highwayInfo.m_UnlockMilestone; info.m_lanes = info.m_lanes.Where(l => l.m_laneType != NetInfo.LaneType.Parking).ToArray(); info.m_laneTypes = NetInfo.LaneType.Pedestrian | NetInfo.LaneType.PublicTransport | NetInfo.LaneType.TransportVehicle; for (int i = 0; i < info.m_lanes.Count(); i++) { var lane = info.m_lanes[i]; if (lane.m_laneType == NetInfo.LaneType.Vehicle) { if (version == NetInfoVersion.Ground) { if (lane.m_position < 0f) { lane.m_position -= 1f; lane.m_stopOffset += 1f; } else { lane.m_position += 1f; lane.m_stopOffset -= 1f; } } lane.m_speedLimit = 1.6f; lane.m_laneType = NetInfo.LaneType.TransportVehicle; lane.SetBusLaneProps(); info.m_lanes[i] = new ExtendedNetInfoLane(lane, ExtendedVehicleType.Bus | ExtendedVehicleType.EmergencyVehicles); } } var roadBaseAI = info.GetComponent <RoadBaseAI>(); if (roadBaseAI != null) { } var roadAI = info.GetComponent <RoadAI>(); if (roadAI != null) { roadAI.m_enableZoning = false; } }
public override void OnBeforeLoadData() { base.OnBeforeLoadData(); // determine vanilla speed limits and customizable NetInfos SteamHelper.DLC_BitMask dlcMask = SteamHelper.GetOwnedDLCMask(); int numLoaded = PrefabCollection <NetInfo> .LoadedCount(); vanillaLaneSpeedLimitsByNetInfoName.Clear(); customizableNetInfos.Clear(); CustomLaneSpeedLimitIndexByNetInfoName.Clear(); childNetInfoNamesByCustomizableNetInfoName.Clear(); NetInfoByName.Clear(); List <NetInfo> mainNetInfos = new List <NetInfo>(); Log.Info($"SpeedLimitManager.OnBeforeLoadData: {numLoaded} NetInfos loaded."); for (uint i = 0; i < numLoaded; ++i) { NetInfo info = PrefabCollection <NetInfo> .GetLoaded(i); if (info == null || info.m_netAI == null || !(info.m_netAI is RoadBaseAI || info.m_netAI is MetroTrackAI || info.m_netAI is TrainTrackBaseAI) || !(info.m_dlcRequired == 0 || (uint)(info.m_dlcRequired & dlcMask) != 0u)) { if (info == null) { Log.Warning($"SpeedLimitManager.OnBeforeLoadData: NetInfo @ {i} is null!"); } continue; } string infoName = info.name; if (infoName == null) { Log.Warning($"SpeedLimitManager.OnBeforeLoadData: NetInfo name @ {i} is null!"); continue; } if (!vanillaLaneSpeedLimitsByNetInfoName.ContainsKey(infoName)) { if (info.m_lanes == null) { Log.Warning($"SpeedLimitManager.OnBeforeLoadData: NetInfo lanes @ {i} is null!"); continue; } Log.Info($"Loaded road NetInfo: {infoName}"); NetInfoByName[infoName] = info; mainNetInfos.Add(info); float[] vanillaLaneSpeedLimits = new float[info.m_lanes.Length]; for (int k = 0; k < info.m_lanes.Length; ++k) { vanillaLaneSpeedLimits[k] = info.m_lanes[k].m_speedLimit; } vanillaLaneSpeedLimitsByNetInfoName[infoName] = vanillaLaneSpeedLimits; } } mainNetInfos.Sort(delegate(NetInfo a, NetInfo b) { bool aRoad = a.m_netAI is RoadBaseAI; bool bRoad = b.m_netAI is RoadBaseAI; if (aRoad != bRoad) { if (aRoad) { return(-1); } else { return(1); } } bool aTrain = a.m_netAI is TrainTrackBaseAI; bool bTrain = b.m_netAI is TrainTrackBaseAI; if (aTrain != bTrain) { if (aTrain) { return(1); } else { return(-1); } } bool aMetro = a.m_netAI is MetroTrackAI; bool bMetro = b.m_netAI is MetroTrackAI; if (aMetro != bMetro) { if (aMetro) { return(1); } else { return(-1); } } if (aRoad && bRoad) { bool aHighway = ((RoadBaseAI)a.m_netAI).m_highwayRules; bool bHighway = ((RoadBaseAI)b.m_netAI).m_highwayRules; if (aHighway != bHighway) { if (aHighway) { return(1); } else { return(-1); } } } int aNumVehicleLanes = 0; foreach (NetInfo.Lane lane in a.m_lanes) { if ((lane.m_laneType & LANE_TYPES) != NetInfo.LaneType.None) { ++aNumVehicleLanes; } } int bNumVehicleLanes = 0; foreach (NetInfo.Lane lane in b.m_lanes) { if ((lane.m_laneType & LANE_TYPES) != NetInfo.LaneType.None) { ++bNumVehicleLanes; } } int res = aNumVehicleLanes.CompareTo(bNumVehicleLanes); if (res == 0) { return(a.name.CompareTo(b.name)); } else { return(res); } }); // identify parent NetInfos int x = 0; while (x < mainNetInfos.Count) { NetInfo info = mainNetInfos[x]; string infoName = info.name; // find parent with prefix name bool foundParent = false; for (int y = 0; y < mainNetInfos.Count; ++y) { NetInfo parentInfo = mainNetInfos[y]; if (info.m_placementStyle == ItemClass.Placement.Procedural && !infoName.Equals(parentInfo.name) && infoName.StartsWith(parentInfo.name)) { Log.Info($"Identified child NetInfo {infoName} of parent {parentInfo.name}"); List <string> childNetInfoNames; if (!childNetInfoNamesByCustomizableNetInfoName.TryGetValue(parentInfo.name, out childNetInfoNames)) { childNetInfoNamesByCustomizableNetInfoName[parentInfo.name] = childNetInfoNames = new List <string>(); } childNetInfoNames.Add(info.name); NetInfoByName[infoName] = info; foundParent = true; break; } } if (foundParent) { mainNetInfos.RemoveAt(x); } else { ++x; } } customizableNetInfos = mainNetInfos; }
public static void Setup16mMesh(this NetInfo info, NetInfoVersion version) { /////////////////////////// // Template // /////////////////////////// var highwayInfo = Prefabs.Find <NetInfo>(NetInfos.Vanilla.HIGHWAY_3L); var defaultMaterial = highwayInfo.m_nodes[0].m_material; switch (version) { case NetInfoVersion.Ground: { var segments0 = info.m_segments[0].ShallowClone(); var nodes0 = info.m_nodes[0].ShallowClone(); var nodes1 = info.m_nodes[0].ShallowClone(); segments0 .SetFlagsDefault() .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Ground.obj", @"Roads\Highways\Common\Meshes\16m\Ground_LOD.obj"); nodes0 .SetFlags(NetNode.Flags.None, NetNode.Flags.Transition) .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Ground_Node.obj", @"Roads\Highways\Common\Meshes\16m\Ground_Node_LOD.obj"); nodes1 .SetFlags(NetNode.Flags.Transition, NetNode.Flags.None) .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Ground_Trans.obj", @"Roads\Highways\Common\Meshes\16m\Ground_Trans_LOD.obj"); info.m_segments = new[] { segments0 }; info.m_nodes = new[] { nodes0, nodes1 }; } break; case NetInfoVersion.Elevated: case NetInfoVersion.Bridge: { var segments0 = info.m_segments[0].ShallowClone(); var nodes0 = info.m_nodes[0].ShallowClone(); var nodes1 = info.m_nodes[0].ShallowClone(); segments0 .SetFlagsDefault() .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Elevated.obj", @"Roads\Highways\Common\Meshes\16m\Elevated_LOD.obj"); nodes0 .SetFlags(NetNode.Flags.None, NetNode.Flags.Transition) .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Elevated_Node.obj", @"Roads\Highways\Common\Meshes\16m\Elevated_Node_LOD.obj"); nodes1 .SetFlags(NetNode.Flags.Transition, NetNode.Flags.None) .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Elevated_Trans.obj", @"Roads\Highways\Common\Meshes\16m\Elevated_Trans_LOD.obj"); info.m_segments = new[] { segments0 }; info.m_nodes = new[] { nodes0, nodes1 }; } break; case NetInfoVersion.Slope: { var segments0 = info.m_segments[0].ShallowClone(); var segments1 = info.m_segments[1].ShallowClone(); var segments2 = info.m_segments[1].ShallowClone(); var nodes0 = info.m_nodes[0].ShallowClone(); var nodes1 = info.m_nodes[0].ShallowClone(); var nodes2 = info.m_nodes[1].ShallowClone(); var nodes3 = info.m_nodes[1].ShallowClone(); segments0 .SetFlagsDefault() .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Tunnel_Gray.obj", @"Roads\Highways\Common\Meshes\16m\Ground_LOD.obj"); segments1 .SetFlagsDefault(); segments2 .SetFlagsDefault() .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Slope.obj", @"Roads\Highways\Common\Meshes\16m\Slope_LOD.obj"); nodes0 .SetFlags(NetNode.Flags.Underground, NetNode.Flags.None) .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Tunnel_Node_Gray.obj", @"Roads\Highways\Common\Meshes\16m\Ground_Node_LOD.obj"); nodes1 .SetFlags(NetNode.Flags.Underground, NetNode.Flags.None) .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Slope_U_Node.obj", @"Roads\Highways\Common\Meshes\16m\Slope_U_Node_LOD.obj"); nodes2 .SetFlags(NetNode.Flags.None, NetNode.Flags.UndergroundTransition) .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Ground_Node.obj", @"Roads\Highways\Common\Meshes\16m\Ground_Node_LOD.obj"); nodes3 .SetFlags(NetNode.Flags.Transition, NetNode.Flags.None) .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Ground_Trans.obj", @"Roads\Highways\Common\Meshes\16m\Ground_Trans_LOD.obj"); nodes1.m_material = defaultMaterial; info.m_segments = new[] { segments0, segments1, segments2 }; info.m_nodes = new[] { nodes0, nodes1, nodes2, nodes3 }; } break; case NetInfoVersion.Tunnel: { var segments0 = info.m_segments[0].ShallowClone(); var segments1 = info.m_segments[0].ShallowClone(); var nodes0 = info.m_nodes[0].ShallowClone(); var nodes1 = info.m_nodes[0].ShallowClone(); segments0 //.SetFlagsDefault() .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Tunnel_Gray.obj", @"Roads\Highways\Common\Meshes\16m\Ground_LOD.obj"); segments1 //.SetFlagsDefault() .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Tunnel.obj", @"Roads\Highways\Common\Meshes\16m\Tunnel_LOD.obj"); nodes0 .SetFlags(NetNode.Flags.None, NetNode.Flags.None) .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Tunnel_Node_Gray.obj", @"Roads\Highways\Common\Meshes\16m\Ground_Node_LOD.obj"); nodes1 .SetFlags(NetNode.Flags.None, NetNode.Flags.None) .SetMeshes (@"Roads\Highways\Common\Meshes\16m\Tunnel_Node.obj", @"Roads\Highways\Common\Meshes\16m\Tunnel_Node_LOD.obj"); segments1.m_material = defaultMaterial; nodes1.m_material = defaultMaterial; info.m_segments = new[] { segments0, segments1 }; info.m_nodes = new[] { nodes0, nodes1 }; } break; } }
internal static bool mayHaveLaneArrows(uint laneId, bool?startNode = null) { if (laneId <= 0) { return(false); } NetManager netManager = Singleton <NetManager> .instance; if (((NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[laneId].m_flags & (NetLane.Flags.Created | NetLane.Flags.Deleted)) != NetLane.Flags.Created) { return(false); } ushort segmentId = netManager.m_lanes.m_buffer[laneId].m_segment; var dir = NetInfo.Direction.Forward; var dir2 = ((netManager.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) ? dir : NetInfo.InvertDirection(dir); NetInfo segmentInfo = netManager.m_segments.m_buffer[segmentId].Info; uint curLaneId = netManager.m_segments.m_buffer[segmentId].m_lanes; int numLanes = segmentInfo.m_lanes.Length; int laneIndex = 0; int wIter = 0; while (laneIndex < numLanes && curLaneId != 0u) { ++wIter; if (wIter >= 100) { Log.Error("Too many iterations in Flags.mayHaveLaneArrows!"); break; } if (curLaneId == laneId) { NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex]; bool isStartNode = (laneInfo.m_finalDirection & dir2) == NetInfo.Direction.None; if (startNode != null && isStartNode != startNode) { return(false); } ushort nodeId = isStartNode ? netManager.m_segments.m_buffer[segmentId].m_startNode : netManager.m_segments.m_buffer[segmentId].m_endNode; if ((netManager.m_nodes.m_buffer[nodeId].m_flags & (NetNode.Flags.Created | NetNode.Flags.Deleted)) != NetNode.Flags.Created) { return(false); } return((netManager.m_nodes.m_buffer[nodeId].m_flags & NetNode.Flags.Junction) != NetNode.Flags.None); } curLaneId = netManager.m_lanes.m_buffer[curLaneId].m_nextLane; ++laneIndex; } return(false); }
public bool CanToggleTrafficLight(ushort nodeId, bool flag, // override? ref NetNode node, out ToggleTrafficLightError reason) { #if DEBUG bool logTrafficLights = DebugSwitch.TimedTrafficLights.Get() && DebugSettings.NodeId == nodeId; #else const bool logTrafficLights = false; #endif if (!flag && TrafficLightSimulationManager.Instance.HasTimedSimulation(nodeId)) { reason = ToggleTrafficLightError.HasTimedLight; if (logTrafficLights) { Log._Debug($"Cannot toggle traffic lights at node {nodeId}: Node has a timed traffic light"); } return(false); } if (flag && (!Services.NetService.IsNodeValid(nodeId) || !Services.NetService.CheckNodeFlags(nodeId, NetNode.Flags.Junction))) { reason = ToggleTrafficLightError.NoJunction; if (logTrafficLights) { Log._Debug($"Cannot toggle traffic lights at node {nodeId}: Node is not a junction"); } return(false); } if (!flag && Services.NetService.CheckNodeFlags(nodeId, NetNode.Flags.LevelCrossing)) { reason = ToggleTrafficLightError.IsLevelCrossing; if (logTrafficLights) { Log._Debug($"Cannot toggle traffic lights at node {nodeId}: Node is a level crossing"); } return(false); } int numRoads = 0; int numTrainTracks = 0; int numMonorailTracks = 0; int numPedSegments = 0; Services.NetService.IterateNodeSegments( nodeId, (ushort segmentId, ref NetSegment segment) => { NetInfo info = segment.Info; if (info.m_class.m_service == ItemClass.Service.Road) { ++numRoads; } else if ((info.m_vehicleTypes & VehicleInfo.VehicleType.Train) != VehicleInfo.VehicleType.None) { ++numTrainTracks; } else if ((info.m_vehicleTypes & VehicleInfo.VehicleType.Monorail) != VehicleInfo.VehicleType.None) { ++numMonorailTracks; } if (info.m_hasPedestrianLanes) { ++numPedSegments; } return(true); }); if (numRoads >= 2 || numTrainTracks >= 2 || numMonorailTracks >= 2 || numPedSegments != 0) { if (logTrafficLights) { Log._DebugFormat( "Can toggle traffic lights at node {0}: numRoads={1} numTrainTracks={2} " + "numMonorailTracks={3} numPedSegments={4}", nodeId, numRoads, numTrainTracks, numMonorailTracks, numPedSegments); } reason = ToggleTrafficLightError.None; return(true); } if (logTrafficLights) { Log._DebugFormat( "Cannot toggle traffic lights at node {0}: Insufficient segments. numRoads={1} " + "numTrainTracks={2} numMonorailTracks={3} numPedSegments={4}", nodeId, numRoads, numTrainTracks, numMonorailTracks, numPedSegments); } reason = ToggleTrafficLightError.InsufficientSegments; return(false); }
/// <summary> /// Creates a new node and returns it. /// </summary> /// <param name="newNodeId"></param> /// <param name="randomizer"></param> /// <param name="info"></param> /// <param name="newNodePosition"></param> /// <returns></returns> private static NetNode CreateNode(out ushort newNodeId, ref Randomizer randomizer, NetInfo info, Vector3 newNodePosition) { NetManager.instance.CreateNode(out newNodeId, ref randomizer, info, newNodePosition, Singleton <SimulationManager> .instance.m_currentBuildIndex + 1); return(NetManager.instance.m_nodes.m_buffer[newNodeId]); }
private void _guiVehicleRestrictionsWindow(int num) { if (GUILayout.Button(Translation.GetString("Invert"))) { // invert pattern NetInfo selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info; List <object[]> sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, selectedSegmentInfo, null); // TODO does not need to be sorted, but every lane should be a vehicle lane foreach (object[] laneData in sortedLanes) { uint laneId = (uint)laneData[0]; uint laneIndex = (uint)laneData[2]; NetInfo.Lane laneInfo = selectedSegmentInfo.m_lanes[laneIndex]; ExtVehicleType baseMask = VehicleRestrictionsManager.Instance().GetBaseMask(laneInfo); if (baseMask == ExtVehicleType.None) { continue; } ExtVehicleType allowedTypes = VehicleRestrictionsManager.Instance().GetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo); allowedTypes = ~allowedTypes & baseMask; VehicleRestrictionsManager.Instance().SetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo, laneId, allowedTypes); } RefreshCurrentRestrictedSegmentIds(); } GUILayout.BeginHorizontal(); if (GUILayout.Button(Translation.GetString("Allow_all_vehicles"))) { // allow all vehicle types NetInfo selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info; List <object[]> sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, selectedSegmentInfo, null); // TODO does not need to be sorted, but every lane should be a vehicle lane foreach (object[] laneData in sortedLanes) { uint laneId = (uint)laneData[0]; uint laneIndex = (uint)laneData[2]; NetInfo.Lane laneInfo = selectedSegmentInfo.m_lanes[laneIndex]; ExtVehicleType baseMask = VehicleRestrictionsManager.Instance().GetBaseMask(laneInfo); if (baseMask == ExtVehicleType.None) { continue; } VehicleRestrictionsManager.Instance().SetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo, laneId, baseMask); } RefreshCurrentRestrictedSegmentIds(); } if (GUILayout.Button(Translation.GetString("Ban_all_vehicles"))) { // ban all vehicle types NetInfo selectedSegmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[SelectedSegmentId].Info; List <object[]> sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(SelectedSegmentId, selectedSegmentInfo, null); // TODO does not need to be sorted, but every lane should be a vehicle lane foreach (object[] laneData in sortedLanes) { uint laneId = (uint)laneData[0]; uint laneIndex = (uint)laneData[2]; NetInfo.Lane laneInfo = selectedSegmentInfo.m_lanes[laneIndex]; VehicleRestrictionsManager.Instance().SetAllowedVehicleTypes(SelectedSegmentId, selectedSegmentInfo, laneIndex, laneInfo, laneId, ExtVehicleType.None); } RefreshCurrentRestrictedSegmentIds(); } GUILayout.EndHorizontal(); if (GUILayout.Button(Translation.GetString("Apply_vehicle_restrictions_to_all_road_segments_between_two_junctions"))) { ApplyRestrictionsToAllSegments(); RefreshCurrentRestrictedSegmentIds(); } GUI.DragWindow(); }
/// <summary> /// Mod's core. /// First, we create the segment using game's original code. /// Then we offset the 2 nodes of the segment, based on both direction and curve, so that we can finally create a /// segment between the 2 offset nodes. /// </summary> /// <param name="segment"></param> /// <param name="randomizer"></param> /// <param name="info"></param> /// <param name="startNode"></param> /// <param name="endNode"></param> /// <param name="startDirection"></param> /// <param name="endDirection"></param> /// <param name="buildIndex"></param> /// <param name="modifiedIndex"></param> /// <param name="invert"></param> /// <returns></returns> private bool CreateSegment(out ushort segment, ref Randomizer randomizer, NetInfo info, ushort startNode, ushort endNode, Vector3 startDirection, Vector3 endDirection, uint buildIndex, uint modifiedIndex, bool invert) { DebugUtils.Log($"Creating a segment and {ParallelRoadTool.SelectedRoadTypes.Count} parallel segments"); // Let's create the segment that the user requested var result = CreateSegmentOriginal(out segment, ref randomizer, info, startNode, endNode, startDirection, endDirection, buildIndex, modifiedIndex, invert); // If we're in upgrade mode we must stop here if (ParallelRoadTool.NetTool.m_mode == NetTool.Mode.Upgrade) { return(result); } // True if we have a slope that is going down from start to end node var isEnteringSlope = NetManager.instance.m_nodes.m_buffer[invert ? startNode : endNode].m_elevation > NetManager.instance.m_nodes.m_buffer[invert ? endNode : startNode].m_elevation; // HACK - [ISSUE-10] [ISSUE-18] Check if we've been called by an allowed caller, otherwise we can stop here var caller = string.Join(".", new [] { new System.Diagnostics.StackFrame(3).GetMethod().DeclaringType?.Name, new System.Diagnostics.StackFrame(2).GetMethod().Name, new System.Diagnostics.StackFrame(1).GetMethod().Name }); DebugUtils.Log($"Caller trace is {caller}"); if (!_allowedCallers.Contains(caller)) { return(result); } for (var i = 0; i < ParallelRoadTool.SelectedRoadTypes.Count; i++) { var currentRoadInfos = ParallelRoadTool.SelectedRoadTypes[i]; var horizontalOffset = currentRoadInfos.HorizontalOffset; var verticalOffset = currentRoadInfos.VerticalOffset; DebugUtils.Log($"Using offsets: h {horizontalOffset} | v {verticalOffset}"); // If the user didn't select a NetInfo we'll use the one he's using for the main road var selectedNetInfo = info.GetNetInfoWithElevation(currentRoadInfos.NetInfo ?? info, out var isSlope); // If the user is using a vertical offset we try getting the relative elevated net info and use it if (verticalOffset > 0 && selectedNetInfo.m_netAI.GetCollisionType() != ItemClass.CollisionType.Elevated) { selectedNetInfo = new RoadAIWrapper(selectedNetInfo.m_netAI).elevated ?? selectedNetInfo; } var isReversed = currentRoadInfos.IsReversed; // Left-hand drive means that any condition must be reversed if (ParallelRoadTool.Instance.IsLeftHandTraffic) { invert = !invert; isReversed = !isReversed; } DebugUtils.Log($"Using netInfo {selectedNetInfo.name} | reversed={isReversed} | invert={invert}"); // Get original nodes to clone them var startNetNode = NetManager.instance.m_nodes.m_buffer[startNode]; var endNetNode = NetManager.instance.m_nodes.m_buffer[endNode]; // Create two clone nodes by offsetting the original ones. // If we're not in "invert" mode (aka final part of a curve) and we already have an ending node with the same id of our starting node, we need to use that so that the segments can be connected. // If the previous segment was in "invert" mode and the current startNode is the same as the previous one, we need to connect them. // If we don't have any previous node matching our starting one, we need to clone startNode as this may be a new segment. ushort newStartNodeId; if (!invert && _endNodeId[i].HasValue && _endNodeId[i].Value == startNode) { DebugUtils.Log( $"[START] Using old node from previous iteration {_clonedEndNodeId[i].Value} instead of the given one {startNode}"); newStartNodeId = _clonedEndNodeId[i].Value; DebugUtils.Log( $"[START] Start node{startNetNode.m_position} becomes {NetManager.instance.m_nodes.m_buffer[newStartNodeId].m_position}"); } else if (!invert && _isPreviousInvert && _startNodeId[i].HasValue && _startNodeId[i].Value == startNode) { DebugUtils.Log( $"[START] Using old node from previous iteration {_clonedStartNodeId[i].Value} instead of the given one {startNode}"); newStartNodeId = _clonedStartNodeId[i].Value; DebugUtils.Log( $"[START] Start node{startNetNode.m_position} becomes {NetManager.instance.m_nodes.m_buffer[newStartNodeId].m_position}"); } else { var newStartPosition = startNetNode.m_position.Offset(startDirection, horizontalOffset, verticalOffset, invert); DebugUtils.Log($"[START] {startNetNode.m_position} --> {newStartPosition} | isLeftHand = {ParallelRoadTool.Instance.IsLeftHandTraffic} | invert = {invert} | isSlope = {isSlope}"); newStartNodeId = NodeAtPositionOrNew(ref randomizer, info, newStartPosition); } // Same thing as startNode, but this time we don't clone if we're in "invert" mode as we may need to connect this ending node with the previous ending one. ushort newEndNodeId; if (invert && _endNodeId[i].HasValue && _endNodeId[i].Value == endNode) { DebugUtils.Log( $"[END] Using old node from previous iteration {_clonedEndNodeId[i].Value} instead of the given one {endNode}"); newEndNodeId = _clonedEndNodeId[i].Value; DebugUtils.Log( $"[END] End node{endNetNode.m_position} becomes {NetManager.instance.m_nodes.m_buffer[newEndNodeId].m_position}"); } else { var newEndPosition = endNetNode.m_position.Offset(endDirection, horizontalOffset, verticalOffset, !(invert && isSlope && isEnteringSlope)); DebugUtils.Log($"[END] {endNetNode.m_position} --> {newEndPosition} | isEnteringSlope = {isEnteringSlope} | invert = {invert} | isSlope = {isSlope}"); newEndNodeId = NodeAtPositionOrNew(ref randomizer, info, newEndPosition); } // Store current end nodes in case we may need to connect the following segment to them _endNodeId[i] = endNode; _clonedEndNodeId[i] = newEndNodeId; _startNodeId[i] = startNode; _clonedStartNodeId[i] = newStartNodeId; if (isReversed) { Vector3 tempStartDirection; Vector3 tempEndDirection; if (startDirection == -endDirection) { // Straight segment, we invert both directions tempStartDirection = -startDirection; tempEndDirection = -endDirection; } else { // Curve, we need to swap start and end direction tempStartDirection = endDirection; tempEndDirection = startDirection; } // Create the segment between the two cloned nodes, inverting start and end node result = CreateSegmentOriginal(out segment, ref randomizer, selectedNetInfo, newEndNodeId, newStartNodeId, tempStartDirection, tempEndDirection, Singleton <SimulationManager> .instance.m_currentBuildIndex + 1, Singleton <SimulationManager> .instance.m_currentBuildIndex, invert); } else { // Create the segment between the two cloned nodes result = CreateSegmentOriginal(out segment, ref randomizer, selectedNetInfo, newStartNodeId, newEndNodeId, startDirection, endDirection, Singleton <SimulationManager> .instance.m_currentBuildIndex + 1, Singleton <SimulationManager> .instance.m_currentBuildIndex, invert); } } _isPreviousInvert = invert; return(result); }
public void BuildUp(NetInfo info, NetInfoVersion version) { /////////////////////////// // Template // /////////////////////////// var roadTunnelInfo = Prefabs.Find <NetInfo>(NetInfos.Vanilla.ROAD_4L_TUNNEL); var roadInfo = Prefabs.Find <NetInfo>(NetInfos.Vanilla.ROAD_6L); /////////////////////////// // 3DModeling // /////////////////////////// info.Setup32m3mSW4mMdnMesh(version); /////////////////////////// // Texturing // /////////////////////////// SetupTextures(info, version); /////////////////////////// // Set up // /////////////////////////// info.m_hasParkingSpaces = true; if (version == NetInfoVersion.Ground) { info.m_pavementWidth = 3; } else if (version == NetInfoVersion.Tunnel) { info.m_pavementWidth = 6; } else { info.m_pavementWidth = 5; } info.m_halfWidth = (version == NetInfoVersion.Tunnel ? 17 : 16); if (version == NetInfoVersion.Tunnel) { info.m_setVehicleFlags = Vehicle.Flags.Transition | Vehicle.Flags.Underground; info.m_setCitizenFlags = CitizenInstance.Flags.Transition | CitizenInstance.Flags.Underground; info.m_class = roadTunnelInfo.m_class.Clone(NetInfoClasses.NEXT_XLARGE_ROAD_TUNNEL); } else { info.m_class = roadInfo.m_class.Clone(NetInfoClasses.NEXT_XLARGE_ROAD); } // Setting up lanes info.SetRoadLanes(version, new LanesConfiguration { IsTwoWay = true, LaneWidth = 3, LanesToAdd = 2, PedPropOffsetX = version == NetInfoVersion.Slope ? 1.5f : 1f, CenterLane = CenterLaneType.Median, CenterLaneWidth = 4, BusStopOffset = 3 }); var medianLane = info.GetMedianLane(); var leftPedLane = info.GetLeftRoadShoulder(); var rightPedLane = info.GetRightRoadShoulder(); // Fix for T++ legacy support (reordering) if (medianLane != null) { info.m_lanes = info .m_lanes .Except(medianLane) .Union(medianLane) .ToArray(); } //Setting Up Props var leftPedLaneProps = leftPedLane.m_laneProps.m_props.ToList(); var rightPedLaneProps = rightPedLane.m_laneProps.m_props.ToList(); var medianPedLaneProps = medianLane?.m_laneProps?.m_props.ToList(); if (version != NetInfoVersion.Tunnel) { var medianStreetLight = medianPedLaneProps?.FirstOrDefault(p => p.m_prop.name.ToLower().Contains("avenue light")); if (medianStreetLight != null) { medianStreetLight.m_finalProp = medianStreetLight.m_prop = Prefabs.Find <PropInfo>(LargeAvenueMedianLightBuilder.NAME); } } if (medianPedLaneProps != null) { medianPedLaneProps.RemoveProps("50 Speed Limit"); } if (version == NetInfoVersion.Slope) { leftPedLaneProps.AddLeftWallLights(info.m_pavementWidth); rightPedLaneProps.AddRightWallLights(info.m_pavementWidth); } leftPedLane.m_laneProps.m_props = leftPedLaneProps.ToArray(); rightPedLane.m_laneProps.m_props = rightPedLaneProps.ToArray(); if (medianLane?.m_laneProps != null && medianPedLaneProps != null) { medianLane.m_laneProps.m_props = medianPedLaneProps.ToArray(); } info.TrimAboveGroundProps(version); // AI var owPlayerNetAI = roadInfo.GetComponent <PlayerNetAI>(); var playerNetAI = info.GetComponent <PlayerNetAI>(); if (owPlayerNetAI != null && playerNetAI != null) { playerNetAI.m_constructionCost = owPlayerNetAI.m_constructionCost * 2; // Charge by the lane? playerNetAI.m_maintenanceCost = owPlayerNetAI.m_maintenanceCost * 2; // Charge by the lane? } var roadBaseAI = info.GetComponent <RoadBaseAI>(); if (roadBaseAI != null) { roadBaseAI.m_trafficLights = true; } }
/// <summary> /// Calculates if the given segment info describes a highway segment /// </summary> /// <param name="segmentInfo"></param> /// <returns></returns> private bool CalculateIsHighway(NetInfo segmentInfo) { return(segmentInfo.m_netAI is RoadBaseAI && ((RoadBaseAI)segmentInfo.m_netAI).m_highwayRules); }
public static void setLaneSpeedLimit(ushort segmentId, uint laneIndex, uint laneId, ushort?speedLimit) { if (segmentId <= 0 || laneIndex < 0 || laneId <= 0) { return; } if ((Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_flags & (NetSegment.Flags.Created | NetSegment.Flags.Deleted)) != NetSegment.Flags.Created) { return; } if (((NetLane.Flags)Singleton <NetManager> .instance.m_lanes.m_buffer[laneId].m_flags & (NetLane.Flags.Created | NetLane.Flags.Deleted)) != NetLane.Flags.Created) { return; } NetInfo segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info; if (laneIndex >= segmentInfo.m_lanes.Length) { return; } try { Monitor.Enter(laneSpeedLimitLock); #if DEBUGFLAGS Log._Debug($"Flags.setLaneSpeedLimit: setting speed limit of lane index {laneIndex} @ seg. {segmentId} to {speedLimit}"); #endif if (speedLimit == null) { laneSpeedLimit.Remove(laneId); if (laneSpeedLimitArray[segmentId] == null) { return; } if (laneIndex >= laneSpeedLimitArray[segmentId].Length) { return; } laneSpeedLimitArray[segmentId][laneIndex] = null; } else { laneSpeedLimit[laneId] = (ushort)speedLimit; // save speed limit into the fast-access array. // (1) ensure that the array is defined and large enough if (laneSpeedLimitArray[segmentId] == null) { laneSpeedLimitArray[segmentId] = new ushort?[segmentInfo.m_lanes.Length]; } else if (laneSpeedLimitArray[segmentId].Length < segmentInfo.m_lanes.Length) { var oldArray = laneSpeedLimitArray[segmentId]; laneSpeedLimitArray[segmentId] = new ushort?[segmentInfo.m_lanes.Length]; Array.Copy(oldArray, laneSpeedLimitArray[segmentId], oldArray.Length); } // (2) insert the custom speed limit laneSpeedLimitArray[segmentId][laneIndex] = speedLimit; } } finally { Monitor.Exit(laneSpeedLimitLock); } }
private static void SetupTextures(NetInfo info, NetInfoVersion version) { switch (version) { case NetInfoVersion.Ground: info.SetAllSegmentsTexture( new TextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_Segment__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_Segment__AlphaMap.png"), new LODTextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_SegmentLOD__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_SegmentLOD__AlphaMap.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_SegmentLOD__XYS.png")); break; case NetInfoVersion.Elevated: case NetInfoVersion.Bridge: info.SetAllSegmentsTexture( new TextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Elevated_MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Elevated_Segment__APRMap.png"), new LODTextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Elevated_LOD__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Elevated_SegmentLOD__APRMap.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Elevated_LOD__XYSMap.png")); info.SetAllNodesTexture( new TextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Elevated_MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Elevated_Node__APRMap.png"), new LODTextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Elevated_LOD__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Elevated_NodeLOD__APRMap.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Elevated_LOD__XYSMap.png")); break; case NetInfoVersion.Slope: for (int i = 0; i < info.m_segments.Length; i++) { if (info.m_segments[i].m_mesh.name == "Slope") { info.m_segments[i].SetTextures( new TextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_Segment__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_Segment__AlphaMap.png"), new LODTextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_SegmentLOD__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_SegmentLOD__AlphaMap.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Slope_SegmentLOD2__XYSMap.png")); } else { info.m_segments[i].SetTextures( new TextureSet (@"Roads\Highways\Highway4L\Textures\Slope_Segment__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Slope_Segment__APRMap.png"), new LODTextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Slope_SegmentLOD__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Slope_SegmentLOD__APRMap.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Slope_SegmentLOD__XYSMap.png")); } } for (int i = 0; i < info.m_nodes.Length; i++) { if (info.m_nodes[i].m_mesh.name == "Slope_Node") { info.m_nodes[i].SetTextures( new TextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_Segment__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_Node__AlphaMap.png"), new LODTextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_SegmentLOD__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_SegmentLOD__AlphaMap.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Ground_SegmentLOD__XYS.png")); } else { info.m_nodes[i].SetTextures( new TextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_Segment__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_Node__APRMap.png"), new LODTextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_NodeLOD__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_LOD__APRMap.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_LOD__XYSMap.png")); } } //info.SetAllNodesTexture( //new TextureSet // (@"Roads\Highways\Highway4L\Textures\Slope_Node__MainTex.png", // @"Roads\Highways\Highway4L\Textures\Ground_Node__APRMap.png"), //new LODTextureSet // (@"Roads\Highways\Highway4L\Textures\Ground_NodeLOD__MainTex.png", // @"Roads\Highways\Highway4L\Textures\Ground_NodeLOD__APRMap.png", // @"Roads\Highways\Highway4L\Textures\Ground_LOD__XYSMap.png")); break; case NetInfoVersion.Tunnel: { info.SetAllSegmentsTexture( new TextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_Segment__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_Segment__APRMap.png"), new LODTextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_NodeLOD__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_LOD__APRMap.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_LOD__XYSMap.png")); info.SetAllNodesTexture( new TextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_Segment__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_Node__APRMap.png"), new LODTextureSet (@"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_NodeLOD__MainTex.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_LOD__APRMap.png", @"Roads\SmallHeavyRoads\OneWay4L\Textures\Tunnel_LOD__XYSMap.png")); break; } } }
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; }
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 ? JunctionUITextures.LaneChangeAllowedTexture2D : JunctionUITextures.LaneChangeForbiddenTexture2D, 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 ? JunctionUITextures.UturnAllowedTexture2D : JunctionUITextures.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; } } } 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 ? JunctionUITextures.EnterBlockedJunctionAllowedTexture2D : JunctionUITextures.EnterBlockedJunctionForbiddenTexture2D, 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 ? JunctionUITextures.PedestrianCrossingAllowedTexture2D : JunctionUITextures.PedestrianCrossingForbiddenTexture2D, 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 ? JunctionUITextures.LeftOnRedAllowedTexture2D : JunctionUITextures.LeftOnRedForbiddenTexture2D, 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 ? JunctionUITextures.RightOnRedAllowedTexture2D : JunctionUITextures.RightOnRedForbiddenTexture2D, 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); }
public static void Setup22mMesh(this NetInfo info, NetInfoVersion version, LanesLayoutStyle lanesLayoutStyle = LanesLayoutStyle.Symmetrical) { /////////////////////////// // Template // /////////////////////////// var highwayInfo = Prefabs.Find <NetInfo>(NetInfos.Vanilla.HIGHWAY_3L); var defaultMaterial = highwayInfo.m_nodes[0].m_material; var defaultLODMaterial = highwayInfo.m_nodes[0].m_lodMaterial; if (version == NetInfoVersion.Ground) { if (lanesLayoutStyle != LanesLayoutStyle.Symmetrical) { var segment0 = info.m_segments[0].ShallowClone(); RoadHelper.HandleAsymSegmentFlags(segment0); info.m_segments = new[] { segment0 }; } } if (version == NetInfoVersion.Elevated || version == NetInfoVersion.Bridge) { if (lanesLayoutStyle != LanesLayoutStyle.Symmetrical) { var segment0 = info.m_segments[0].ShallowClone(); RoadHelper.HandleAsymSegmentFlags(segment0); var segments = info.m_segments.ToList(); segments[0] = segment0; info.m_segments = segments.ToArray(); } } if (version == NetInfoVersion.Slope) { var segments0 = info.m_segments[0].ShallowClone(); var segments1 = info.m_segments[1].ShallowClone(); var segments2 = info.m_segments[1].ShallowClone(); var nodes0 = info.m_nodes[0].ShallowClone(); var nodes1 = info.m_nodes[1].ShallowClone(); var nodes2 = info.m_nodes[0].ShallowClone(); //var nodes1 = info.m_nodes[1].ShallowClone(); segments1 .SetMeshes (@"Roads\Highways\Common\Meshes\22m\Slope.obj"); segments2 .SetMeshes (@"Roads\Highways\Common\Meshes\22m\Slope_Cover.obj", @"Roads\Common\Meshes\Blank.obj") .SetConsistentUVs(); nodes2 .SetFlags(NetNode.Flags.Underground, NetNode.Flags.None) .SetMeshes (@"Roads\Highways\Common\Meshes\22m\Slope_U_Node.obj", @"Roads\Highways\Common\Meshes\22m\Slope_U_Node_LOD.obj"); //nodes1 // .SetFlags(NetNode.Flags.UndergroundTransition, NetNode.Flags.None) // .SetMeshes // (@"Roads\Highways\Common\Meshes\22m\Slope_U_Trans.obj", // @"Roads\Highways\Common\Meshes\22m\Slope_U_Trans_LOD.obj"); if (lanesLayoutStyle != LanesLayoutStyle.Symmetrical) { RoadHelper.HandleAsymSegmentFlags(segments1); } nodes2.m_material = defaultMaterial; nodes2.m_lodMaterial = defaultLODMaterial; //nodes1.m_material = defaultMaterial; //nodes1.m_lodMaterial = defaultLODMaterial; info.m_segments = new[] { segments0, segments1 }; info.m_nodes = new[] { nodes0, nodes1, nodes2 }; } else if (version == NetInfoVersion.Tunnel) { var segments0 = info.m_segments[0].ShallowClone(); var segments1 = info.m_segments[0].ShallowClone(); var nodes0 = info.m_nodes[0].ShallowClone(); var nodes1 = info.m_nodes[0].ShallowClone(); var nodes2 = info.m_nodes[0].ShallowClone(); nodes1.m_flagsForbidden = NetNode.Flags.None; nodes1.m_flagsRequired = NetNode.Flags.None; segments1.SetMeshes (@"Roads\Highways\Common\Meshes\22m\Tunnel.obj", @"Roads\Highways\Common\Meshes\22m\Tunnel_LOD.obj"); nodes1.SetMeshes (@"Roads\Highways\Common\Meshes\22m\Tunnel_Node.obj", @"Roads\Highways\Common\Meshes\22m\Tunnel_Node_LOD.obj"); //nodes2.SetMeshes // (@"Roads\Highways\Common\Meshes\22m\Tunnel_Trans.obj", // @"Roads\Highways\Common\Meshes\22m\Tunnel_Trans_LOD.obj"); if (lanesLayoutStyle != LanesLayoutStyle.Symmetrical) { RoadHelper.HandleAsymSegmentFlags(segments1); } segments1.m_material = defaultMaterial; segments1.m_lodMaterial = defaultLODMaterial; nodes1.m_material = defaultMaterial; nodes1.m_lodMaterial = defaultLODMaterial; info.m_segments = new[] { segments0, segments1 }; info.m_nodes = new[] { nodes0, nodes1, nodes2 }; } }
private static BuildingInfo.PathInfo ChainPath(BuildingInfo.PathInfo startPath, Vector3 endNode, int startNodeIndex = -1, NetInfo info = null) { var newNodes = new List <Vector3>(); var newPath = startPath.ShallowClone(); if (startNodeIndex == -1 || startNodeIndex >= startPath.m_nodes.Count()) { startNodeIndex = startPath.m_nodes.Count() - 1; } if (info != null) { newPath.AssignNetInfo(info); } var startNode = startPath.m_nodes[startNodeIndex]; newNodes.Add(startNode); newNodes.Add(endNode); newPath.m_nodes = newNodes.ToArray(); MarkPathGenerated(newPath); return(newPath); }