public bool IsMonorailSegment(NetInfo segmentInfo) { ItemClass connectionClass = segmentInfo.GetConnectionClass(); return(connectionClass.m_service == ItemClass.Service.PublicTransport && connectionClass.m_subService == ItemClass.SubService.PublicTransportMonorail); }
private static bool FindConnectNode(FastList <ushort> buffer, Vector3 pos, NetInfo info2, out NetTool.ControlPoint point) { point = default(NetTool.ControlPoint); NetManager instance = Singleton <NetManager> .instance; ItemClass.Service service = info2.m_class.m_service; ItemClass.SubService subService = info2.m_class.m_subService; ItemClass.Layer layer = info2.m_class.m_layer; ItemClass.Service service2 = ItemClass.Service.None; ItemClass.SubService subService2 = ItemClass.SubService.None; ItemClass.Layer layer2 = ItemClass.Layer.Default; if (info2.m_intersectClass != null) { service2 = info2.m_intersectClass.m_service; subService2 = info2.m_intersectClass.m_subService; layer2 = info2.m_intersectClass.m_layer; } if (info2.m_netAI.SupportUnderground() || info2.m_netAI.IsUnderground()) { layer |= (ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels); layer2 |= (ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels); } for (int i = 0; i < buffer.m_size; i++) { ushort num = buffer.m_buffer[i]; if (Vector3.SqrMagnitude(pos - instance.m_nodes.m_buffer[(int)num].m_position) < 0.001f) { NetInfo info3 = instance.m_nodes.m_buffer[(int)num].Info; ItemClass connectionClass = info3.GetConnectionClass(); if (((service == ItemClass.Service.None || connectionClass.m_service == service) && (subService == ItemClass.SubService.None || connectionClass.m_subService == subService) && (layer == ItemClass.Layer.None || (connectionClass.m_layer & layer) != ItemClass.Layer.None)) || (info3.m_intersectClass != null && (service == ItemClass.Service.None || info3.m_intersectClass.m_service == service) && (subService == ItemClass.SubService.None || info3.m_intersectClass.m_subService == subService) && (layer == ItemClass.Layer.None || (info3.m_intersectClass.m_layer & layer) != ItemClass.Layer.None)) || (connectionClass.m_service == service2 && (subService2 == ItemClass.SubService.None || connectionClass.m_subService == subService2) && (layer2 == ItemClass.Layer.None || (connectionClass.m_layer & layer2) != ItemClass.Layer.None))) { point.m_position = instance.m_nodes.m_buffer[(int)num].m_position; point.m_direction = Vector3.zero; point.m_node = num; point.m_segment = 0; if (info3.m_netAI.IsUnderground()) { point.m_elevation = (float)(-(float)instance.m_nodes.m_buffer[(int)num].m_elevation); } else { point.m_elevation = (float)instance.m_nodes.m_buffer[(int)num].m_elevation; } return(true); } } } return(false); }
public Dictionary <NetInfo, ushort> GetDefaultSpeedLimits() { Dictionary <NetInfo, ushort> ret = new Dictionary <NetInfo, ushort>(); int numLoaded = PrefabCollection <NetInfo> .LoadedCount(); for (uint i = 0; i < numLoaded; ++i) { NetInfo info = PrefabCollection <NetInfo> .GetLoaded(i); ushort defaultSpeedLimit = GetAverageDefaultCustomSpeedLimit(info, NetInfo.Direction.Forward); ret.Add(info, defaultSpeedLimit); Log._Debug($"Loaded NetInfo: {info.name}, connectionClass.service: {info.GetConnectionClass().m_service.ToString()}, connectionClass.subService: {info.GetConnectionClass().m_subService.ToString()}, avg. default speed limit: {defaultSpeedLimit}"); } return(ret); }
private static bool RequireFixedHeight(BuildingInfo buildingInfo, NetInfo info2, Vector3 pos) { if (info2.m_useFixedHeight) { return(true); } ItemClass.Service service = info2.m_class.m_service; ItemClass.SubService subService = info2.m_class.m_subService; ItemClass.Layer layer = info2.m_class.m_layer; ItemClass.Service service2 = ItemClass.Service.None; ItemClass.SubService subService2 = ItemClass.SubService.None; ItemClass.Layer layer2 = ItemClass.Layer.Default; if (info2.m_intersectClass != null) { service2 = info2.m_intersectClass.m_service; subService2 = info2.m_intersectClass.m_subService; layer2 = info2.m_intersectClass.m_layer; } if (info2.m_netAI.SupportUnderground() || info2.m_netAI.IsUnderground()) { layer |= (ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels); layer2 |= (ItemClass.Layer.Default | ItemClass.Layer.MetroTunnels); } for (int i = 0; i < buildingInfo.m_paths.Length; i++) { BuildingInfo.PathInfo pathInfo = buildingInfo.m_paths[i]; if (pathInfo.m_finalNetInfo != null && pathInfo.m_finalNetInfo.m_useFixedHeight && pathInfo.m_nodes != null && pathInfo.m_nodes.Length != 0) { for (int j = 0; j < pathInfo.m_nodes.Length; j++) { if (Vector3.SqrMagnitude(pos - pathInfo.m_nodes[j]) < 0.001f) { NetInfo finalNetInfo = pathInfo.m_finalNetInfo; ItemClass connectionClass = finalNetInfo.GetConnectionClass(); if (((service == ItemClass.Service.None || connectionClass.m_service == service) && (subService == ItemClass.SubService.None || connectionClass.m_subService == subService) && (layer == ItemClass.Layer.None || (connectionClass.m_layer & layer) != ItemClass.Layer.None)) || (finalNetInfo.m_intersectClass != null && (service == ItemClass.Service.None || finalNetInfo.m_intersectClass.m_service == service) && (subService == ItemClass.SubService.None || finalNetInfo.m_intersectClass.m_subService == subService) && (layer == ItemClass.Layer.None || (finalNetInfo.m_intersectClass.m_layer & layer) != ItemClass.Layer.None)) || (finalNetInfo.m_netAI.CanIntersect(info2) && connectionClass.m_service == service2 && (subService2 == ItemClass.SubService.None || connectionClass.m_subService == subService2) && (layer2 == ItemClass.Layer.None || (connectionClass.m_layer & layer2) != ItemClass.Layer.None))) { return(true); } } } } } return(false); }
private bool RayCastSegmentAndNode(NetInfo connectedType, Segment3 ray, float snapElevation, bool nameOnly, ItemClass.Service service, ItemClass.Service service2, ItemClass.SubService subService, ItemClass.SubService subService2, ItemClass.Layer itemLayers, ItemClass.Layer itemLayers2, NetNode.Flags ignoreNodeFlags, NetSegment.Flags ignoreSegmentFlags, out Vector3 hit, out ushort nodeIndex, out ushort segmentIndex) { var bounds = new Bounds(new Vector3(0f, 512f, 0f), new Vector3(17280f, 1152f, 17280f)); if (ray.Clip(bounds)) { Vector3 vector = ray.b - ray.a; var num = (int)((ray.a.x / 64f) + 135f); var num2 = (int)((ray.a.z / 64f) + 135f); var num3 = (int)((ray.b.x / 64f) + 135f); var num4 = (int)((ray.b.z / 64f) + 135f); var num5 = Mathf.Abs(vector.x); var num6 = Mathf.Abs(vector.z); int num7; int num8; if (num5 >= num6) { num7 = ((vector.x <= 0f) ? -1 : 1); num8 = 0; if (num5 > 0.001f) { vector *= 64f / num5; } } else { num7 = 0; num8 = ((vector.z <= 0f) ? -1 : 1); if (num6 > 0.001f) { vector *= 64f / num6; } } var num9 = 2f; var num10 = 16f; var num11 = 2f; var num12 = 16f; ushort num13 = 0; ushort num14 = 0; ushort num15 = 0; Vector3 vector2 = ray.a; Vector3 vector3 = ray.a; var num16 = num; var num17 = num2; do { Vector3 vector4 = vector3 + vector; int num18; int num19; int num20; int num21; if (num7 != 0) { if ((num16 == num && num7 > 0) || (num16 == num3 && num7 < 0)) { num18 = Mathf.Max((int)(((vector4.x - 64f) / 64f) + 135f), 0); } else { num18 = Mathf.Max(num16, 0); } if ((num16 == num && num7 < 0) || (num16 == num3 && num7 > 0)) { num19 = Mathf.Min((int)(((vector4.x + 64f) / 64f) + 135f), 269); } else { num19 = Mathf.Min(num16, 269); } num20 = Mathf.Max((int)(((Mathf.Min(vector2.z, vector4.z) - 64f) / 64f) + 135f), 0); num21 = Mathf.Min((int)(((Mathf.Max(vector2.z, vector4.z) + 64f) / 64f) + 135f), 269); } else { if ((num17 == num2 && num8 > 0) || (num17 == num4 && num8 < 0)) { num20 = Mathf.Max((int)(((vector4.z - 64f) / 64f) + 135f), 0); } else { num20 = Mathf.Max(num17, 0); } if ((num17 == num2 && num8 < 0) || (num17 == num4 && num8 > 0)) { num21 = Mathf.Min((int)(((vector4.z + 64f) / 64f) + 135f), 269); } else { num21 = Mathf.Min(num17, 269); } num18 = Mathf.Max((int)(((Mathf.Min(vector2.x, vector4.x) - 64f) / 64f) + 135f), 0); num19 = Mathf.Min((int)(((Mathf.Max(vector2.x, vector4.x) + 64f) / 64f) + 135f), 269); } for (var i = num20; i <= num21; i++) { for (var j = num18; j <= num19; j++) { var num22 = Singleton <NetManager> .instance.m_nodeGrid[(i * 270) + j]; var num23 = 0; while (num22 != 0) { NetNode.Flags flags = NodeBuffer[num22].m_flags; NetInfo info = NodeBuffer[num22].Info; ItemClass connectionClass = info.GetConnectionClass(); if ((((service == ItemClass.Service.None || connectionClass.m_service == service) && (subService == ItemClass.SubService.None || connectionClass.m_subService == subService) && (itemLayers == ItemClass.Layer.None || (connectionClass.m_layer & itemLayers) != ItemClass.Layer.None)) || (info.m_intersectClass != null && (service == ItemClass.Service.None || info.m_intersectClass.m_service == service) && (subService == ItemClass.SubService.None || info.m_intersectClass.m_subService == subService) && (itemLayers == ItemClass.Layer.None || (info.m_intersectClass.m_layer & itemLayers) != ItemClass.Layer.None)) || (info.m_netAI.CanIntersect(connectedType) && connectionClass.m_service == service2 && (subService2 == ItemClass.SubService.None || connectionClass.m_subService == subService2) && (itemLayers2 == ItemClass.Layer.None || (connectionClass.m_layer & itemLayers2) != ItemClass.Layer.None))) && (flags & ignoreNodeFlags) == NetNode.Flags.None && (connectedType == null || (info.m_netAI.CanConnect(connectedType) && connectedType.m_netAI.CanConnect(info)))) { var flag = false; if ((flags & (NetNode.Flags.Middle | NetNode.Flags.Untouchable)) == (NetNode.Flags.Middle | NetNode.Flags.Untouchable) && NodeBuffer[num22].CountSegments(NetSegment.Flags.Untouchable, 0) >= 2) { flag = true; } if (!flag && NodeBuffer[num22].RayCast(ray, snapElevation, out var num24, out var num25) && (num25 < num12 || (num25 == num12 && num24 < num11))) { num11 = num24; num12 = num25; num14 = num22; } } num22 = NodeBuffer[num22].m_nextGridNode; if (++num23 > 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } } for (var k = num20; k <= num21; k++) { for (var l = num18; l <= num19; l++) { var num26 = Singleton <NetManager> .instance.m_segmentGrid[(k * 270) + l]; var num27 = 0; while (num26 != 0) { NetSegment.Flags flags2 = SegmentBuffer[num26].m_flags; NetInfo info2 = SegmentBuffer[num26].Info; ItemClass connectionClass2 = info2.GetConnectionClass(); if (((service == ItemClass.Service.None || connectionClass2.m_service == service) && (subService == ItemClass.SubService.None || connectionClass2.m_subService == subService) && (itemLayers == ItemClass.Layer.None || (connectionClass2.m_layer & itemLayers) != ItemClass.Layer.None || nameOnly)) || (info2.m_intersectClass != null && (service == ItemClass.Service.None || info2.m_intersectClass.m_service == service) && (subService == ItemClass.SubService.None || info2.m_intersectClass.m_subService == subService) && (itemLayers == ItemClass.Layer.None || (info2.m_intersectClass.m_layer & itemLayers) != ItemClass.Layer.None || nameOnly)) || (info2.m_netAI.CanIntersect(connectedType) && connectionClass2.m_service == service2 && (subService2 == ItemClass.SubService.None || connectionClass2.m_subService == subService2) && (itemLayers2 == ItemClass.Layer.None || (connectionClass2.m_layer & itemLayers2) != ItemClass.Layer.None || nameOnly))) { var flag2 = (flags2 & ignoreSegmentFlags) != NetSegment.Flags.None && !nameOnly; if ((flags2 & ignoreSegmentFlags) == NetSegment.Flags.None && (connectedType == null || (info2.m_netAI.CanConnect(connectedType) && connectedType.m_netAI.CanConnect(info2))) && SegmentBuffer[num26].RayCast(num26, ray, snapElevation, nameOnly, out var num28, out var num29) && (num29 < num10 || (num29 == num10 && num28 < num9))) { var startNode = SegmentBuffer[num26].m_startNode; var endNode = SegmentBuffer[num26].m_endNode; Vector3 position = NodeBuffer[startNode].m_position; Vector3 position2 = NodeBuffer[endNode].m_position; var num30 = NodeBuffer[startNode].Info.GetMinNodeDistance(); var num31 = NodeBuffer[endNode].Info.GetMinNodeDistance(); num10 = num29; num9 = num28; Vector3 a = ray.a + ((ray.b - ray.a) * num28); NetNode.Flags flags3 = NodeBuffer[startNode].m_flags; if ((flags3 & NetNode.Flags.End) != NetNode.Flags.None) { flags3 &= ~NetNode.Flags.Moveable; } NetNode.Flags flags4 = NodeBuffer[endNode].m_flags; if ((flags4 & NetNode.Flags.End) != NetNode.Flags.None) { flags4 &= ~NetNode.Flags.Moveable; } if (flag2) { num30 = 1000f; num31 = 1000f; } var flag3 = (flags3 & (NetNode.Flags.Moveable | ignoreNodeFlags)) == NetNode.Flags.None; var flag4 = (flags4 & (NetNode.Flags.Moveable | ignoreNodeFlags)) == NetNode.Flags.None; var num32 = VectorUtils.LengthSqrXZ(a - position) / (num30 * num30); var num33 = VectorUtils.LengthSqrXZ(a - position2) / (num31 * num31); if (flag3 && num32 < 1f && (!flag4 || num32 < num33) && !nameOnly) { num13 = startNode; if (!flag2) { num15 = num26; } } else if (flag4 && num33 < 1f && !nameOnly) { num13 = endNode; if (!flag2) { num15 = num26; } } else if (!flag2) { num13 = 0; num15 = num26; } } } num26 = SegmentBuffer[num26].m_nextGridSegment; if (++num27 > 36864) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } } } vector2 = vector3; vector3 = vector4; num16 += num7; num17 += num8; }while ((num16 <= num3 || num7 <= 0) && (num16 >= num3 || num7 >= 0) && (num17 <= num4 || num8 <= 0) && (num17 >= num4 || num8 >= 0)); if (num12 < num10 || (num12 == num10 && num11 < num9)) { num9 = num11; num13 = num14; } if (num9 != 2f) { hit = ray.Position(num9); nodeIndex = num13; segmentIndex = num15; return(true); } } hit = Vector3.zero; nodeIndex = 0; segmentIndex = 0; return(false); }
public bool IsRoadSegment(NetInfo segmentInfo) { ItemClass connectionClass = segmentInfo.GetConnectionClass(); return(connectionClass.m_service == ItemClass.Service.Road); }
private bool drawVehicleRestrictionHandles(ushort segmentId, bool viewOnly, out bool stateUpdated) { stateUpdated = false; if (viewOnly && !Options.vehicleRestrictionsOverlay && TrafficManagerTool.GetToolMode() != ToolMode.VehicleRestrictions) { return(false); } Vector3 center = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_bounds.center; var screenPos = Camera.main.WorldToScreenPoint(center); screenPos.y = Screen.height - screenPos.y; if (screenPos.z < 0) { return(false); } var camPos = Singleton <SimulationManager> .instance.m_simulationView.m_position; var diff = center - camPos; if (diff.magnitude > TrafficManagerTool.PriorityCloseLod) { return(false); // do not draw if too distant } int numDirections; // TODO refactor vehicle mask int numLanes = TrafficManagerTool.GetSegmentNumVehicleLanes(segmentId, null, out numDirections, VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train); // draw vehicle restrictions over each lane NetInfo segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info; Vector3 yu = (Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_endDirection - Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_startDirection).normalized; if ((Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.None) { yu = -yu; } Vector3 xu = Vector3.Cross(yu, new Vector3(0, 1f, 0)).normalized; float f = viewOnly ? 4f : 7f; // reserved sign size in game coordinates ItemClass connectionClass = segmentInfo.GetConnectionClass(); int maxNumSigns = 0; if (connectionClass.m_service == ItemClass.Service.Road) { maxNumSigns = roadVehicleTypes.Length; } else if (connectionClass.m_service == ItemClass.Service.PublicTransport && connectionClass.m_subService == ItemClass.SubService.PublicTransportTrain) { maxNumSigns = railVehicleTypes.Length; } //Vector3 zero = center - 0.5f * (float)(numLanes + numDirections - 1) * f * (xu + yu); // "bottom left" Vector3 zero = center - 0.5f * (float)(numLanes - 1 + numDirections - 1) * f * xu - 0.5f * (float)maxNumSigns * f * yu; // "bottom left" /*if (!viewOnly) * Log._Debug($"xu: {xu.ToString()} yu: {yu.ToString()} center: {center.ToString()} zero: {zero.ToString()} numLanes: {numLanes} numDirections: {numDirections}");*/ uint x = 0; var guiColor = GUI.color; // TODO refactor vehicle mask List <object[]> sortedLanes = TrafficManagerTool.GetSortedVehicleLanes(segmentId, segmentInfo, null, VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Train); bool hovered = false; HashSet <NetInfo.Direction> directions = new HashSet <NetInfo.Direction>(); int sortedLaneIndex = -1; foreach (object[] laneData in sortedLanes) { ++sortedLaneIndex; uint laneId = (uint)laneData[0]; uint laneIndex = (uint)laneData[2]; NetInfo.Lane laneInfo = segmentInfo.m_lanes[laneIndex]; if (!directions.Contains(laneInfo.m_direction)) { if (directions.Count > 0) { ++x; // space between different directions } directions.Add(laneInfo.m_direction); } ExtVehicleType[] possibleVehicleTypes = null; if (VehicleRestrictionsManager.Instance.IsRoadLane(laneInfo)) { possibleVehicleTypes = roadVehicleTypes; } else if (VehicleRestrictionsManager.Instance.IsRailLane(laneInfo)) { possibleVehicleTypes = railVehicleTypes; } else { ++x; continue; } ExtVehicleType allowedTypes = VehicleRestrictionsManager.Instance.GetAllowedVehicleTypes(segmentId, segmentInfo, laneIndex, laneInfo); uint y = 0; #if DEBUGx Vector3 labelCenter = zero + f * (float)x * xu + f * (float)y * yu; // in game coordinates var labelScreenPos = Camera.main.WorldToScreenPoint(labelCenter); labelScreenPos.y = Screen.height - labelScreenPos.y; diff = labelCenter - camPos; var labelZoom = 1.0f / diff.magnitude * 100f; _counterStyle.fontSize = (int)(11f * labelZoom); _counterStyle.normal.textColor = new Color(1f, 1f, 0f); string labelStr = $"Idx {laneIndex}"; Vector2 dim = _counterStyle.CalcSize(new GUIContent(labelStr)); Rect labelRect = new Rect(labelScreenPos.x - dim.x / 2f, labelScreenPos.y, dim.x, dim.y); GUI.Label(labelRect, labelStr, _counterStyle); ++y; #endif foreach (ExtVehicleType vehicleType in possibleVehicleTypes) { bool allowed = VehicleRestrictionsManager.Instance.IsAllowed(allowedTypes, vehicleType); if (allowed && viewOnly) { continue; // do not draw allowed vehicles in view-only mode } bool hoveredHandle; DrawRestrictionsSign(viewOnly, camPos, out diff, xu, yu, f, zero, x, y, ref guiColor, TrafficLightToolTextureResources.VehicleRestrictionTextures[vehicleType][allowed], out hoveredHandle); if (hoveredHandle) { hovered = true; } if (hoveredHandle && MainTool.CheckClicked()) { // toggle vehicle restrictions //Log._Debug($"Setting vehicle restrictions of segment {segmentId}, lane idx {laneIndex}, {vehicleType.ToString()} to {!allowed}"); VehicleRestrictionsManager.Instance.ToggleAllowedType(segmentId, segmentInfo, laneIndex, laneId, laneInfo, vehicleType, !allowed); stateUpdated = true; // TODO use SegmentTraverser if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) { ApplyRestrictionsToAllSegments(sortedLaneIndex); } } ++y; } ++x; } guiColor.a = 1f; GUI.color = guiColor; return(hovered); }
private bool drawSignHandles(ushort nodeId, bool viewOnly, bool handleClick, ref Vector3 camPos, out bool stateUpdated) { bool hovered = false; stateUpdated = false; if (viewOnly && !Options.junctionRestrictionsOverlay && MainTool.GetToolMode() != ToolMode.JunctionRestrictions) { return(false); } NetManager netManager = Singleton <NetManager> .instance; var guiColor = GUI.color; Vector3 nodePos = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].m_position; for (int i = 0; i < 8; ++i) { ushort segmentId = netManager.m_nodes.m_buffer[nodeId].GetSegment(i); if (segmentId == 0) { continue; } SegmentGeometry geometry = SegmentGeometry.Get(segmentId); if (geometry == null) { Log.Error($"JunctionRestrictionsTool.drawSignHandles: No geometry information available for segment {segmentId}"); continue; } bool startNode = geometry.StartNodeId() == nodeId; bool incoming = geometry.IsIncoming(startNode); int numSignsPerRow = incoming ? 2 : 1; NetInfo segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info; ItemClass connectionClass = segmentInfo.GetConnectionClass(); if (connectionClass.m_service != ItemClass.Service.Road) { continue; // only for road junctions } // draw all junction restriction signs Vector3 segmentCenterPos = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_bounds.center; Vector3 yu = (segmentCenterPos - nodePos).normalized; Vector3 xu = Vector3.Cross(yu, new Vector3(0, 1f, 0)).normalized; float f = viewOnly ? 6f : 7f; // reserved sign size in game coordinates Vector3 centerStart = nodePos + yu * (viewOnly ? 5f : 14f); Vector3 zero = centerStart - 0.5f * (float)(numSignsPerRow - 1) * f * xu; // "top left" if (viewOnly) { if (Constants.ServiceFactory.SimulationService.LeftHandDrive) { zero -= xu * 8f; } else { zero += xu * 8f; } } bool signHovered; int x = 0; int y = 0; // draw "lane-changing when going straight allowed" sign at (0; 0) bool allowed = JunctionRestrictionsManager.Instance.IsLaneChangingAllowedWhenGoingStraight(segmentId, startNode); if (incoming && (!viewOnly || allowed != Options.allowLaneChangesWhileGoingStraight)) { DrawSign(viewOnly, ref camPos, ref xu, ref yu, f, ref zero, x, y, ref guiColor, allowed ? TextureResources.LaneChangeAllowedTexture2D : TextureResources.LaneChangeForbiddenTexture2D, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { JunctionRestrictionsManager.Instance.ToggleLaneChangingAllowedWhenGoingStraight(segmentId, startNode); stateUpdated = true; } } if (viewOnly) { ++y; } else { ++x; } } // draw "u-turns allowed" sign at (1; 0) allowed = JunctionRestrictionsManager.Instance.IsUturnAllowed(segmentId, startNode); if (incoming && (!viewOnly || allowed != Options.allowUTurns)) { DrawSign(viewOnly, ref camPos, ref xu, ref yu, f, ref zero, x, y, ref guiColor, allowed ? TextureResources.UturnAllowedTexture2D : TextureResources.UturnForbiddenTexture2D, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { if (!JunctionRestrictionsManager.Instance.ToggleUturnAllowed(segmentId, startNode)) { // TODO MainTool.ShowTooltip(Translation.GetString("..."), Singleton<NetManager>.instance.m_nodes.m_buffer[nodeId].m_position); } else { stateUpdated = true; } } } ++y; x = 0; } // draw "entering blocked junctions allowed" sign at (0; 1) allowed = JunctionRestrictionsManager.Instance.IsEnteringBlockedJunctionAllowed(segmentId, startNode); if (incoming && (!viewOnly || allowed != Options.allowEnterBlockedJunctions)) { DrawSign(viewOnly, ref camPos, ref xu, ref yu, f, ref zero, x, y, ref guiColor, allowed ? TextureResources.EnterBlockedJunctionAllowedTexture2D : TextureResources.EnterBlockedJunctionForbiddenTexture2D, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { JunctionRestrictionsManager.Instance.ToggleEnteringBlockedJunctionAllowed(segmentId, startNode); stateUpdated = true; } } if (viewOnly) { ++y; } else { ++x; } } // draw "pedestrian crossing allowed" sign at (1; 1) allowed = JunctionRestrictionsManager.Instance.IsPedestrianCrossingAllowed(segmentId, startNode); if (!viewOnly || !allowed) { DrawSign(viewOnly, ref camPos, ref xu, ref yu, f, ref zero, x, y, ref guiColor, allowed ? TextureResources.PedestrianCrossingAllowedTexture2D : TextureResources.PedestrianCrossingForbiddenTexture2D, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { JunctionRestrictionsManager.Instance.TogglePedestrianCrossingAllowed(segmentId, startNode); stateUpdated = true; } } } } guiColor.a = 1f; GUI.color = guiColor; return(hovered); }
public static void CSURUpdateEndSegments(ref NetSegment __instance, ushort segmentID) { NetManager instance = Singleton <NetManager> .instance; NetInfo info = __instance.Info; if (info == null) { return; } ItemClass connectionClass = info.GetConnectionClass(); float num = -4f; float num2 = -4f; ushort endLeftSegment = 0; ushort endRightSegment = 0; for (int i = 0; i < 8; i++) { ushort segment = instance.m_nodes.m_buffer[(int)__instance.m_endNode].GetSegment(i); if (segment != 0 && segment != segmentID) { NetInfo info2 = instance.m_segments.m_buffer[(int)segment].Info; if (info2 != null) { ItemClass connectionClass2 = info2.GetConnectionClass(); if (connectionClass.m_service == connectionClass2.m_service) { //Non-stock code begin Vector3 vector = instance.m_lanes.m_buffer[instance.m_segments.m_buffer[(int)segment].m_lanes].m_bezier.Position(0.5f) - instance.m_lanes.m_buffer[instance.m_segments.m_buffer[(int)segmentID].m_lanes].m_bezier.Position(0.5f); vector = VectorUtils.NormalizeXZ(vector); //Non-stock code end float num3 = __instance.m_endDirection.x * vector.x + __instance.m_endDirection.z * vector.z; if (vector.z * __instance.m_endDirection.x - vector.x * __instance.m_endDirection.z < 0f) { if (num3 > num) { num = num3; endLeftSegment = segment; } num3 = -2f - num3; if (num3 > num2) { num2 = num3; endRightSegment = segment; } } else { if (num3 > num2) { num2 = num3; endRightSegment = segment; } num3 = -2f - num3; if (num3 > num) { num = num3; endLeftSegment = segment; } } } } } } __instance.m_endLeftSegment = endLeftSegment; __instance.m_endRightSegment = endRightSegment; }
private bool drawSignHandles(bool debug, ushort nodeId, ref NetNode node, bool viewOnly, bool handleClick, ref Vector3 camPos, out bool stateUpdated) { bool hovered = false; stateUpdated = false; if (viewOnly && !(Options.junctionRestrictionsOverlay || PrioritySignsTool.showMassEditOverlay) && (MainTool.GetToolMode() != ToolMode.JunctionRestrictions)) { return(false); } // NetManager netManager = Singleton<NetManager>.instance; Color guiColor = GUI.color; Vector3 nodePos = Singleton <NetManager> .instance.m_nodes.m_buffer[nodeId].m_position; IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager; for (int i = 0; i < 8; ++i) { ushort segmentId = node.GetSegment(i); if (segmentId == 0) { continue; } bool startNode = (bool)Constants.ServiceFactory.NetService.IsStartNode(segmentId, nodeId); bool incoming = segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segmentId, startNode)].incoming; int numSignsPerRow = incoming ? 2 : 1; NetInfo segmentInfo = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].Info; ItemClass connectionClass = segmentInfo.GetConnectionClass(); if (connectionClass.m_service != ItemClass.Service.Road) { continue; // only for road junctions } // draw all junction restriction signs Vector3 segmentCenterPos = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId] .m_bounds.center; Vector3 yu = (segmentCenterPos - nodePos).normalized; Vector3 xu = Vector3.Cross(yu, new Vector3(0, 1f, 0)).normalized; float f = viewOnly ? 6f : 7f; // reserved sign size in game coordinates Vector3 centerStart = nodePos + (yu * (viewOnly ? 5f : 14f)); Vector3 zero = centerStart - (0.5f * (numSignsPerRow - 1) * f * xu); // "top left" if (viewOnly) { if (Constants.ServiceFactory.SimulationService.TrafficDrivesOnLeft) { zero -= xu * 8f; } else { zero += xu * 8f; } } bool signHovered; int x = 0; int y = 0; bool hasSignInPrevRow = false; // draw "lane-changing when going straight allowed" sign at (0; 0) bool allowed = JunctionRestrictionsManager.Instance.IsLaneChangingAllowedWhenGoingStraight( segmentId, startNode); bool configurable = Constants.ManagerFactory.JunctionRestrictionsManager .IsLaneChangingAllowedWhenGoingStraightConfigurable( segmentId, startNode, ref node); if (debug || (configurable && (!viewOnly || (allowed != Constants.ManagerFactory .JunctionRestrictionsManager .GetDefaultLaneChangingAllowedWhenGoingStraight( segmentId, startNode, ref node))))) { DrawSign( viewOnly, !configurable, ref camPos, ref xu, ref yu, f, ref zero, x, y, guiColor, allowed ? JunctionRestrictions.LaneChangeAllowed : JunctionRestrictions.LaneChangeForbidden, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { JunctionRestrictionsManager.Instance.ToggleLaneChangingAllowedWhenGoingStraight( segmentId, startNode); stateUpdated = true; } } ++x; hasSignInPrevRow = true; } // draw "u-turns allowed" sign at (1; 0) allowed = JunctionRestrictionsManager.Instance.IsUturnAllowed(segmentId, startNode); configurable = Constants.ManagerFactory.JunctionRestrictionsManager.IsUturnAllowedConfigurable( segmentId, startNode, ref node); if (debug || (configurable && (!viewOnly || (allowed != Constants.ManagerFactory .JunctionRestrictionsManager .GetDefaultUturnAllowed( segmentId, startNode, ref node))))) { DrawSign( viewOnly, !configurable, ref camPos, ref xu, ref yu, f, ref zero, x, y, guiColor, allowed ? JunctionRestrictions.UturnAllowed : JunctionRestrictions.UturnForbidden, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { if (!JunctionRestrictionsManager.Instance.ToggleUturnAllowed( segmentId, startNode)) { // TODO MainTool.ShowTooltip(Translation.GetString("..."), Singleton<NetManager>.instance.m_nodes.m_buffer[nodeId].m_position); } else { stateUpdated = true; } } } x++; hasSignInPrevRow = true; } x = 0; if (hasSignInPrevRow) { ++y; hasSignInPrevRow = false; } // draw "entering blocked junctions allowed" sign at (0; 1) allowed = JunctionRestrictionsManager.Instance.IsEnteringBlockedJunctionAllowed( segmentId, startNode); configurable = Constants.ManagerFactory.JunctionRestrictionsManager .IsEnteringBlockedJunctionAllowedConfigurable( segmentId, startNode, ref node); if (debug || (configurable && (!viewOnly || (allowed != Constants.ManagerFactory .JunctionRestrictionsManager .GetDefaultEnteringBlockedJunctionAllowed( segmentId, startNode, ref node))))) { DrawSign( viewOnly, !configurable, ref camPos, ref xu, ref yu, f, ref zero, x, y, guiColor, allowed ? JunctionRestrictions.EnterBlockedJunctionAllowed : JunctionRestrictions.EnterBlockedJunctionForbidden, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { JunctionRestrictionsManager .Instance .ToggleEnteringBlockedJunctionAllowed(segmentId, startNode); stateUpdated = true; } } ++x; hasSignInPrevRow = true; } // draw "pedestrian crossing allowed" sign at (1; 1) allowed = JunctionRestrictionsManager.Instance.IsPedestrianCrossingAllowed( segmentId, startNode); configurable = Constants.ManagerFactory.JunctionRestrictionsManager .IsPedestrianCrossingAllowedConfigurable( segmentId, startNode, ref node); if (debug || (configurable && (!viewOnly || !allowed))) { DrawSign( viewOnly, !configurable, ref camPos, ref xu, ref yu, f, ref zero, x, y, guiColor, allowed ? JunctionRestrictions.PedestrianCrossingAllowed : JunctionRestrictions.PedestrianCrossingForbidden, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { JunctionRestrictionsManager.Instance.TogglePedestrianCrossingAllowed(segmentId, startNode); stateUpdated = true; } } x++; hasSignInPrevRow = true; } x = 0; if (hasSignInPrevRow) { ++y; hasSignInPrevRow = false; } if (!Options.turnOnRedEnabled) { continue; } //-------------------------------- // TURN ON RED ENABLED //-------------------------------- IJunctionRestrictionsManager junctionRestrictionsManager = Constants.ManagerFactory.JunctionRestrictionsManager; bool lht = Constants.ServiceFactory.SimulationService.TrafficDrivesOnLeft; // draw "turn-left-on-red allowed" sign at (2; 0) allowed = junctionRestrictionsManager.IsTurnOnRedAllowed(lht, segmentId, startNode); configurable = junctionRestrictionsManager.IsTurnOnRedAllowedConfigurable( lht, segmentId, startNode, ref node); if (debug || (configurable && (!viewOnly || (allowed != junctionRestrictionsManager .GetDefaultTurnOnRedAllowed( lht, segmentId, startNode, ref node))))) { DrawSign( viewOnly, !configurable, ref camPos, ref xu, ref yu, f, ref zero, x, y, guiColor, allowed ? JunctionRestrictions.LeftOnRedAllowed : JunctionRestrictions.LeftOnRedForbidden, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { junctionRestrictionsManager.ToggleTurnOnRedAllowed( lht, segmentId, startNode); stateUpdated = true; } } hasSignInPrevRow = true; } x++; // draw "turn-right-on-red allowed" sign at (2; 1) allowed = junctionRestrictionsManager.IsTurnOnRedAllowed( !lht, segmentId, startNode); configurable = junctionRestrictionsManager.IsTurnOnRedAllowedConfigurable( !lht, segmentId, startNode, ref node); if (debug || (configurable && (!viewOnly || (allowed != junctionRestrictionsManager .GetDefaultTurnOnRedAllowed( !lht, segmentId, startNode, ref node))))) { DrawSign( viewOnly, !configurable, ref camPos, ref xu, ref yu, f, ref zero, x, y, guiColor, allowed ? JunctionRestrictions.RightOnRedAllowed : JunctionRestrictions.RightOnRedForbidden, out signHovered); if (signHovered && handleClick) { hovered = true; if (MainTool.CheckClicked()) { junctionRestrictionsManager.ToggleTurnOnRedAllowed( !lht, segmentId, startNode); stateUpdated = true; } } hasSignInPrevRow = true; } } guiColor.a = 1f; GUI.color = guiColor; return(hovered); }
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; }
// Token: 0x060034D0 RID: 13520 RVA: 0x0023E078 File Offset: 0x0023C478 public static void CalculateNode(ref NetNode This, ushort nodeID) { if (This.m_flags == NetNode.Flags.None) { return; } NetManager netMan = Singleton <NetManager> .instance; Vector3 DirFirst = Vector3.zero; int iSegment = 0; int ConnectCount = 0; bool hasSegments = false; bool canBeMiddle = false; bool bCompatibleButNodeMiddle = false; bool isAsymForward = false; bool isAsymBackward = false; bool needsJunctionFlag = false; bool hasCurvedSegment = false; bool hasStraightSegment = false; bool bCompatibleAndStart2End = false; bool allConnectedSegmentsAreFlat = true; bool CanModify = true; bool bHasDetailMapping = Singleton <TerrainManager> .instance.HasDetailMapping(This.m_position); NetInfo prevInfo = null; int prev_backwardVehicleLaneCount = 0; int prev_m_forwardVehicleLaneCount = 0; NetInfo infoNode = null; float num5 = -1E+07f; for (int i = 0; i < 8; i++) { ushort segmentID = This.GetSegment(i); if (segmentID != 0) { NetInfo infoSegment = netMan.m_segments.m_buffer[segmentID].Info; float nodeInfoPriority = infoSegment.m_netAI.GetNodeInfoPriority(segmentID, ref netMan.m_segments.m_buffer[segmentID]); if (nodeInfoPriority > num5) { infoSegment = infoSegment; num5 = nodeInfoPriority; } } } if (infoNode == null) { infoNode = This.Info; } if (infoNode != This.Info) { This.Info = infoNode; Singleton <NetManager> .instance.UpdateNodeColors(nodeID); if (!infoNode.m_canDisable) { This.m_flags &= ~NetNode.Flags.Disabled; } } bool bStartNodeFirst = false; for (int j = 0; j < 8; j++) { ushort segmentID = This.GetSegment(j); if (segmentID != 0) { iSegment++; ushort startNodeID = netMan.m_segments.m_buffer[segmentID].m_startNode; ushort endNodeID = netMan.m_segments.m_buffer[segmentID].m_endNode; Vector3 startDirection = netMan.m_segments.m_buffer[segmentID].m_startDirection; Vector3 endDirection = netMan.m_segments.m_buffer[segmentID].m_endDirection; bool bStartNode = nodeID == startNodeID; Vector3 currentDir = (!bStartNode) ? endDirection : startDirection; NetInfo infoSegment = netMan.m_segments.m_buffer[segmentID].Info; ItemClass connectionClass = infoSegment.GetConnectionClass(); if (!infoSegment.m_netAI.CanModify()) { CanModify = false; } int backwardVehicleLaneCount; int forwardVehicleLaneCount; if (bStartNode == ((netMan.m_segments.m_buffer[segmentID].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)) { backwardVehicleLaneCount = infoSegment.m_backwardVehicleLaneCount; forwardVehicleLaneCount = infoSegment.m_forwardVehicleLaneCount; } else { backwardVehicleLaneCount = infoSegment.m_forwardVehicleLaneCount; forwardVehicleLaneCount = infoSegment.m_backwardVehicleLaneCount; } for (int k = j + 1; k < 8; k++) { ushort segmentID2 = This.GetSegment(k); if (segmentID2 != 0) { NetInfo infoSegment2 = netMan.m_segments.m_buffer[segmentID2].Info; ItemClass connectionClass2 = infoSegment2.GetConnectionClass(); if (connectionClass2.m_service == connectionClass.m_service || (infoSegment2.m_nodeConnectGroups & infoSegment.m_connectGroup) != NetInfo.ConnectGroup.None || (infoSegment.m_nodeConnectGroups & infoSegment2.m_connectGroup) != NetInfo.ConnectGroup.None) { bool bStartNode2 = nodeID == netMan.m_segments.m_buffer[segmentID2].m_startNode; Vector3 dir2 = (!bStartNode2) ? netMan.m_segments.m_buffer[segmentID2].m_endDirection : netMan.m_segments.m_buffer[segmentID2].m_startDirection; float dot2 = currentDir.x * dir2.x + currentDir.z * dir2.z; float turnThreshold = 0.01f - Mathf.Min(infoSegment.m_maxTurnAngleCos, infoSegment2.m_maxTurnAngleCos); if (dot2 < turnThreshold) { if ((infoSegment.m_requireDirectRenderers && (infoSegment.m_nodeConnectGroups == NetInfo.ConnectGroup.None || (infoSegment.m_nodeConnectGroups & infoSegment2.m_connectGroup) != NetInfo.ConnectGroup.None)) || (infoSegment2.m_requireDirectRenderers && (infoSegment2.m_nodeConnectGroups == NetInfo.ConnectGroup.None || (infoSegment2.m_nodeConnectGroups & infoSegment.m_connectGroup) != NetInfo.ConnectGroup.None))) { ConnectCount++; } } else { needsJunctionFlag = true; } } else { needsJunctionFlag = true; } } } if (netMan.m_nodes.m_buffer[startNodeID].m_elevation != netMan.m_nodes.m_buffer[endNodeID].m_elevation) { allConnectedSegmentsAreFlat = false; } Vector3 startPos = netMan.m_nodes.m_buffer[startNodeID].m_position; Vector3 endPos = netMan.m_nodes.m_buffer[endNodeID].m_position; if (bStartNode) { bHasDetailMapping = (bHasDetailMapping && Singleton <TerrainManager> .instance.HasDetailMapping(endPos)); } else { bHasDetailMapping = (bHasDetailMapping && Singleton <TerrainManager> .instance.HasDetailMapping(startPos)); } if (NetSegment.IsStraight(startPos, startDirection, endPos, endDirection)) { hasStraightSegment = true; } else { hasCurvedSegment = true; } if (iSegment == 1) { bStartNodeFirst = bStartNode; DirFirst = currentDir; hasSegments = true; } else if (iSegment == 2 && infoSegment.IsCombatible(prevInfo) && infoSegment.IsCombatible(infoNode) && (backwardVehicleLaneCount != 0) == (prev_m_forwardVehicleLaneCount != 0) && (forwardVehicleLaneCount != 0) == (prev_backwardVehicleLaneCount != 0)) { float dot = DirFirst.x * currentDir.x + DirFirst.z * currentDir.z; if (backwardVehicleLaneCount != prev_m_forwardVehicleLaneCount || forwardVehicleLaneCount != prev_backwardVehicleLaneCount) { if (backwardVehicleLaneCount > forwardVehicleLaneCount) { isAsymForward = true; } else { isAsymBackward = true; } bCompatibleButNodeMiddle = true; } else if (dot < -0.999f) // straight. { canBeMiddle = true; } else { bCompatibleButNodeMiddle = true; } bCompatibleAndStart2End = (bStartNode != bStartNodeFirst); } else { needsJunctionFlag = true; } prevInfo = infoSegment; prev_backwardVehicleLaneCount = backwardVehicleLaneCount; prev_m_forwardVehicleLaneCount = forwardVehicleLaneCount; } } if (!infoNode.m_enableMiddleNodes && canBeMiddle) { bCompatibleButNodeMiddle = true; } if (!infoNode.m_enableBendingNodes && bCompatibleButNodeMiddle) { needsJunctionFlag = true; } if (infoNode.m_requireContinuous && (This.m_flags & NetNode.Flags.Untouchable) != NetNode.Flags.None) { needsJunctionFlag = true; } if (infoNode.m_requireContinuous && !bCompatibleAndStart2End && (canBeMiddle || bCompatibleButNodeMiddle)) { needsJunctionFlag = true; } NetNode.Flags flags = This.m_flags & ~(NetNode.Flags.End | NetNode.Flags.Middle | NetNode.Flags.Bend | NetNode.Flags.Junction | NetNode.Flags.Moveable | NetNode.Flags.AsymForward | NetNode.Flags.AsymBackward); if ((flags & NetNode.Flags.Outside) != NetNode.Flags.None) { This.m_flags = flags; } else if (needsJunctionFlag) { This.m_flags = (flags | NetNode.Flags.Junction); } else if (bCompatibleButNodeMiddle) { if (isAsymForward) { flags |= NetNode.Flags.AsymForward; } if (isAsymBackward) { flags |= NetNode.Flags.AsymBackward; } This.m_flags = (flags | NetNode.Flags.Bend); } else if (canBeMiddle) { if ((!hasCurvedSegment || !hasStraightSegment) && (This.m_flags & (NetNode.Flags.Untouchable | NetNode.Flags.Double)) == NetNode.Flags.None && allConnectedSegmentsAreFlat && CanModify) { flags |= NetNode.Flags.Moveable; } This.m_flags = (flags | NetNode.Flags.Middle); } else if (hasSegments) { if ((This.m_flags & NetNode.Flags.Untouchable) == NetNode.Flags.None && allConnectedSegmentsAreFlat && CanModify && infoNode.m_enableMiddleNodes) { flags |= NetNode.Flags.Moveable; } This.m_flags = (flags | NetNode.Flags.End); } else { This.m_flags = flags; } This.m_heightOffset = (byte)((!bHasDetailMapping && infoNode.m_requireSurfaceMaps) ? 64 : 0); This.m_connectCount = (byte)ConnectCount; BuildingInfo newBuilding; float heightOffset; infoNode.m_netAI.GetNodeBuilding(nodeID, ref This, out newBuilding, out heightOffset); This.UpdateBuilding(nodeID, newBuilding, heightOffset); }
// NetNode // Token: 0x060034C6 RID: 13510 RVA: 0x0023D1EC File Offset: 0x0023B5EC /// <param name="centerPos">position between left corner and right corner of segmentID (or something like that).</param> private static void RefreshJunctionData(ref NetNode This, ushort nodeID, int segmentIndex, ushort SegmentID, Vector3 centerPos, ref uint instanceIndex, ref RenderManager.Instance data) { Vector3 cornerPos_right = Vector3.zero, cornerDir_right = Vector3.zero, cornerPos_left = Vector3.zero, cornerDir_left = Vector3.zero, cornerPosA_right = Vector3.zero, cornerDirA_right = Vector3.zero, cornerPosA_left = Vector3.zero, cornerDirA_left = Vector3.zero, cornerPosB_right = Vector3.zero, cornerDirB_right = Vector3.zero, cornerPosB_left = Vector3.zero, cornerDirB_left = Vector3.zero; NetManager instance = Singleton <NetManager> .instance; data.m_position = This.m_position; data.m_rotation = Quaternion.identity; data.m_initialized = true; NetSegment segment = SegmentID.ToSegment(); NetInfo info = segment.Info; float vscale = info.m_netAI.GetVScale(); ItemClass connectionClass = info.GetConnectionClass(); bool bStartNode = nodeID == segment.m_startNode; Vector3 dir = !bStartNode ? segment.m_endDirection : segment.m_startDirection; float dot_A = -4f; float dot_B = -4f; ushort segmentID_A = 0; ushort segmentID_B = 0; for (int i = 0; i < 8; i++) { ushort segmentID2 = This.GetSegment(i); if (segmentID2 != 0 && segmentID2 != SegmentID) { NetInfo info2 = instance.m_segments.m_buffer[(int)segmentID2].Info; ItemClass connectionClass2 = info2.GetConnectionClass(); if (connectionClass.m_service == connectionClass2.m_service) { NetSegment segment2 = segmentID2.ToSegment(); bool bStartNode2 = nodeID != segment2.m_startNode; Vector3 dir2 = !bStartNode2 ? segment2.m_endDirection : segment2.m_startDirection; float dot = dir.x * dir2.x + dir.z * dir2.z; float determinent = dir2.z * dir.x - dir2.x * dir.z; bool bRight = determinent > 0; bool bWide = dot < 0; // 180 -> det=0 dot=-1 if (!bRight) { if (dot > dot_A) // most accute { dot_A = dot; segmentID_A = segmentID2; } dot = -2f - dot; if (dot > dot_B) // widest { dot_B = dot; segmentID_B = segmentID2; } } else { if (dot > dot_B) // most accute { dot_B = dot; segmentID_B = segmentID2; } dot = -2f - dot; if (dot > dot_A) // widest { dot_A = dot; segmentID_A = segmentID2; } } } } } segment.CalculateCorner(SegmentID, true, bStartNode, false, out cornerPos_right, out cornerDir_right, out _); segment.CalculateCorner(SegmentID, true, bStartNode, true, out cornerPos_left, out cornerDir_left, out _); if (segmentID_A != 0 && segmentID_B != 0) { float pavementRatio_avgA = info.m_pavementWidth / info.m_halfWidth * 0.5f; float averageWidthA = 1f; if (segmentID_A != 0) { NetSegment segment_A = instance.m_segments.m_buffer[(int)segmentID_A]; NetInfo infoA = segment_A.Info; bStartNode = (segment_A.m_startNode == nodeID); segment_A.CalculateCorner(segmentID_A, true, bStartNode, true, out cornerPosA_right, out cornerDirA_right, out _); segment_A.CalculateCorner(segmentID_A, true, bStartNode, false, out cornerPosA_left, out cornerDirA_left, out _); float pavementRatioA = infoA.m_pavementWidth / infoA.m_halfWidth * 0.5f; pavementRatio_avgA = (pavementRatio_avgA + pavementRatioA) * 0.5f; averageWidthA = 2f * info.m_halfWidth / (info.m_halfWidth + infoA.m_halfWidth); } float pavementRatio_avgB = info.m_pavementWidth / info.m_halfWidth * 0.5f; float averageWithB = 1f; if (segmentID_B != 0) { NetSegment segment_B = instance.m_segments.m_buffer[(int)segmentID_B]; NetInfo infoB = segment_B.Info; bStartNode = (segment_B.m_startNode == nodeID); segment_B.CalculateCorner(segmentID_B, true, bStartNode, true, out cornerPosB_right, out cornerDirB_right, out _); segment_B.CalculateCorner(segmentID_B, true, bStartNode, false, out cornerPosB_left, out cornerDirB_left, out _); float pavementRatioB = infoB.m_pavementWidth / infoB.m_halfWidth * 0.5f; pavementRatio_avgB = (pavementRatio_avgB + pavementRatioB) * 0.5f; averageWithB = 2f * info.m_halfWidth / (info.m_halfWidth + infoB.m_halfWidth); } Bezier3 bezierA_right = new Bezier3 { a = cornerPos_right, d = cornerPosA_right, }; NetSegment.CalculateMiddlePoints(bezierA_right.a, -cornerDir_right, bezierA_right.d, -cornerDirA_right, true, true, out bezierA_right.b, out bezierA_right.c); NetSegment.CalculateMiddlePoints(cornerPos_left, -cornerDir_left, cornerPosA_left, -cornerDirA_left, true, true, out var cpoint2_Aleft, out var cpoint3_Aleft); NetSegment.CalculateMiddlePoints(cornerPos_right, -cornerDir_right, cornerPosB_right, -cornerDirB_right, true, true, out var cpoint2_Bright, out var cpoint3_Bright); NetSegment.CalculateMiddlePoints(cornerPos_left, -cornerDir_left, cornerPosB_left, -cornerDirB_left, true, true, out var cpoint2_Bleft, out var cpoint3_Bleft); data.m_dataMatrix0 = NetSegment.CalculateControlMatrix(bezierA_right.a, bezierA_right.b, bezierA_right.c, bezierA_right.d, bezierA_right.a, bezierA_right.b, bezierA_right.c, bezierA_right.d, This.m_position, vscale); data.m_extraData.m_dataMatrix2 = NetSegment.CalculateControlMatrix(cornerPos_left, cpoint2_Aleft, cpoint3_Aleft, cornerPosA_left, cornerPos_left, cpoint2_Aleft, cpoint3_Aleft, cornerPosA_left, This.m_position, vscale); data.m_extraData.m_dataMatrix3 = NetSegment.CalculateControlMatrix(cornerPos_right, cpoint2_Bright, cpoint3_Bright, cornerPosB_right, cornerPos_right, cpoint2_Bright, cpoint3_Bright, cornerPosB_right, This.m_position, vscale); data.m_dataMatrix1 = NetSegment.CalculateControlMatrix(cornerPos_left, cpoint2_Bleft, cpoint3_Bleft, cornerPosB_left, cornerPos_left, cpoint2_Bleft, cpoint3_Bleft, cornerPosB_left, This.m_position, vscale); // Vector4(1/width | 1/length | 0.5 - pavement/width | pavement/width ) data.m_dataVector0 = new Vector4(0.5f / info.m_halfWidth, 1f / info.m_segmentLength, 0.5f - info.m_pavementWidth / info.m_halfWidth * 0.5f, info.m_pavementWidth / info.m_halfWidth * 0.5f); data.m_dataVector1 = centerPos - data.m_position; data.m_dataVector1.w = (data.m_dataMatrix0.m31 + data.m_dataMatrix0.m32 + data.m_extraData.m_dataMatrix2.m31 + data.m_extraData.m_dataMatrix2.m32 + data.m_extraData.m_dataMatrix3.m31 + data.m_extraData.m_dataMatrix3.m32 + data.m_dataMatrix1.m31 + data.m_dataMatrix1.m32) * 0.125f; data.m_dataVector2 = new Vector4(pavementRatio_avgA, averageWidthA, pavementRatio_avgB, averageWithB); } else { centerPos.x = (cornerPos_right.x + cornerPos_left.x) * 0.5f; centerPos.z = (cornerPos_right.z + cornerPos_left.z) * 0.5f; var cornerPos_left_prev = cornerPos_left; var cornerPos_right_prev = cornerPos_right; cornerDirB_right = cornerDir_left; cornerDirB_left = cornerDir_right; float d = info.m_netAI.GetEndRadius() * 1.33333337f; Vector3 vector13 = cornerPos_right - cornerDir_right * d; Vector3 vector14 = cornerPos_left_prev - cornerDirB_right * d; Vector3 vector15 = cornerPos_left - cornerDir_left * d; Vector3 vector16 = cornerPos_right_prev - cornerDirB_left * d; Vector3 vector17 = cornerPos_right + cornerDir_right * d; Vector3 vector18 = cornerPos_left_prev + cornerDirB_right * d; Vector3 vector19 = cornerPos_left + cornerDir_left * d; Vector3 vector20 = cornerPos_right_prev + cornerDirB_left * d; data.m_dataMatrix0 = NetSegment.CalculateControlMatrix(cornerPos_right, vector13, vector14, cornerPos_left_prev, cornerPos_right, vector13, vector14, cornerPos_left_prev, This.m_position, vscale); data.m_extraData.m_dataMatrix2 = NetSegment.CalculateControlMatrix(cornerPos_left, vector19, vector20, cornerPos_right_prev, cornerPos_left, vector19, vector20, cornerPos_right_prev, This.m_position, vscale); data.m_extraData.m_dataMatrix3 = NetSegment.CalculateControlMatrix(cornerPos_right, vector17, vector18, cornerPos_left_prev, cornerPos_right, vector17, vector18, cornerPos_left_prev, This.m_position, vscale); data.m_dataMatrix1 = NetSegment.CalculateControlMatrix(cornerPos_left, vector15, vector16, cornerPos_right_prev, cornerPos_left, vector15, vector16, cornerPos_right_prev, This.m_position, vscale); data.m_dataMatrix0.SetRow(3, data.m_dataMatrix0.GetRow(3) + new Vector4(0.2f, 0.2f, 0.2f, 0.2f)); data.m_extraData.m_dataMatrix2.SetRow(3, data.m_extraData.m_dataMatrix2.GetRow(3) + new Vector4(0.2f, 0.2f, 0.2f, 0.2f)); data.m_extraData.m_dataMatrix3.SetRow(3, data.m_extraData.m_dataMatrix3.GetRow(3) + new Vector4(0.2f, 0.2f, 0.2f, 0.2f)); data.m_dataMatrix1.SetRow(3, data.m_dataMatrix1.GetRow(3) + new Vector4(0.2f, 0.2f, 0.2f, 0.2f)); data.m_dataVector0 = new Vector4(0.5f / info.m_halfWidth, 1f / info.m_segmentLength, 0.5f - info.m_pavementWidth / info.m_halfWidth * 0.5f, info.m_pavementWidth / info.m_halfWidth * 0.5f); data.m_dataVector1 = centerPos - data.m_position; data.m_dataVector1.w = (data.m_dataMatrix0.m31 + data.m_dataMatrix0.m32 + data.m_extraData.m_dataMatrix2.m31 + data.m_extraData.m_dataMatrix2.m32 + data.m_extraData.m_dataMatrix3.m31 + data.m_extraData.m_dataMatrix3.m32 + data.m_dataMatrix1.m31 + data.m_dataMatrix1.m32) * 0.125f; data.m_dataVector2 = new Vector4(info.m_pavementWidth / info.m_halfWidth * 0.5f, 1f, info.m_pavementWidth / info.m_halfWidth * 0.5f, 1f); } Vector4 colorLocation; Vector4 vector21; if (NetNode.BlendJunction(nodeID)) { colorLocation = RenderManager.GetColorLocation(86016u + (uint)nodeID); vector21 = colorLocation; } else { colorLocation = RenderManager.GetColorLocation((uint)(49152 + SegmentID)); vector21 = RenderManager.GetColorLocation(86016u + (uint)nodeID); } data.m_extraData.m_dataVector4 = new Vector4(colorLocation.x, colorLocation.y, vector21.x, vector21.y); data.m_dataInt0 = segmentIndex; data.m_dataColor0 = info.m_color; data.m_dataColor0.a = 0f; data.m_dataFloat0 = Singleton <WeatherManager> .instance.GetWindSpeed(data.m_position); if (info.m_requireSurfaceMaps) { Singleton <TerrainManager> .instance.GetSurfaceMapping(data.m_position, out data.m_dataTexture0, out data.m_dataTexture1, out data.m_dataVector3); } instanceIndex = (uint)data.m_nextInstance; }