static bool IsSplineParent(SplineBase spline, SplineBase parent) { if (parent.IsHazard) { return(false); } Vector3 splineMin = spline.Lines.MinPoint; Vector3 splineMax = spline.Lines.MaxPoint; Vector3 parentMin = parent.Lines.MinPoint; Vector3 parentMax = parent.Lines.MaxPoint; if (splineMin.x < parentMin.x || splineMax.x > parentMax.x || splineMin.z < parentMin.z || splineMax.z > parentMax.z) { return(false); } Vector3[] splineLinePoints = spline.Lines.Lines; Vector3[] parentSplineLinePoints = parent.Lines.Lines; for (int i = 0; i < splineLinePoints.Length; ++i) { if (!splineLinePoints[i].IsInside(parentSplineLinePoints)) { return(false); } } return(true); }
Line GridFill(SplineBase spline, Line line) { float offset = spline.Offset + spline.Depth; Layer layer = spline.Layer; float resolution = layer.resolution; SplineBase.SplinePattern pattern = spline.Pattern; Color color = new Color(pattern.extra ? 0 : 1, 0, 0, spline.IsHole ? 0.01f : 1); Line xy = new Line(); for (float x = editorMin.x; x < editorMax.x; x += resolution) { for (float z = editorMin.z; z < editorMax.z; z += resolution) { Vector3 point = new Vector3(x, 0, z); if (!point.IsInside(line.points)) { continue; } float y = offset; xy.Add(GetPosition(new Vector2(x, z), y), GetNormal(point, Vector3.zero, Vector3.zero, new Vector2(x, z)), color); } } return(xy); }
/// <summary> /// Creates spline /// </summary> /// <param name="info"></param> /// <returns></returns> public static SplineBase CreateSpline(SplineBase.SplineInfo info) { SplineBase spline = CreateSpline(info.points.ToVector3(), CourseBase.GetLayer(info.layerName, SplineLayers), (SplineBase.SplineInfo.Flags)info.flags, info.InstanceID); spline.Info.pin = info.pin; spline.UpdateLine(); splines.Add(spline); spline.LineChanged(); return(spline); }
/// <summary> /// Creates pin lip hole spline /// </summary> /// <param name="position"></param> /// <returns></returns> public static SplineBase CreatePinLipHole(Vector3 position) { Vector3Object[] points = MakeCircle(position, Utility.holeLip); SplineBase.SplineInfo info = new SplineBase.SplineInfo(); info.layerName = GetPinLipLayer().name; info.points = points; info.InstanceID = FreeSplineInstanceID(); SplineBase spline = CreateSpline(info); spline.Info.pin = true; return(spline); }
/// <summary> /// Update mesh visibility /// </summary> /// <param name="spline"></param> /// <param name="visible"></param> public void UpdateVisibility(SplineBase spline, bool visible) { if (visible) { if (meshRenderer) { meshRenderer.enabled = true; } } else { if (meshRenderer) { meshRenderer.enabled = false; } } }
/// <summary> /// Creates spline /// </summary> /// <param name="points"></param> /// <param name="layer"></param> /// <param name="flags"></param> /// <param name="rearrange"></param> /// <returns></returns> public static SplineBase CreateSpline(Vector3[] points, Layer layer, SplineBase.SplineInfo.Flags flags, bool rearrange = false) { if ((flags & SplineBase.SplineInfo.Flags.Square) == 0 || rearrange) { points = points.ToList().RearrangePoints(layer.metersPerOnePoint).ToArray(); } if (points.Length < 3) { return(null); } SplineBase spline = CreateSpline(points, layer, flags, FreeSplineInstanceID()); spline.UpdateLine(); splines.Add(spline); spline.LineChanged(); return(spline); }
static void CheckSplines() { List <HazardBase> hazards = Hazards; for (int i = 0; i < hazards.Count; ++i) { HazardBase hazard = hazards[i]; if (hazard.Info.layerName == "NoLayerName") { hazard.Info.layerName = GetLayer(hazard.Info.layerIndex, Layers).name; } if (hazard.Info.colorNames.Length == 0) { hazard.Info.colorNames = new string[hazard.Info.colorIndex.Length]; for (int j = 0; j < hazard.Info.colorNames.Length; ++j) { hazard.Info.colorNames[j] = GetLayer(hazard.Info.colorIndex[j], HazardLayers).name; } } } List <SplineBase> splines = Splines; for (int i = 0; i < splines.Count; ++i) { SplineBase spline = splines[i]; if (spline.Info.pin) { MonoBehaviour.DestroyImmediate(spline.gameObject); splines.Remove(spline); i = -1; continue; } if (spline.Info.layerName == "NoLayerName") { spline.Info.layerName = GetLayer(spline.Info.layerIndex, Layers).name; } } }
static void SetRefreshRecursive(SplineBase spline) { if (spline == null) { Debug.LogException(new NullReferenceException("Null spline")); return; } spline.SetRefresh(); for (int i = 0; i < spline.Transform.childCount; ++i) { SplineBase child = spline.Transform.GetChild(i).GetComponent <SplineBase>(); if (child) { SetRefreshRecursive(child); } } }
/// <summary> /// Reparents splines /// </summary> public static void ReparentSplines() { List <SplineBase> splines = Splines; for (int i = 0; i < splines.Count; ++i) { SplineBase spline = splines[i]; SplineBase cachedParent = null; Transform cachedParentTransform = null; for (int j = 0; j < splines.Count; ++j) { if (i == j) { continue; } SplineBase j_Parent = splines[j]; if (IsSplineParent(spline, j_Parent)) { if (cachedParent == null) { cachedParent = j_Parent; cachedParentTransform = j_Parent.Transform; } else if (!IsSplineParent(cachedParent, j_Parent)) { cachedParent = j_Parent; cachedParentTransform = j_Parent.Transform; } } } spline.transform.parent = cachedParentTransform; } List <HazardBase> hazards = Hazards; for (int i = 0; i < hazards.Count; ++i) { hazards[i].transform.parent = null; } }
/// <summary> /// Creates spline /// </summary> /// <param name="points"></param> /// <param name="layer"></param> /// <param name="flags"></param> /// <param name="instanceID"></param> /// <returns></returns> public static SplineBase CreateSpline(Vector3[] points, Layer layer, SplineBase.SplineInfo.Flags flags, int instanceID) { GameObject gameObject = new GameObject("Spline " + instanceID.ToString()); if (PlatformBase.IO.IsEditor) { PlatformBase.Editor.RegisterCreatedObjectUndo(gameObject, "Spline tool Creation"); PlatformBase.Editor.SetStaticFlags(gameObject); gameObject.hideFlags = HideFlags.HideInHierarchy; } SplineBase spline = (SplineBase)gameObject.AddComponent(Types.GetType("PerfectParallel.CourseForge.Spline", "Assembly-CSharp")); spline.Info.layerName = layer.name; spline.Points = (Vector3[])points.Clone(); spline.Info.flags = (int)flags; spline.Info.InstanceID = instanceID; spline.UpdateLine(); splines.Add(spline); spline.LineChanged(); return(spline); }
List <Line> RadialFill(SplineBase spline) { Layer layer = spline.Layer; float resolution = layer.resolution; float offset = spline.Offset + spline.Depth; float minDistanceToChilds = (RealMaxPoint - RealMinPoint).magnitude; List <Line> xy = new List <Line>(); Color color = innerLine.colors[0]; List <List <Vector2> > previous = new List <List <Vector2> >(); previous.Add(innerLine.points.ToVector2()); float distance = 0; while (distance + resolution < minDistanceToChilds) { distance += resolution; List <List <Vector2> > current = new List <List <Vector2> >(); for (int t = 0; t < 10; ++t) { try { current = previous.MakeShell(-resolution, 1000 + t); break; } catch { } } for (int i = 0; i < current.Count; ++i) { if (current[i].Count < 3) { current.RemoveAt(i); i = -1; continue; } } for (int i = 0; i < current.Count; ++i) { Line line = new Line(); for (int j = 0; j < current[i].Count; ++j) { Vector3 position = GetPosition(current[i][j], offset); Vector3 normal = GetNormal(position, Vector3.zero, Vector3.zero, current[i][j]); line.Add(position, normal, color); } xy.Add(line); } previous = current; } for (int i = 0; i < previous.Count; ++i) { Vector2 center = previous[i][0]; for (int j = 1; j < previous[i].Count; ++j) { center += previous[i][j]; } center /= previous[i].Count; { Line line = new Line(); Vector3 position = GetPosition(center, offset); Vector3 normal = GetNormal(position, Vector3.zero, Vector3.zero, center); line.Add(position, normal, color); xy.Add(line); } } return(xy); }
/// <summary> /// Uppdate mesh data, create mesh /// </summary> /// <param name="spline"></param> public void UpdateMesh(SplineBase spline) { outerLine.Update(); extraOuterLine.Update(); extraInnerLine.Update(); shrinkLine.Update(); innerLine.Update(); transitionPoly.Clear(); extraPoly.Clear(); extraTransitionPoly.Clear(); shrinkPoly.Clear(); corePoly.Clear(); SplineBase.SplinePattern pattern = spline.Pattern; if (pattern.extra) { if (pattern.transition) { transitionPoly.AddSimple(outerLine, extraOuterLine); } extraPoly.AddSimple(extraOuterLine, extraInnerLine); if (pattern.shrink) { if (pattern.extraTransition) { extraTransitionPoly.AddSimple(extraInnerLine, shrinkLine); } shrinkPoly.AddSimple(shrinkLine, innerLine); } else { if (pattern.extraTransition) { extraTransitionPoly.AddSimple(extraInnerLine, innerLine); } } } else { if (pattern.shrink) { if (pattern.transition) { transitionPoly.AddSimple(outerLine, shrinkLine); } shrinkPoly.AddSimple(shrinkLine, innerLine); } else { if (pattern.transition) { transitionPoly.AddSimple(outerLine, innerLine); } } } if (!spline.IsHazard) { corePoly.AddPolygon(innerLine); Layer layer = spline.Layer; if (layer.fillType == Layer.FillType.Grid_Fill) { corePoly.AddSteiner(GridFill(spline, innerLine)); for (int i = 0; i < spline.Transform.childCount; ++i) { SplineBase child = spline.Transform.GetChild(i).GetComponent <SplineBase>(); child.Lines.outerLine.Update(); corePoly.AddChildAsHole(child.Lines.outerLine); } } if (layer.fillType == Layer.FillType.Radial_Fill) { List <Line> xy = RadialFill(spline); for (int i = 0; i < xy.Count; ++i) { corePoly.AddSteiner(xy[i]); } for (int i = 0; i < spline.Transform.childCount; ++i) { SplineBase child = spline.Transform.GetChild(i).GetComponent <SplineBase>(); child.Lines.outerLine.Update(); corePoly.AddChildAsHole(child.Lines.outerLine); } } } if (transitionPoly.IsInUse) { transitionPoly.Triangulate(); } if (extraPoly.IsInUse) { extraPoly.Triangulate(); } if (extraTransitionPoly.IsInUse) { extraTransitionPoly.Triangulate(); } if (shrinkPoly.IsInUse) { shrinkPoly.Triangulate(); } if (corePoly.IsInUse) { corePoly.Triangulate(); } needMeshRefresh = false; }
/// <summary> /// Update line data, fill the containers /// </summary> /// <param name="spline"></param> public void FormLines(SplineBase spline) { outerLine.Clear(); extraOuterLine.Clear(); extraInnerLine.Clear(); shrinkLine.Clear(); innerLine.Clear(); bool isHazard = spline.IsHazard; bool hasParent = spline.HasParent; SplineBase.SplinePattern pattern = spline.Pattern; Color outerColor = new Color(0, 0, 0, hasParent ? 1 : 0); Color extraInnerColor = new Color(1, 0, 0, 1); Color extraOuterColor = new Color(1, 0, 0, 1); Color shrinkColor = new Color(pattern.extra ? 0 : 1, 0, 0, spline.IsHole ? 0.01f : 1); Color innerColor = new Color(pattern.extra ? 0 : 1, 0, 0, spline.IsHole ? 0.01f : 1); float baseOffset = spline.Offset; Vector3[] points = editorLinesPoints; if (isHazard) { baseOffset += 0.01f; } for (int i = 0; i < points.Length - 1; ++i) { float offset = baseOffset; if (isHazard) { outerColor = editorLinesColors[i]; innerColor = editorLinesColors[i]; } Vector2 point = new Vector2(points[i].x, points[i].z); Vector2 normalVector = GetNormalAtIndex(points, i); Vector2 outerPoint2 = point + (pattern.transition ? (pattern.transitionLength * (isHazard ? 0.5f : 1.0f)) * normalVector : Vector2.zero); Vector2 extraOuterPoint2 = outerPoint2 - (pattern.extra ? (pattern.transition ? pattern.transitionLength * normalVector : Vector2.zero) : Vector2.zero); Vector2 extraInnerPoint2 = extraOuterPoint2 - (pattern.extra ? pattern.extraLength * normalVector : Vector2.zero); Vector2 shrinkPoint2 = extraInnerPoint2 - (pattern.extra ? (pattern.extraTransition ? pattern.extraTransitionLength * normalVector : Vector2.zero) : (pattern.transition ? pattern.transitionLength * normalVector : Vector2.zero)); Vector2 innerPoint2 = shrinkPoint2 - (pattern.shrink ? pattern.shrinkLength * normalVector : Vector2.zero); if (!isHazard && !hasParent) { offset *= 0.001f; } Vector3 outerPoint3 = GetPosition(outerPoint2, offset); if (!isHazard && !hasParent) { offset *= 1000; } if (pattern.transition) { offset += pattern.transitionDepth; } Vector3 extraOuterPoint3 = GetPosition(extraOuterPoint2, offset); if (pattern.extra) { offset += pattern.extraDepth; } Vector3 extraInnerPoint3 = GetPosition(extraInnerPoint2, offset); if (pattern.extra && pattern.extraTransition) { offset += pattern.extraTransitionDepth; } Vector3 shrinkPoint3 = GetPosition(shrinkPoint2, offset); if (pattern.shrink) { offset += pattern.shrinkDepth; } Vector3 innerPoint3 = GetPosition(innerPoint2, offset); outerLine.Add(outerPoint3, GetNormal(outerPoint3, Vector3.zero, Vector3.zero, outerPoint2), outerColor); if (pattern.extra) { extraOuterLine.Add(extraOuterPoint3, GetNormal(extraOuterPoint3, (pattern.transition ? outerPoint3 : Vector3.zero), extraInnerPoint3, extraOuterPoint2, spline.Layer.IsBunker), extraOuterColor); extraInnerLine.Add(extraInnerPoint3, GetNormal(extraInnerPoint3, extraOuterPoint3, (pattern.extraTransition ? (pattern.shrink ? shrinkPoint3 : innerPoint3) : Vector3.zero), extraInnerPoint2, spline.Layer.IsBunker), extraInnerColor); } if (pattern.shrink) { shrinkLine.Add(shrinkPoint3, GetNormal(shrinkPoint3, (pattern.extra && pattern.extraTransition ? extraInnerPoint3 : (pattern.transition ? outerPoint3 : Vector3.zero)), innerPoint3, shrinkPoint2), shrinkColor); } innerLine.Add(innerPoint3, GetNormal(innerPoint3, Vector3.zero, Vector3.zero, innerPoint2), innerColor); } }
/// <summary> /// Update the lines /// </summary> /// <param name="spline"></param> public void UpdateLines(SplineBase spline) { if (spline.IsSquare) { List <Vector3> temp = editorPoints.ToList(); temp.Add(temp[0]); editorLinesPoints = temp.ToArray(); } else { editorLinesPoints = editorPoints.CatmullRom(spline.Layer.pointsPerEdge, true).ToArray(); } if (spline.IsHazard) { editorLinesColors = new Color[editorLinesPoints.Length]; string[] colorNames = spline.Info.colorNames; editorColors = new Color[colorNames.Length]; for (int i = 0; i < colorNames.Length; ++i) { editorColors[i] = CourseBase.GetLayer(colorNames[i], CourseBase.HazardLayers).hazardColor; } int step = (int)(editorLinesPoints.Length / editorPoints.Length); int index = 0; int counter = 0; for (int i = 0; i < editorLinesPoints.Length; ++i) { try { editorLinesColors[i] = editorColors[index]; counter++; if (counter == step) { counter = 0; if (index != editorPoints.Length - 1) { index++; } } } catch (Exception e) { Debug.Log(editorColors.Length + "[" + index + "]"); Debug.LogException(e); } } } editorBoxesPoints = new Vector3[editorPoints.Length * 9]; for (int i = 0; i < editorPoints.Length; ++i) { editorBoxesPoints[i * 9 + 0].Set(editorPoints[i].x - Utility.squareHalf, editorPoints[i].y, editorPoints[i].z - Utility.squareHalf); editorBoxesPoints[i * 9 + 1].Set(editorPoints[i].x + Utility.squareHalf, editorPoints[i].y, editorPoints[i].z - Utility.squareHalf); editorBoxesPoints[i * 9 + 2].Set(editorPoints[i].x - Utility.squareHalf, editorPoints[i].y, editorPoints[i].z - Utility.squareHalf); editorBoxesPoints[i * 9 + 3].Set(editorPoints[i].x - Utility.squareHalf, editorPoints[i].y, editorPoints[i].z + Utility.squareHalf); editorBoxesPoints[i * 9 + 4].Set(editorPoints[i].x - Utility.squareHalf, editorPoints[i].y, editorPoints[i].z + Utility.squareHalf); editorBoxesPoints[i * 9 + 5].Set(editorPoints[i].x + Utility.squareHalf, editorPoints[i].y, editorPoints[i].z + Utility.squareHalf); editorBoxesPoints[i * 9 + 6].Set(editorPoints[i].x + Utility.squareHalf, editorPoints[i].y, editorPoints[i].z - Utility.squareHalf); editorBoxesPoints[i * 9 + 7].Set(editorPoints[i].x + Utility.squareHalf, editorPoints[i].y, editorPoints[i].z + Utility.squareHalf); editorBoxesPoints[i * 9 + 8].Set(0, float.PositiveInfinity, 0); } editorMin = editorLinesPoints[0]; editorMax = editorLinesPoints[0]; for (int i = 0; i < editorLinesPoints.Length; ++i) { if (editorLinesPoints[i].x < editorMin.x) { editorMin.x = editorLinesPoints[i].x; } if (editorLinesPoints[i].y < editorMin.y) { editorMin.y = editorLinesPoints[i].y; } if (editorLinesPoints[i].z < editorMin.z) { editorMin.z = editorLinesPoints[i].z; } if (editorLinesPoints[i].x > editorMax.x) { editorMax.x = editorLinesPoints[i].x; } if (editorLinesPoints[i].y > editorMax.y) { editorMax.y = editorLinesPoints[i].y; } if (editorLinesPoints[i].z > editorMax.z) { editorMax.z = editorLinesPoints[i].z; } } editorMin /= 1.01f; editorMax *= 1.01f; }
/// <summary> /// Update mesh from the line data /// </summary> /// <param name="spline"></param> public void UpdateMesh(SplineBase spline) { if (mesh) { MonoBehaviour.DestroyImmediate(mesh); mesh = null; } if (meshPhysics) { MonoBehaviour.DestroyImmediate(meshPhysics); meshPhysics = null; } if (meshFilter) { MonoBehaviour.DestroyImmediate(meshFilter); meshFilter = null; } if (meshCollider && meshCollider.material) { MonoBehaviour.DestroyImmediate(meshCollider.material); meshCollider.material = null; } if (meshCollider && meshCollider.sharedMaterial) { meshCollider.sharedMaterial = null; } if (meshCollider) { MonoBehaviour.DestroyImmediate(meshCollider); meshCollider = null; } if (spline.IsHazard) { return; } SplineBase.SplinePattern pattern = spline.Pattern; List <Vector3> vertices = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <Vector4> tangents = new List <Vector4>(); List <Color> colors = new List <Color>(); mesh = new Mesh(); mesh.Clear(); mesh.name = "Spline Mesh"; int submesh = 0; if (pattern.extra) { if (pattern.transition) { AddPoly(spline.Lines.TransitionPoly, mesh, submesh++, vertices, normals, tangents, colors); } AddPoly(spline.Lines.ExtraPoly, mesh, submesh++, vertices, normals, tangents, colors); if (pattern.extraTransition) { AddPoly(spline.Lines.ExtraTransitionPoly, mesh, submesh++, vertices, normals, tangents, colors); } } else { if (pattern.transition) { AddPoly(spline.Lines.TransitionPoly, mesh, submesh++, vertices, normals, tangents, colors); } } if (pattern.shrink) { AddPoly(spline.Lines.ShrinkPoly, mesh, submesh++, vertices, normals, tangents, colors); } AddPoly(spline.Lines.CorePoly, mesh, submesh++, vertices, normals, tangents, colors); meshFilter = spline.Transform.gameObject.AddComponent <MeshFilter>(); meshFilter.mesh = mesh; meshCollider = spline.Transform.gameObject.AddComponent <MeshCollider>(); meshCollider.sharedMesh = mesh; meshCollider.sharedMaterial = spline.Layer.PhysicsMaterial; }
/// <summary> /// Terrain hit at x,y /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public static RaycastHit?TerrainHit(float x, float y) { SplineBase insideSpline = null; List <SplineBase> splines = Splines; for (int i = 0; i < splines.Count; ++i) { SplineBase spline = splines[i]; if (spline.HasChilds) { continue; } if (spline is HazardBase) { continue; } if (!spline.InBounds(new Vector3(x, 0, y))) { continue; } if (new Vector2(x, y).IsInside(spline.Lines.Points)) { insideSpline = spline; break; } } if (insideSpline) { Ray ray = new Ray(new Vector3(x, 7777, y), -Vector3.up); RaycastHit hit; if (insideSpline.GetComponent <Collider>().Raycast(ray, out hit, 8888)) { return(hit); } } if (true) { Ray ray = new Ray(new Vector3(x, 7777, y), -Vector3.up); RaycastHit hit; if (Physics.Raycast(ray, out hit, 8888)) { while (!hit.transform.gameObject.name.Contains("Spline")) { ray = new Ray(new Vector3(x, hit.point.y - 0.01f, y), -Vector3.up); if (!Physics.Raycast(ray, out hit)) { break; } } return(hit); } Debug.DrawLine(ray.origin, ray.origin + ray.direction * 8888, Color.green, 60); if (Terrain.GetComponent <Collider>().Raycast(ray, out hit, 8888)) { return(hit); } } return(null); }
/// <summary> /// Update mesh material /// </summary> /// <param name="spline"></param> public void UpdateMaterial(SplineBase spline) { if (meshRenderer) { MonoBehaviour.DestroyImmediate(meshRenderer); meshRenderer = null; } if (meshRenderer && meshRenderer.sharedMaterials != null) { meshRenderer.sharedMaterials = null; } for (int i = 0; i < materials.Count; ++i) { MonoBehaviour.DestroyImmediate(materials[i]); materials[i] = null; } if (spline.IsHazard) { return; } SplineBase parent = null; if (spline.HasParent) { parent = spline.Parent; } Layer cLayer = spline.Layer; Layer eLayer = spline.Layer; Layer tLayer = spline.Layer; if (spline.Pattern.extra) { eLayer = spline.ExtraLayer; if (spline.HasParent) { tLayer = parent.Layer; } else { tLayer = eLayer; } } else { if (spline.HasParent) { tLayer = parent.Layer; } } materials.Clear(); SplineBase.SplinePattern pattern = spline.Pattern; if (pattern.extra) { if (pattern.transition) { AddMaterialTransition(materials, tLayer, eLayer); } AddMaterialCore(materials, eLayer); if (pattern.extraTransition) { AddMaterialTransition(materials, cLayer, eLayer); } } else { if (pattern.transition) { AddMaterialTransition(materials, tLayer, cLayer); } } if (pattern.shrink) { AddMaterialCore(materials, cLayer); } AddMaterialCore(materials, cLayer); meshRenderer = spline.Transform.gameObject.AddComponent <MeshRenderer>(); meshRenderer.sharedMaterials = materials.ToArray(); meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; needMaterialRefresh = false; }