Segments(NetSegment.Flags flags = NetSegment.Flags.Created) { var mgr = Singleton <Cities::NetManager> .instance; return(mgr.m_segments.m_buffer.Where(e => (e.m_flags & flags) != Cities::NetSegment.Flags.None )); }
/// <summary> /// Check segment flags contain at least one of the flags in <paramref name="flagMask"/>. /// </summary> /// /// <param name="segmentId">The id of the segment to inspect.</param> /// <param name="flagMask">The flags to test.</param> /// <param name="expectedResult">If specified, ensure only the expected flags are found.</param> /// /// <returns>Returns <c>true</c> if the test passes, otherwise <c>false</c>.</returns> public bool CheckSegmentFlags(ushort segmentId, NetSegment.Flags flagMask, NetSegment.Flags?expectedResult = null) { NetSegment.Flags result = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId].m_flags & flagMask; return(expectedResult == null ? result != 0 : result == expectedResult); }
public void Calculate() { //Capture the default values. DefaultFlags = Segment.m_flags; PedestrianLaneCount = Info.CountPedestrianLanes(); Refresh(); }
public bool CheckSegmentFlags(ushort segmentId, NetSegment.Flags flagMask, NetSegment.Flags?expectedResult = null) { bool ret = false; ProcessSegment(segmentId, delegate(ushort sId, ref NetSegment segment) { ret = LogicUtil.CheckFlags((uint)segment.m_flags, (uint)flagMask, (uint?)expectedResult); return(true); }); return(ret); }
public static bool CheckFlags(this NetInfo.Segment segmentInfo, NetSegment.Flags flags, bool turnAround) { if (!turnAround) { return(flags.CheckFlags(segmentInfo.m_forwardRequired, segmentInfo.m_forwardForbidden)); } else { return(flags.CheckFlags(segmentInfo.m_backwardRequired, segmentInfo.m_backwardForbidden)); } }
public void CustomClickNodeButton(ushort nodeId, ref NetNode data, int index) { if ((data.m_flags & NetNode.Flags.Junction) == NetNode.Flags.None || Singleton <InfoManager> .instance.CurrentMode != InfoManager.InfoMode.TrafficRoutes || Singleton <InfoManager> .instance.CurrentSubMode != InfoManager.SubInfoMode.WaterPower) { return; } if (index == -1) { /*data.m_flags ^= NetNode.Flags.TrafficLights; * data.m_flags |= NetNode.Flags.CustomTrafficLights;*/ // NON-STOCK CODE START ToggleTrafficLightsTool toggleTool = (ToggleTrafficLightsTool)ModUI .GetTrafficManagerTool(true) .GetSubTool(ToolMode.SwitchTrafficLight); toggleTool.ToggleTrafficLight(nodeId, ref data, false); // NON-STOCK CODE END UpdateNodeFlags(nodeId, ref data); Singleton <NetManager> .instance.m_yieldLights.Disable(); } else if (index >= 1 && index <= 8 && (data.m_flags & (NetNode.Flags.TrafficLights | NetNode.Flags.OneWayIn)) == NetNode.Flags.None) { ushort segmentId = data.GetSegment(index - 1); if (segmentId == 0) { return; } NetManager netManager = Singleton <NetManager> .instance; NetInfo info = netManager.m_segments.m_buffer[segmentId].Info; if ((info.m_vehicleTypes & (VehicleInfo.VehicleType.Car | VehicleInfo.VehicleType.Tram)) == VehicleInfo.VehicleType.None) { return; } bool flag = netManager.m_segments.m_buffer[segmentId].m_startNode == nodeId; NetSegment.Flags flags = (!flag) ? NetSegment.Flags.YieldEnd : NetSegment.Flags.YieldStart; netManager.m_segments.m_buffer[segmentId].m_flags ^= flags; netManager.m_segments.m_buffer[segmentId].UpdateLanes(segmentId, true); Singleton <NetManager> .instance.m_yieldLights.Disable(); } }
public static void UpdateSegmentStopFlags(this RoadBridgeAI roadbridge, ushort segmentID, ref NetSegment data) { Log.Debug($"updateflags on {segmentID}"); roadbridge.UpdateSegmentFlags(segmentID, ref data); NetSegment.Flags flags = data.m_flags & ~(NetSegment.Flags.StopRight | NetSegment.Flags.StopLeft | NetSegment.Flags.StopRight2 | NetSegment.Flags.StopLeft2); if (roadbridge.m_info.m_lanes == null) { return; } NetManager instance = Singleton <NetManager> .instance; bool inverted = (data.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None; uint lane = instance.m_segments.m_buffer[(int)segmentID].m_lanes; int i = 0; while (i < roadbridge.m_info.m_lanes.Length && lane != 0U) { NetLane.Flags laneFlags = (NetLane.Flags)instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].m_flags; if ((laneFlags & NetLane.Flags.Stop) != NetLane.Flags.None) { if (roadbridge.m_info.m_lanes[i].m_position < 0f != inverted) { flags |= NetSegment.Flags.StopLeft; } else { flags |= NetSegment.Flags.StopRight; } } else if ((laneFlags & NetLane.Flags.Stop2) != NetLane.Flags.None) { if (roadbridge.m_info.m_lanes[i].m_position < 0f != inverted) { flags |= NetSegment.Flags.StopLeft2; } else { flags |= NetSegment.Flags.StopRight2; } } lane = instance.m_lanes.m_buffer[(int)((UIntPtr)lane)].m_nextLane; i++; } data.m_flags = flags; Log.Debug($"flags {flags}"); }
public static void UpdateSegmentStopFlags(this RoadBridgeAI roadbridge, ushort segmentID, ref NetSegment data) { roadbridge.UpdateSegmentFlags(segmentID, ref data); var oldflags = data.m_flags; NetSegment.Flags flags = data.m_flags & ~(NetSegment.Flags.StopRight | NetSegment.Flags.StopLeft | NetSegment.Flags.StopRight2 | NetSegment.Flags.StopLeft2); if (roadbridge.m_info.m_lanes != null) { NetManager instance = Singleton <NetManager> .instance; bool flag = (data.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None; uint num = instance.m_segments.m_buffer[(int)segmentID].m_lanes; int num2 = 0; while (num2 < roadbridge.m_info.m_lanes.Length && num != 0U) { NetLane.Flags flags2 = (NetLane.Flags)instance.m_lanes.m_buffer[(int)((UIntPtr)num)].m_flags; if ((flags2 & NetLane.Flags.Stop) != NetLane.Flags.None) { if (roadbridge.m_info.m_lanes[num2].m_position < 0f != flag) { flags |= NetSegment.Flags.StopLeft; } else { flags |= NetSegment.Flags.StopRight; } } if ((flags2 & NetLane.Flags.Stop2) != NetLane.Flags.None) { if (roadbridge.m_info.m_lanes[num2].m_position < 0f != flag) { flags |= NetSegment.Flags.StopLeft2; } else { flags |= NetSegment.Flags.StopRight2; } } num = instance.m_lanes.m_buffer[(int)((UIntPtr)num)].m_nextLane; num2++; } } Log.Debug($"oldflags {oldflags} newflags {flags} on segment {segmentID} bridge"); data.m_flags = flags; }
public static List <ushort> GetSegmentOrderRoad(ushort segmentID, bool requireSameDirection, bool requireSameSizeAndType, bool localAdjust, out bool startRef, out bool endRef, out ushort[] nodes) { NetSegment.Flags flags = NetManager.instance.m_segments.m_buffer[segmentID].m_flags; var nodeList = new List <ushort>(); if (segmentID != 0 && flags != NetSegment.Flags.None) { List <ushort> path = CalculatePathNet(segmentID, false, requireSameDirection, requireSameSizeAndType, out nodes); path.Add(segmentID); ushort startNode0 = NetManager.instance.m_segments.m_buffer[path[0]].m_startNode; ushort endNode0 = NetManager.instance.m_segments.m_buffer[path[0]].m_endNode; ushort startNodeRef = NetManager.instance.m_segments.m_buffer[segmentID].m_startNode; ushort endNodeRef = NetManager.instance.m_segments.m_buffer[segmentID].m_endNode; bool circular = (path.Count > 2 && (startNode0 == endNodeRef || startNode0 == startNodeRef || endNode0 == endNodeRef || endNode0 == startNodeRef)) || (path.Count == 2 && (startNode0 == endNodeRef || startNode0 == startNodeRef) && (endNode0 == endNodeRef || endNode0 == startNodeRef)); if (circular) { LogUtils.DoLog("Circular!"); ushort refer = path.Min(); int referIdx = path.IndexOf(refer); if (referIdx != 0) { path = path.GetRange(referIdx, path.Count - referIdx).Union(path.Take(referIdx)).ToList(); } } else { path.AddRange(CalculatePathNet(segmentID, true, requireSameDirection, requireSameSizeAndType, out _)); } //doLog($"[s={strict}]path = [{string.Join(",", path.Select(x => x.ToString()).ToArray())}]"); GetEdgeNodes(ref path, out startRef, out endRef, localAdjust); return(path); } nodes = new ushort[0]; startRef = false; endRef = false; return(null); }
private void ExportWays() { NetManager netManager = Singleton <NetManager> .instance; NetSegment[] netSegments = netManager.m_segments.m_buffer; for (int segmentId = 0; segmentId < netSegments.Length; segmentId++) { NetSegment netSegment = netSegments[segmentId]; NetSegment.Flags segmentFlags = netSegment.m_flags; if (segmentFlags.IsFlagSet(NetSegment.Flags.Created)) { OSMWay generatedWay = CreateWay(unindexedWayOffset++, netSegment, (ushort)segmentId); if (generatedWay != null) { osmWays.Add(generatedWay); } } } }
public bool CheckFlags(NetSegment.Flags flags) => flags.CheckFlags(Required, Forbidden);
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 static bool CheckFlags(this NetSegment.Flags value, NetSegment.Flags required, NetSegment.Flags forbidden = 0) => (value & (required | forbidden)) == required;
public static bool CheckFlags(this NetSegment.Flags value, NetSegment.Flags required, NetSegment.Flags forbidden) { return((value & (required | forbidden)) == required); }
/// <summary> /// Redraw the text to be drawn later with a mesh. Use sparingly, as /// this is an expensive task. /// </summary> private void RenderText() { DistrictManager districtManager = DistrictManager.instance; NetManager netManager = NetManager.instance; if (districtManager.m_properties.m_areaNameFont != null) { UIFontManager.Invalidate(districtManager.m_properties.m_areaNameFont); foreach (RouteContainer route in RouteManager.Instance().m_routeDict.Values) { if (route.m_segmentId != 0) { string routeStr = route.m_route; if (routeStr != null) { NetSegment netSegment = netManager.m_segments.m_buffer[route.m_segmentId]; NetSegment.Flags segmentFlags = netSegment.m_flags; if (segmentFlags.IsFlagSet(NetSegment.Flags.Created)) { //Load a route shield type ( generic motorway shield should be default value ) RouteShieldInfo shieldInfo = RouteShieldConfig.Instance().GetRouteShieldInfo(route.m_routePrefix); NetNode startNode = netManager.m_nodes.m_buffer[netSegment.m_startNode]; NetNode endNode = netManager.m_nodes.m_buffer[netSegment.m_endNode]; Vector3 startNodePosition = startNode.m_position; if (!SpriteUtils.m_textureStore.ContainsKey(shieldInfo.textureName)) { LoggerUtils.Log("WTF, No texture found for route shield" + shieldInfo.textureName); } Material mat = SpriteUtils.m_textureStore[shieldInfo.textureName]; route.m_shieldObject.GetComponent <Renderer>().material = mat; //TODO: Make mesh size dependent on text size route.m_shieldMesh.mesh = MeshUtils.CreateRectMesh(mat.mainTexture.width, mat.mainTexture.height); route.m_shieldMesh.transform.position = startNodePosition; route.m_shieldMesh.transform.LookAt(endNode.m_position, Vector3.up); route.m_shieldMesh.transform.Rotate(90f, 0f, 90f); //TODO: Bind the elevation of the mesh to the text z offset route.m_shieldMesh.transform.position += (Vector3.up * (0.5f)); route.m_shieldMesh.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f); route.m_shieldObject.GetComponent <Renderer>().sortingOrder = 1000; route.m_numMesh.anchor = TextAnchor.MiddleCenter; route.m_numMesh.font = FontUtils.m_fontStore.ContainsKey("Highway Gothic") ? FontUtils.m_fontStore["Highway Gothic"] : districtManager.m_properties.m_areaNameFont.baseFont; route.m_numMesh.GetComponent <Renderer>().material = route.m_numMesh.font.material; if (ShaderUtils.m_shaderStore.ContainsKey("font")) { route.m_numMesh.GetComponent <Renderer>().material.shader = ShaderUtils.m_shaderStore["font"]; } else { route.m_numMesh.GetComponent <Renderer>().material.shader = ShaderUtils.m_shaderStore["fallback"]; } //TODO: Tie the font size to the font size option route.m_numMesh.fontSize = 50; route.m_numMesh.transform.position = startNode.m_position; route.m_numMesh.transform.parent = route.m_shieldObject.transform; route.m_numMesh.transform.LookAt(endNode.m_position, Vector3.up); route.m_numMesh.transform.Rotate(90f, 0f, 90f); route.m_numMesh.transform.position = route.m_shieldObject.GetComponent <Renderer>().bounds.center; //Just a hack, to make sure the text actually shows up above the shield route.m_numMesh.offsetZ = 0.001f; //TODO: Definitely get a map of the texture to the required text offsets route.m_numMesh.transform.localPosition += (Vector3.up * shieldInfo.upOffset); route.m_numMesh.transform.localPosition += (Vector3.left * shieldInfo.leftOffset); //TODO: Figure out a better ratio for route markers route.m_numMesh.transform.localScale = new Vector3(shieldInfo.textScale, shieldInfo.textScale, shieldInfo.textScale); route.m_numMesh.GetComponent <Renderer>().material.color = shieldInfo.textColor; route.m_numMesh.text = route.m_route.ToString(); } } } } foreach (SignContainer sign in RouteManager.Instance().m_signList) { Vector3 position = new Vector3(sign.x, sign.y, sign.z); string signPropType = (sign.m_exitNum == null || !m_signPropDict.ContainsKey(sign.m_exitNum)) ? "hwysign" : sign.m_exitNum; SignPropInfo signPropInfo = SignPropConfig.signPropInfoDict[signPropType]; int numSignProps = signPropInfo.isDoubleGantry ? 2 : 1; sign.m_sign.GetComponent <Renderer>().material = m_signPropDict[signPropType].m_material; //TODO: Make mesh size dependent on text size sign.m_sign.mesh = m_signPropDict[signPropType].m_mesh; sign.m_sign.transform.position = position; if (sign.m_routePrefix != null) { RouteShieldInfo shieldInfo = RouteShieldConfig.Instance().GetRouteShieldInfo(sign.m_routePrefix); Material mat = SpriteUtils.m_textureStore[shieldInfo.textureName]; sign.m_shieldObject.GetComponent <Renderer>().material = mat; //TODO: Make mesh size dependent on text size sign.m_shieldMesh.mesh = MeshUtils.CreateRectMesh(mat.mainTexture.width, mat.mainTexture.height); sign.m_shieldMesh.transform.position = position; //TODO: Bind the elevation of the mesh to the text z offset sign.m_shieldMesh.transform.position += (Vector3.up * (0.5f)); sign.m_shieldMesh.transform.localScale = signPropInfo.shieldScale; sign.m_shieldObject.GetComponent <Renderer>().sortingOrder = 1000; sign.m_numMesh.anchor = TextAnchor.MiddleCenter; sign.m_numMesh.font = FontUtils.m_fontStore.ContainsKey("Highway Gothic") ? FontUtils.m_fontStore["Highway Gothic"] : districtManager.m_properties.m_areaNameFont.baseFont; sign.m_numMesh.GetComponent <Renderer>().material = sign.m_numMesh.font.material; if (ShaderUtils.m_shaderStore.ContainsKey("font")) { sign.m_numMesh.GetComponent <Renderer>().material.shader = ShaderUtils.m_shaderStore["font"]; } else { sign.m_numMesh.GetComponent <Renderer>().material.shader = ShaderUtils.m_shaderStore["fallback"]; } //TODO: Tie the font size to the font size option sign.m_numMesh.fontSize = 50; sign.m_numMesh.transform.position = position; sign.m_numMesh.transform.parent = sign.m_shieldObject.transform; sign.m_numMesh.transform.position = sign.m_shieldObject.GetComponent <Renderer>().bounds.center; //Just a hack, to make sure the text actually shows up above the shield sign.m_numMesh.offsetZ = 0.01f; //TODO: Definitely get a map of the texture to the required text offsets ds sign.m_numMesh.transform.localPosition += (Vector3.up * shieldInfo.upOffset); sign.m_numMesh.transform.localPosition += (Vector3.left * shieldInfo.leftOffset); //TODO: Figure out a better ratio for route markers sign.m_numMesh.transform.localScale = new Vector3(shieldInfo.textScale, shieldInfo.textScale, shieldInfo.textScale); sign.m_numMesh.GetComponent <Renderer>().material.color = shieldInfo.textColor; sign.m_numMesh.text = sign.m_route.ToString(); sign.m_numMesh.TE sign.m_shieldMesh.transform.parent = sign.m_sign.transform; sign.m_shieldMesh.transform.localPosition = signPropInfo.shieldOffset; } string[] destinationStrings = sign.m_destination.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); for (int i = 0; i < numSignProps; i++) { sign.m_destinationMesh[i].anchor = TextAnchor.MiddleCenter; sign.m_destinationMesh[i].font = FontUtils.m_fontStore.ContainsKey(signPropInfo.fontType) ? FontUtils.m_fontStore[signPropInfo.fontType] : districtManager.m_properties.m_areaNameFont.baseFont; sign.m_destinationMesh[i].font.material.SetColor("Text Color", Color.white); if (ShaderUtils.m_shaderStore.ContainsKey("font")) { sign.m_destinationMesh[i].font.material.shader = ShaderUtils.m_shaderStore["font"]; } else { sign.m_destinationMesh[i].font.material.shader = ShaderUtils.m_shaderStore["fallback"]; } sign.m_destinationMesh[i].GetComponent <Renderer>().material = sign.m_destinationMesh[i].font.material; //TODO: Tie the font size to the font size option sign.m_destinationMesh[i].fontSize = 50; sign.m_destinationMesh[i].transform.position = position; sign.m_destinationMesh[i].transform.parent = sign.m_sign.transform; sign.m_destinationMesh[i].transform.position = position; //Just a hack, to make sure the text actually shows up above the shield sign.m_destinationMesh[i].offsetZ = 0.001f; //TODO: Definitely get a map of the texture to the required text offsets //TODO: Figure out a better ratio for route markers sign.m_destinationMesh[i].transform.localScale = signPropInfo.textScale; sign.m_destinationMesh[i].text = signPropInfo.isDoubleGantry ? destinationStrings[i] : sign.m_destination; sign.m_destinationMesh[i].transform.localPosition = sign.m_routePrefix == null ? signPropInfo.textOffsetNoSign[i] : signPropInfo.textOffsetSign[i]; } } foreach (DynamicSignContainer sign in RouteManager.Instance().m_dynamicSignList) { Vector3 position = new Vector3(sign.x, sign.y, sign.z); sign.m_sign.GetComponent <Renderer>().material = m_signPropDict["electronic_sign_gantry"].m_material; //TODO: Make mesh size dependent on text size sign.m_sign.mesh = m_signPropDict["electronic_sign_gantry"].m_mesh; sign.m_sign.transform.position = position; sign.m_messageTextMesh.anchor = TextAnchor.MiddleLeft; sign.m_messageTextMesh.font = FontUtils.m_fontStore.ContainsKey("Electronic Highway Sign") ? FontUtils.m_fontStore["Electronic Highway Sign"] : districtManager.m_properties.m_areaNameFont.baseFont; if (ShaderUtils.m_shaderStore.ContainsKey("font")) { sign.m_messageTextMesh.font.material.shader = ShaderUtils.m_shaderStore["font"]; } else { sign.m_numMesh.GetComponent <Renderer>().material.shader = ShaderUtils.m_shaderStore["fallback"]; } sign.m_messageTextMesh.color = (new Color(1, 0.77f, 0.56f, 1f)); sign.m_messageTextMesh.font.material.SetColor("Text Color", new Color(1, 0.77f, 0.56f, 1f)); sign.m_messageTextMesh.GetComponent <Renderer>().material = sign.m_messageTextMesh.font.material; //TODO: Tie the font size to the font size option sign.m_messageTextMesh.fontSize = 50; sign.m_messageTextMesh.transform.position = position; sign.m_messageTextMesh.transform.parent = sign.m_sign.transform; sign.m_messageTextMesh.transform.position = position; //Just a hack, to make sure the text actually shows up above the shield sign.m_messageTextMesh.offsetZ = 0.001f; //TODO: Definitely get a map of the texture to the required text odffsets //TODO: Figure out a better ratio for route markers sign.m_messageTextMesh.transform.localScale = new Vector3(0.25f, 0.25f, 0.25f); String msgText = (sign.m_route == null ? "Traffic" : (sign.m_routePrefix + '-' + sign.m_route)) + " moving smoothly"; sign.m_messageTextMesh.text = msgText; sign.m_messageTextMesh.transform.localPosition = new Vector3(0.7f, 8.4f, -19.7f); } } }
private bool SnapToOneSide(Vector3 refPos, out Vector3 pos, out Vector3 dir, float maxDistance) { bool result = false; pos = refPos; dir = Vector3.forward; float minX = refPos.x - maxDistance - 100f; float minZ = refPos.z - maxDistance - 100f; float maxX = refPos.x + maxDistance + 100f; float maxZ = refPos.z + maxDistance + 100f; int minXint = Mathf.Max((int)(minX / 64f + 135f), 0); int minZint = Mathf.Max((int)(minZ / 64f + 135f), 0); int maxXint = Mathf.Max((int)(maxX / 64f + 135f), 269); int maxZint = Mathf.Max((int)(maxZ / 64f + 135f), 269); Array16 <NetSegment> segments = Singleton <NetManager> .instance.m_segments; ushort[] segmentGrid = Singleton <NetManager> .instance.m_segmentGrid; for (int i = minZint; i <= maxZint; i++) { for (int j = minXint; j <= maxXint; j++) { ushort segmentGridZX = segmentGrid[i * 270 + j]; int iterator = 0; while (segmentGridZX != 0) { NetSegment.Flags flags = segments.m_buffer[(int)segmentGridZX].m_flags; if ((flags & (NetSegment.Flags.Created | NetSegment.Flags.Deleted)) == NetSegment.Flags.Created) { NetInfo info = segments.m_buffer[(int)segmentGridZX].Info; if (info.m_class.m_service == ItemClass.Service.Road) { Vector3 min = segments.m_buffer[(int)segmentGridZX].m_bounds.min; Vector3 max = segments.m_buffer[(int)segmentGridZX].m_bounds.max; if (min.x < maxX && min.z < maxZ && max.x > minX && max.z > minZ) { Vector3 centerPos; Vector3 centerDirection; segments.m_buffer[(int)segmentGridZX].GetClosestPositionAndDirection(refPos, out centerPos, out centerDirection); float distanceToRoad = Vector3.Distance(centerPos, refPos) - info.m_halfWidth; if (distanceToRoad < maxDistance) { if (info.m_lanes.Length == 9 || info.m_halfWidth == 20) { if (this.m_rotation == 0 || this.m_rotation == 180) { Vector3 vector2 = new Vector3(centerDirection.z, 0f, -centerDirection.x); dir = vector2.normalized; float delta = Vector3.Dot(centerPos - refPos, dir); if (delta > info.m_halfWidth / 2f && delta > 0 || delta < 0 && delta > -info.m_halfWidth / 2f) { if (this.m_rotation == 0) { dir = -dir; } } } else if (this.m_rotation == 90 || this.m_rotation == 270) { Vector3 vector2 = new Vector3(centerDirection.x, 0f, centerDirection.z); dir = vector2.normalized; float delta = Vector3.Dot(centerPos - refPos, dir); if (delta > info.m_halfWidth / 2f && delta > 0 || delta < 0 && delta > -info.m_halfWidth / 2f) { if (this.m_rotation == 90) { dir = -dir; } } } } else if (info.m_lanes.Length == 13 || info.m_halfWidth == 29) { if (this.m_rotation == 0 || this.m_rotation == 180) { Vector3 vector2 = new Vector3(centerDirection.z, 0f, -centerDirection.x); dir = vector2.normalized; float delta = Vector3.Dot(centerPos - refPos, dir); if (delta > 2f * info.m_halfWidth / 3f && delta > 0 || delta > 0 && delta < info.m_halfWidth / 3f || delta < -info.m_halfWidth / 3f && delta > -2f * info.m_halfWidth / 3f) { if (this.m_rotation == 0) { dir = -dir; } } } else if (this.m_rotation == 90 || this.m_rotation == 270) { Vector3 vector2 = new Vector3(centerDirection.x, 0f, centerDirection.z); dir = vector2.normalized; float delta = Vector3.Dot(centerPos - refPos, dir); if (delta > 2f * info.m_halfWidth / 3f && delta > 0 || delta > 0 && delta < info.m_halfWidth / 3f || delta < -info.m_halfWidth / 3f && delta > 2f * info.m_halfWidth / 3f) { if (this.m_rotation == 90) { dir = -dir; } } } } else { if (this.m_rotation == 0 || this.m_rotation == 180) { Vector3 vector2 = new Vector3(centerDirection.z, 0f, -centerDirection.x); dir = vector2.normalized; if (Vector3.Dot(centerPos - refPos, dir) > 0f) { if (this.m_rotation == 0) { dir = -dir; } } } else if (this.m_rotation == 90 || this.m_rotation == 270) { Vector3 vector2 = new Vector3(centerDirection.x, 0f, centerDirection.z); dir = vector2.normalized; if (Vector3.Dot(centerPos - refPos, dir) > 0f) { if (this.m_rotation == 90) { dir = -dir; } } } } Vector3 centerDirectionNormalized = centerDirection.normalized; float distanceDivisor = 100f; if (info.m_lanes.Length == 9 || info.m_halfWidth == 20) { float delta2 = Vector3.Dot(centerPos - refPos, dir); if (delta2 < -info.m_halfWidth / 2f) { pos = centerPos + dir * (9f + this.m_offset - (float)ModSettings.DistanceFromCurb / distanceDivisor); } else if (delta2 > -info.m_halfWidth / 2f && delta2 < 0) { pos = centerPos + dir * (9f - this.m_offset - (float)ModSettings.DistanceBetweenParkingStalls / distanceDivisor); } else if (delta2 < info.m_halfWidth) { pos = centerPos - dir * (9f - this.m_offset + (float)ModSettings.DistanceBetweenParkingStalls / distanceDivisor); } else { pos = centerPos - dir * (9f + this.m_offset - (float)ModSettings.DistanceFromCurb / distanceDivisor); } } else if (info.m_lanes.Length == 13 || info.m_halfWidth == 29) { float delta2 = Vector3.Dot(centerPos - refPos, dir); if (delta2 < -2f * info.m_halfWidth / 3f) { pos = centerPos + dir * (18f + this.m_offset - (float)ModSettings.DistanceFromCurb / distanceDivisor); } else if (delta2 < -info.m_halfWidth / 3f) { pos = centerPos + dir * (18f - this.m_offset - (float)ModSettings.DistanceBetweenParkingStalls / distanceDivisor); } else if (delta2 < 0f) { pos = centerPos + dir * (this.m_offset - (float)ModSettings.DistanceBetweenParkingStalls / distanceDivisor); } else if (delta2 < info.m_halfWidth / 3f) { pos = centerPos - dir * (this.m_offset + (float)ModSettings.DistanceBetweenParkingStalls / distanceDivisor); } else if (delta2 < 2f * info.m_halfWidth / 3f) { pos = centerPos - dir * (18f - this.m_offset + (float)ModSettings.DistanceBetweenParkingStalls / distanceDivisor); } else { pos = centerPos - dir * (18f + this.m_offset - (float)ModSettings.DistanceFromCurb / distanceDivisor); } } else if (info.m_lanes.Length == 4 || info.m_halfWidth == 8) { if (Vector3.Dot(centerPos - refPos, dir) < 0f) { pos = centerPos + dir * (this.m_offset - 3f - (float)ModSettings.DistanceFromCurb / distanceDivisor); } else { pos = centerPos - dir * (this.m_offset - 3f - (float)ModSettings.DistanceFromCurb / distanceDivisor); } } else { if (Vector3.Dot(centerPos - refPos, dir) < 0f) { pos = centerPos + dir * (this.m_offset - (float)ModSettings.DistanceFromCurb / distanceDivisor); } else { pos = centerPos - dir * (this.m_offset - (float)ModSettings.DistanceFromCurb / distanceDivisor); } } maxDistance = distanceToRoad; result = true; } } } } segmentGridZX = segments.m_buffer[(int)segmentGridZX].m_nextGridSegment; if (++iterator >= 32768) { Debug.Log("[APL].PSAAI.SnapToRoad Invalid List Detected!!!"); break; } } } } return(result); }
private bool SnapToRoad(Vector3 refPos, out Vector3 pos, out Vector3 dir, float maxDistance, Building currentBuilding) { bool result = false; pos = refPos; dir = Vector3.forward; float minX = refPos.x - maxDistance - 100f; float minZ = refPos.z - maxDistance - 100f; float maxX = refPos.x + maxDistance + 100f; float maxZ = refPos.z + maxDistance + 100f; int minXint = Mathf.Max((int)(minX / 64f + 135f), 0); int minZint = Mathf.Max((int)(minZ / 64f + 135f), 0); int maxXint = Mathf.Max((int)(maxX / 64f + 135f), 269); int maxZint = Mathf.Max((int)(maxZ / 64f + 135f), 269); Array16 <NetSegment> segments = Singleton <NetManager> .instance.m_segments; ushort[] segmentGrid = Singleton <NetManager> .instance.m_segmentGrid; for (int i = minZint; i <= maxZint; i++) { for (int j = minXint; j <= maxXint; j++) { ushort segmentGridZX = segmentGrid[i * 270 + j]; int iterator = 0; while (segmentGridZX != 0) { NetSegment.Flags flags = segments.m_buffer[(int)segmentGridZX].m_flags; if ((flags & (NetSegment.Flags.Created | NetSegment.Flags.Deleted)) == NetSegment.Flags.Created) { NetInfo info = segments.m_buffer[(int)segmentGridZX].Info; if (info.m_class.m_service == ItemClass.Service.Road) { Vector3 min = segments.m_buffer[(int)segmentGridZX].m_bounds.min; Vector3 max = segments.m_buffer[(int)segmentGridZX].m_bounds.max; if (min.x < maxX && min.z < maxZ && max.x > minX && max.z > minZ) { Vector3 centerPos; Vector3 centerDirection; segments.m_buffer[(int)segmentGridZX].GetClosestPositionAndDirection(refPos, out centerPos, out centerDirection); float distanceToRoad = Vector3.Distance(centerPos, refPos) - info.m_halfWidth; //Debug.Log("[APL].PSAAI.Snap to Road info.lanes = " + info.m_lanes.Length.ToString()); //Debug.Log("[APL].PSAAI.Snap to Road info.m_halfwidth = " + info.m_halfWidth.ToString()); if (distanceToRoad < maxDistance) { Vector3 vector2 = new Vector3(centerDirection.z, 0f, -centerDirection.x); dir = vector2.normalized; if (Vector3.Dot(centerPos - refPos, dir) < 0f) { dir = -dir; } if (info.m_halfWidth == 20 || info.m_lanes.Length == 9) { if (this.m_rotation == 0 || this.m_rotation == 180) { if (Vector3.Dot(centerPos - refPos, dir) > 0f) { if (this.m_rotation == 0) { dir = -dir; } } } else if (this.m_rotation == 90 || this.m_rotation == 270) { if (Vector3.Dot(centerPos - refPos, dir) > 0f) { if (this.m_rotation == 90) { dir = -dir; } } } Vector3 centerDirectionNormalized = centerDirection.normalized; if (Vector3.Dot(centerPos - refPos, dir) < 0f) { pos = centerPos + dir * (9f); } else { pos = centerPos - dir * (9f); } } else if (info.m_halfWidth == 29 || info.m_lanes.Length == 13) { pos = centerPos; if (this.m_rotation == 0 || this.m_rotation == 180) { if (Vector3.Dot(centerPos - refPos, dir) > 0f) { if (this.m_rotation == 0) { dir = -dir; } } } else if (this.m_rotation == 90 || this.m_rotation == 270) { if (Vector3.Dot(centerPos - refPos, dir) > 0f) { if (this.m_rotation == 90) { dir = -dir; } } } Vector3 centerDirectionNormalized = centerDirection.normalized; if (Vector3.Dot(centerPos - refPos, dir) < -11f) { pos = centerPos + dir * 18f; } else if ((Vector3.Dot(centerPos - refPos, dir) > 11f)) { pos = centerPos - dir * 18f; } } else { float angle = Mathf.Atan2(dir.x, -dir.z); ushort adjacentParkingAssetID = CheckForParkingSpaces(centerPos, angle, currentBuilding.m_width, currentBuilding.m_length); bool snappedToParkingAsset = false; /* * if (adjacentParkingAssetID != 0) { * Building adjacentParkingAsset = BuildingManager.instance.m_buildings.m_buffer[adjacentParkingAssetID]; * if (adjacentParkingAsset.m_angle == angle) * { * Debug.Log("[APL].PSAAi.SnapToRoad Snap to this asset id = " + adjacentParkingAssetID.ToString()); * Vector3 centerDirectionNormalized = centerDirection.normalized; * * float dist1 = Vector3.Dot(centerPos - adjacentParkingAsset.m_position, centerDirectionNormalized); * Debug.Log("[APL].PSAAi.SnapToRoad Dot Product equals " + dist1.ToString()); * pos = centerPos - (adjacentParkingAsset.Width*4f-dist1)*centerDirectionNormalized + currentBuilding.m_width*4f* centerDirectionNormalized; * snappedToParkingAsset = true; * * //snappedToParkingAsset = true; * } * } */ if (snappedToParkingAsset == false) { pos = centerPos; } } maxDistance = distanceToRoad; result = true; } } } } segmentGridZX = segments.m_buffer[(int)segmentGridZX].m_nextGridSegment; if (++iterator >= 32768) { Debug.Log("[APL].PSAAI.SnapToRoad Invalid List Detected!!!"); break; } } } } return(result); }
internal static bool IsFlagSet(this NetSegment.Flags value, NetSegment.Flags flag) => (value & flag) != 0;
/// <summary> /// Perform actual network replacement. /// </summary> /// <param name="target">Target netInfo</param> /// <param name="replacement">Replacement netInfo</param> /// <param name="segmentList">Array of segment IDs</param> internal static void ReplaceNets(NetInfo target, NetInfo replacement, List <ushort> segmentList) { try { // Ensure segment list is valid.. if (segmentList == null || segmentList.Count == 0) { Logging.Message("no selected networks for replacing"); return; } // Input checks. if (target?.name == null || replacement?.name == null) { Logging.Error("null parameter passed to ReplaceNets"); return; } // Local references. NetManager netManager = Singleton <NetManager> .instance; Randomizer randomizer = new Randomizer(); NetSegment[] segmentBuffer = netManager.m_segments.m_buffer; // Copy segment IDs from segment list to avoid concurrency issues while replacing. ushort[] segmentIDs = new ushort[segmentList.Count]; segmentList.CopyTo(segmentIDs, 0); // Initialize undo buffer. undoBuffer = new List <ushort>(); undoPrefab = target; // Iterate through each segment ID in our prepared list. for (int i = 0; i < segmentIDs.Length; ++i) { // Local references. ushort segmentID = segmentIDs[i]; NetSegment segment = segmentBuffer[segmentID]; // Null check, just in case. NetInfo segmentInfo = segment.Info; if (segmentInfo != null) { // Check that this is an active network before we do actual replacement. if (segment.m_flags != NetSegment.Flags.None) { // Get segment name and prority. bool priority = netManager.IsPriorityRoad(segmentID, out bool _); ushort nameSeed = segment.m_nameSeed; bool customNameFlag = (segment.m_flags & NetSegment.Flags.CustomName) != 0; string segmentName = netManager.GetSegmentName(segmentID); NetSegment.Flags flags = segment.m_flags & NetSegment.Flags.Original; // Get segment 'original' status. NetSegment.Flags originalFlag = segment.m_flags & NetSegment.Flags.Original; // Active network segment - replace segment. ushort newSegmentID = ReplaceNet(segmentID, segmentBuffer, replacement, ref randomizer); // Set nameseed and priority of new segment to match original. segmentBuffer[newSegmentID].m_nameSeed = nameSeed; netManager.SetPriorityRoad(newSegmentID, priority); // Set 'original' status of new segment. segmentBuffer[newSegmentID].m_flags |= originalFlag; // Restore any custom name. if (customNameFlag && segmentName != null) { netManager.SetSegmentNameImpl(newSegmentID, segmentName); } // Add new segment ID to undo buffer. undoBuffer.Add(newSegmentID); } else { // Inactive network segment - just replace info directly.. segmentBuffer[segmentID].Info = replacement; } } } } catch (Exception e) { // Don't care too much - just want to make sure that we set the status flag correctly and not hang in the 'processing' state indefinitely. Logging.LogException(e, "network replacement exception"); } // All done - let replacer panel know we're finished (if its still open). if (ReplacerPanel.Panel != null) { ReplacerPanel.Panel.replacingDone = true; } }
public bool CheckFlags( NetNodeExt.Flags nodeFlags, NetSegmentEnd.Flags segmentEndFlags, NetSegmentExt.Flags segmentFlags, NetSegment.Flags vanillaSegmentFlags) => NodeFlags.CheckFlags(nodeFlags) && SegmentEndFlags.CheckFlags(segmentEndFlags) && SegmentFlags.CheckFlags(segmentFlags) && VanillaSegmentFlags.CheckFlags(vanillaSegmentFlags);
private OSMWay CreateWay(int index, NetSegment segment, ushort segmentId) { OSMWay returnWay = null; NetSegment.Flags segmentFlags = segment.m_flags; NetManager netManager = Singleton <NetManager> .instance; List <OSMWayND> wayPaths = new List <OSMWayND>(); List <OSMWayTag> wayTags; ushort startNodeId = segment.m_startNode, endNodeId = segment.m_endNode; if (startNodeId != 0 && endNodeId != 0) { Vector3 startNodeDirection = segment.m_startDirection; Vector3 endNodeDirection = segment.m_endDirection; if (segmentFlags.IsFlagSet(NetSegment.Flags.Invert)) { startNodeId = segment.m_endNode; endNodeId = segment.m_startNode; startNodeDirection = segment.m_endDirection; endNodeDirection = segment.m_startDirection; } NetNode startNode = netManager.m_nodes.m_buffer[startNodeId]; NetNode endNode = netManager.m_nodes.m_buffer[endNodeId]; Vector3 startNodePosition = startNode.m_position; Vector3 endNodePosition = endNode.m_position; wayPaths.Add(new OSMWayND { @ref = startNodeId }); if (Vector3.Angle(startNodeDirection, -endNodeDirection) > 3f) { Vector3 midPointA = Vector3.zero, midPointB = Vector3.zero; NetSegment.CalculateMiddlePoints(startNodePosition, startNodeDirection, endNodePosition, endNodeDirection, false, false, out midPointA, out midPointB); Bezier3 bezier = new Bezier3(startNodePosition, midPointA, midPointB, endNodePosition); osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.25f))); osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.5f))); osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.75f))); wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 3 }); wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 2 }); wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 1 }); } wayPaths.Add(new OSMWayND { @ref = endNodeId }); if (Tagger.CreateWayTags(segment, out wayTags)) { if (haveRoadNamerMod) { // If road namer mod is available, then attempt to get the name asscociated with the segment, if any string roadName = RoadNamerManager.Instance().getSegmentName((ushort)(segmentId)); if (roadName != null) { //If a name is available, add a name tag wayTags.Add(new OSMWayTag { k = "name", v = StringUtilities.RemoveTags(roadName) }); } } returnWay = new OSMWay { changeset = 50000000, id = (uint)index, timestamp = DateTime.Now, user = "******", nd = wayPaths.ToArray(), tag = wayTags.ToArray(), version = 1 }; } else { UniqueLogger.AddLog("Road names missing from search", segment.Info.name, ""); } } return(returnWay); }