void ShowDirection(IFerr2DTMaterial aMat, int aDir) { Ferr2DT_SegmentDescription desc = aMat.GetDescriptor((Ferr2DT_TerrainDirection)aDir); settingsScroll = EditorGUILayout.BeginScrollView(settingsScroll); EditorGUILayout.LabelField("Edge Placement", EditorStyles.boldLabel); EditorGUI.indentLevel = 1; desc.zOffset = EditorGUILayout.IntField("Draw Order", Mathf.RoundToInt(desc.zOffset * 1000)) / 1000f; desc.YOffsetPercent = EditorGUILayout.Slider("Y Offset", desc.YOffsetPercent, -.5f, .5f); desc.yOffset = EditorGUILayout.FloatField("[Legacy] Y Offset", desc.yOffset); desc.capOffset = EditorGUILayout.FloatField("[Legacy] Cap Offset", desc.capOffset); EditorGUI.indentLevel = 0; Ferr2DT_TerrainMaterialUtility.EditColliders(desc); EditorGUILayout.Space(); EditorGUILayout.LabelField("Edge Segments", EditorStyles.boldLabel); simpleUVs = EditorGUILayout.Toggle("Simple Mode", simpleUVs); if (simpleUVs) { Ferr2DT_TerrainMaterialUtility.EditUVsSimple(aMat, desc); } else { Ferr2DT_TerrainMaterialUtility.EditUVsComplex(aMat, desc, width, ref currBody); } EditorGUILayout.EndScrollView(); }
public Ferr2DT_Material CreateNewFormatMaterial() { Ferr2DT_Material result = ScriptableObject.CreateInstance <Ferr2DT_Material>(); result.edgeMaterial = _edgeMaterial; result.fillMaterial = _fillMaterial; for (int i = 0; i < 4; i += 1) { Ferr2DT_TerrainDirection dir = (Ferr2DT_TerrainDirection)i; if (!Has(dir)) { continue; } result.Set(dir, true); Ferr2DT_SegmentDescription dest = result.GetDescriptor(dir); Ferr2DT_SegmentDescription src = GetDescriptor(dir); dest.applyTo = src.applyTo; dest.body = src.body; dest.capOffset = src.capOffset; dest.innerLeftCap = src.innerLeftCap; dest.innerRightCap = src.innerRightCap; dest.leftCap = src.leftCap; dest.rightCap = src.rightCap; dest.yOffset = src.yOffset; dest.zOffset = src.zOffset; } return(result); }
public Ferr2DT_TerrainMaterial() { for (int i = 0; i < descriptors.Length; i++) { descriptors[i] = new Ferr2DT_SegmentDescription(); } }
private Rect LegacyGetRandomBodyRect(Vector2 aInitialPos, Ferr2DT_SegmentDescription aDesc) { #if UNITY_5_4_OR_NEWER UnityEngine.Random.State tSeed = default(UnityEngine.Random.State); #else int tSeed = 0; #endif if (randomByWorldCoordinates) { #if UNITY_5_4_OR_NEWER tSeed = UnityEngine.Random.state; UnityEngine.Random.InitState((int)(aInitialPos.x + aInitialPos.y)); #else tSeed = UnityEngine.Random.seed; UnityEngine.Random.seed = (int)(aInitialPos.x + aInitialPos.y); #endif } Rect body = TerrainMaterial.ToUV(aDesc.body[UnityEngine.Random.Range(0, aDesc.body.Length)]); if (randomByWorldCoordinates) { #if UNITY_5_4_OR_NEWER UnityEngine.Random.state = tSeed; #else UnityEngine.Random.seed = tSeed; #endif } return(body); }
public static void CreateAsset() { Ferr2DT_Material mat = (Ferr2DT_Material)Ferr.SOUtil.CreateAsset(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, editorMenuName); // top mat.Set(Ferr2DT_TerrainDirection.Top, true); Ferr2DT_SegmentDescription curr = mat._descriptors[0]; curr.SingleColliderCapType = Ferr2D_CapColliderType.Connected; // left mat.Set(Ferr2DT_TerrainDirection.Left, true); curr = mat._descriptors[1]; curr.ZOffset = 2f / 1000f; curr.SingleColliderCapType = Ferr2D_CapColliderType.Rectangle; // right mat.Set(Ferr2DT_TerrainDirection.Right, true); curr = mat._descriptors[2]; curr.ZOffset = 2f / 1000f; curr.SingleColliderCapType = Ferr2D_CapColliderType.Rectangle; // right mat.Set(Ferr2DT_TerrainDirection.Bottom, true); curr = mat._descriptors[3]; curr.ZOffset = 1f / 1000f; curr.SingleColliderCapType = Ferr2D_CapColliderType.Connected; }
private void AddSegment(List <Vector2> aSegment, bool aClosed, Ferr2DT_TerrainDirection aDir = Ferr2DT_TerrainDirection.None) { Ferr2DT_SegmentDescription desc = GetDescription(aSegment); if (aDir != Ferr2DT_TerrainDirection.None) { desc = terrainMaterial.GetDescriptor(aDir); } int bodyID = UnityEngine.Random.Range(0, desc.body.Length); Rect body = terrainMaterial.ToUV(desc.body[bodyID]); float bodyWidth = body.width * unitsPerUV.x; int tSeed = UnityEngine.Random.seed; Vector2 capLeftSlideDir = (aSegment[1] - aSegment[0]); Vector2 capRightSlideDir = (aSegment[aSegment.Count - 2] - aSegment[aSegment.Count - 1]); capLeftSlideDir.Normalize(); capRightSlideDir.Normalize(); aSegment[0] -= capLeftSlideDir * desc.capOffset; aSegment[aSegment.Count - 1] -= capRightSlideDir * desc.capOffset; for (int i = 0; i < aSegment.Count - 1; i++) { Vector2 norm1 = Vector2.zero; Vector2 norm2 = Vector2.zero; float length = Vector2.Distance(aSegment[i + 1], aSegment[i]); int repeats = Mathf.Max(1, Mathf.FloorToInt(length / bodyWidth + stretchThreshold)); norm1 = Ferr2D_Path.GetNormal(aSegment, i, aClosed); norm2 = Ferr2D_Path.GetNormal(aSegment, i + 1, aClosed); for (int t = 1; t < repeats + 1; t++) { UnityEngine.Random.seed = (int)(transform.position.x * 100000 + transform.position.y * 10000 + i * 100 + t); body = terrainMaterial.ToUV(desc.body[UnityEngine.Random.Range(0, desc.body.Length)]); Vector2 pos1, pos2, n1, n2; pos1 = Vector2.Lerp(aSegment[i], aSegment[i + 1], (float)(t - 1) / repeats); pos2 = Vector2.Lerp(aSegment[i], aSegment[i + 1], (float)t / repeats); n1 = Vector2.Lerp(norm1, norm2, (float)(t - 1) / repeats); n2 = Vector2.Lerp(norm1, norm2, (float)t / repeats); float d = (body.height / 2) * unitsPerUV.y; float yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -desc.yOffset : desc.yOffset; int v1 = dMesh.AddVertex(pos1.x + n1.x * (d + yOff), pos1.y + n1.y * (d + yOff), desc.zOffset, body.x, fill == Ferr2DT_FillMode.InvertedClosed ? body.yMax : body.y); int v2 = dMesh.AddVertex(pos1.x - n1.x * (d - yOff), pos1.y - n1.y * (d - yOff), desc.zOffset, body.x, fill == Ferr2DT_FillMode.InvertedClosed ? body.y : body.yMax); int v3 = dMesh.AddVertex(pos2.x + n2.x * (d + yOff), pos2.y + n2.y * (d + yOff), desc.zOffset, body.xMax, fill == Ferr2DT_FillMode.InvertedClosed ? body.yMax : body.y); int v4 = dMesh.AddVertex(pos2.x - n2.x * (d - yOff), pos2.y - n2.y * (d - yOff), desc.zOffset, body.xMax, fill == Ferr2DT_FillMode.InvertedClosed ? body.y : body.yMax); dMesh.AddFace(v1, v3, v4, v2); } } if (!aClosed) { AddCap(aSegment, desc, -1); AddCap(aSegment, desc, 1); } UnityEngine.Random.seed = tSeed; }
public void Add() { Array.Resize(ref descriptors, descriptors.Length + 1); var newSegment = new Ferr2DT_SegmentDescription(); newSegment.applyTo = (Ferr2DT_TerrainDirection)descriptors.Length - 1; descriptors[descriptors.Length - 1] = newSegment; }
public static void EditUVsComplex(Ferr2DT_TerrainMaterial aMat, Ferr2DT_SegmentDescription desc, float aWidth, ref int aCurrBody) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Body", GUILayout.Width(40f)); int bodyID = Mathf.Clamp(aCurrBody, 0, desc.body.Length); if (GUILayout.Button("<", GUILayout.Width(20f))) aCurrBody = Mathf.Clamp(aCurrBody - 1, 0, desc.body.Length - 1); EditorGUILayout.LabelField("" + (bodyID + 1), GUILayout.Width(12f)); if (GUILayout.Button(">", GUILayout.Width(20f))) aCurrBody = Mathf.Clamp(aCurrBody + 1, 0, desc.body.Length - 1); bodyID = Mathf.Clamp(aCurrBody, 0, desc.body.Length - 1); int length = Math.Max(1, EditorGUILayout.IntField(desc.body.Length, GUILayout.Width(32f))); EditorGUILayout.LabelField("Total", GUILayout.Width(40f)); if (length != desc.body.Length) Array.Resize<Rect>(ref desc.body, length); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); desc.body[bodyID] = AtlasField(aMat, desc.body[bodyID], aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture); if (desc.leftCap.width == 0 && desc.leftCap.height == 0) { if (EditorGUILayout.Toggle("Left Cap", false)) { desc.leftCap = new Rect(0, 0, 30, 30); } } else { if (EditorGUILayout.Toggle("Left Cap", true)) { desc.leftCap = AtlasField(aMat, desc.leftCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture); } else { desc.leftCap = new Rect(0, 0, 0, 0); } } if (desc.rightCap.width == 0 && desc.rightCap.height == 0) { if (EditorGUILayout.Toggle("Right Cap", false)) { desc.rightCap = new Rect(0, 0, 30, 30); } } else { if (EditorGUILayout.Toggle("Right Cap", true)) { desc.rightCap = AtlasField(aMat, desc.rightCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture); } else { desc.rightCap = new Rect(0, 0, 0, 0); } } }
/// <summary> /// Creates a TerrainMaterial from a JSON object, does -not- link edgeMaterial or fillMaterial, you'll have to do that yourself! /// </summary> /// <param name="aJSON">A parsed JSON value</param> public void FromJSON(Ferr_JSONValue aJSON) { Ferr_JSONValue descArr = aJSON["descriptors"]; for (int i = 0; i < descArr.Length; i++) { descriptors[i] = new Ferr2DT_SegmentDescription(); descriptors[i].FromJSON(descArr[i]); } }
public static void EditColliders(Ferr2DT_SegmentDescription desc) { EditorGUILayout.LabelField("Colliders", EditorStyles.boldLabel); EditorGUI.indentLevel = 1; desc.ColliderOffset = EditorGUILayout.Slider("Vertical Offset", desc.ColliderOffset, -1, 1); desc.ColliderThickness = EditorGUILayout.Slider("Thickness", desc.ColliderThickness, 0, 2); desc.PhysicsMaterial2D = (PhysicsMaterial2D)EditorGUILayout.ObjectField("Physics Material 2D", desc.PhysicsMaterial2D, typeof(PhysicsMaterial2D), false); desc.PhysicsMaterial3D = (PhysicMaterial )EditorGUILayout.ObjectField("Physics Material 3D", desc.PhysicsMaterial3D, typeof(PhysicMaterial), false); EditorGUI.indentLevel = 0; }
public static void EditUVsSimple(Ferr2DT_TerrainMaterial aMat, Ferr2DT_SegmentDescription desc) { Rect cap = aMat.ToPixels(desc.leftCap); Rect body = aMat.ToPixels(desc.body[0]); float height = body.height; float capWidth = cap.width; float bodyWidth = body.width; int bodyCount = desc.body.Length; Vector2 pos = new Vector2(cap.x, cap.y); if (cap.width == 0 && cap.height == 0) { pos = new Vector2(body.x, body.y); } pos = EditorGUILayout.Vector2Field("Position", pos); height = EditorGUILayout.FloatField("Height", height); capWidth = EditorGUILayout.FloatField("Cap Width", capWidth); bodyWidth = EditorGUILayout.FloatField("Body Width", bodyWidth); bodyCount = Mathf.Max(1, EditorGUILayout.IntField("Body slices", bodyCount)); if (bodyCount != desc.body.Length) { Array.Resize <Rect>(ref desc.body, bodyCount); } float currX = pos.x; desc.leftCap.x = currX; desc.leftCap.y = pos.y; desc.leftCap.width = capWidth; desc.leftCap.height = capWidth == 0 ? 0 : height; desc.leftCap = aMat.ToNative(desc.leftCap); currX += capWidth; for (int i = 0; i < desc.body.Length; i++) { desc.body[i].x = currX; desc.body[i].y = pos.y; desc.body[i].width = bodyWidth; desc.body[i].height = height; desc.body[i] = aMat.ToNative(desc.body[i]); currX += bodyWidth; } desc.rightCap.x = currX; desc.rightCap.y = pos.y; desc.rightCap.width = capWidth; desc.rightCap.height = capWidth == 0 ? 0 : height; desc.rightCap = aMat.ToNative(desc.rightCap); }
public static float MaxHeight(Ferr2DT_SegmentDescription aDesc) { float sourceHeight = Mathf.Max(aDesc.leftCap.height, aDesc.rightCap.height); float max = 0; for (int i = 0; i < aDesc.body.Length; i++) { if (aDesc.body[i].height > max) { max = aDesc.body[i].height; } } return(Mathf.Max(max, sourceHeight)); }
private void LegacyCreateBody(Ferr2DT_SegmentDescription aDesc, List <Vector2> aSegment, List <float> aSegmentScale, List <CutOverrides> aCutOverrides, float aBodyWidth, int aTextureSlices, bool aClosed) { float distance = Ferr2D_Path.GetSegmentLength(aSegment); int textureCuts = Mathf.Max(1, Mathf.FloorToInt(distance / aBodyWidth + 0.5f)); Ferr2D_DynamicMesh mesh = DMesh; Rect body = LegacyPickBody(aDesc, aCutOverrides, aSegment[0], 0, 0); float d = (body.height / 2) * unitsPerUV.y; float yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset; int p1 = 0, p2 = 0, p3 = 0; int pIndex = 0; int cutIndex = 0; // loop for each instance of the texture for (int t = 0; t < textureCuts; t++) { float texPercent = (t / (float)(textureCuts)); float texPercentStep = (1f / (float)(textureCuts)); // slice each texture chunk a number of times for (int i = 0; i < aTextureSlices; i++) { float slicePercent = (i / (float)(aTextureSlices - 1)); float totalPercent = texPercent + slicePercent * texPercentStep; int ptLocal = 0; float pctLocal = 0; Ferr2D_Path.PathGlobalPercentToLocal(aSegment, totalPercent, out ptLocal, out pctLocal, distance, aClosed); // if we skip over path points, we need to add slices at each path point to prevent the mesh from bypassing it. for (int extra = 0; extra < ptLocal - pIndex; extra++) { float traveledDist = Ferr2D_Path.GetSegmentLengthToIndex(aSegment, pIndex + extra + 1); float v = (traveledDist / distance) * textureCuts; v = v - (int)v; LegacyAddVertexColumn(aDesc, aSegment, aSegmentScale, aClosed, mesh, body, d, yOff, i != 0, v, pIndex + extra + 1, 0, ref p1, ref p2, ref p3); cutIndex = -1; } pIndex = ptLocal; LegacyAddVertexColumn(aDesc, aSegment, aSegmentScale, aClosed, mesh, body, d, yOff, i != 0, slicePercent, ptLocal, pctLocal, ref p1, ref p2, ref p3); } cutIndex += 1; body = LegacyPickBody(aDesc, aCutOverrides, mesh.GetVert(p2), pIndex, cutIndex); } }
/// <summary> /// Sets a particular direction as having a valid descriptor. Or not. That's a bool. /// </summary> /// <param name="aDirection">The direction!</param> /// <param name="aActive">To active, or not to active? That is the question!</param> public void Set(Ferr2DT_TerrainDirection aDirection, bool aActive) { if (aActive) { if (descriptors[(int)aDirection].applyTo != aDirection) { descriptors[(int)aDirection] = new Ferr2DT_SegmentDescription(); descriptors[(int)aDirection].applyTo = aDirection; } } else if (descriptors[(int)aDirection].applyTo != Ferr2DT_TerrainDirection.Top) { descriptors[(int)aDirection] = new Ferr2DT_SegmentDescription(); } }
private float TexDistAtSegment(Ferr2DT_PathTerrain.EdgeSegment aSegment, Ferr2DT_SegmentDescription edgeData, List <int> aTexSegments, int aSegmentId) { float currLength = 0; for (int i = 0; i < aTexSegments.Count && i <= aSegmentId; i++) { float segLength = terrain.TerrainMaterial.ToUV(edgeData.GetBody(aTexSegments[i])).width *terrain.UnitsPerUV.x; if (i == aSegmentId) { return(currLength + segLength / 2); } currLength += terrain.TerrainMaterial.ToUV(edgeData.GetBody(aTexSegments[i])).width *terrain.UnitsPerUV.x; } return(-1); }
private void AddCap(List <Vector2> aSegment, Ferr2DT_SegmentDescription aDesc, float aDir) { int index = 0; Vector2 dir = Vector2.zero; if (aDir < 0) { index = 0; dir = aSegment[0] - aSegment[1]; } else { index = aSegment.Count - 1; dir = aSegment[aSegment.Count - 1] - aSegment[aSegment.Count - 2]; } dir.Normalize(); Vector2 norm = Ferr2D_Path.GetNormal(aSegment, index, false); Vector2 pos = aSegment[index]; Rect lCap = fill == Ferr2DT_FillMode.InvertedClosed ? terrainMaterial.ToUV(aDesc.rightCap) : terrainMaterial.ToUV(aDesc.leftCap); Rect rCap = fill == Ferr2DT_FillMode.InvertedClosed ? terrainMaterial.ToUV(aDesc.leftCap) : terrainMaterial.ToUV(aDesc.rightCap); float yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset; if (aDir < 0) { float width = lCap.width * unitsPerUV.x; float scale = (lCap.height / 2) * unitsPerUV.y; int v1 = dMesh.AddVertex(pos + dir * width + norm * (scale + yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed? lCap.xMax : lCap.x, fill == Ferr2DT_FillMode.InvertedClosed ? lCap.yMax : lCap.y)); int v2 = dMesh.AddVertex(pos + norm * (scale + yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? lCap.x : lCap.xMax, fill == Ferr2DT_FillMode.InvertedClosed ? lCap.yMax : lCap.y)); int v3 = dMesh.AddVertex(pos - norm * (scale - yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? lCap.x : lCap.xMax, fill == Ferr2DT_FillMode.InvertedClosed ? lCap.y : lCap.yMax)); int v4 = dMesh.AddVertex(pos + dir * width - norm * (scale - yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? lCap.xMax : lCap.x, fill == Ferr2DT_FillMode.InvertedClosed ? lCap.y : lCap.yMax)); dMesh.AddFace(v1, v2, v3, v4); } else { float width = rCap.width * unitsPerUV.x; float scale = (rCap.height / 2) * unitsPerUV.y; int v1 = dMesh.AddVertex(pos + dir * width + norm * (scale + yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? rCap.x : rCap.xMax, fill == Ferr2DT_FillMode.InvertedClosed ? rCap.yMax : rCap.y)); int v2 = dMesh.AddVertex(pos + norm * (scale + yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? rCap.xMax : rCap.x, fill == Ferr2DT_FillMode.InvertedClosed ? rCap.yMax : rCap.y)); int v3 = dMesh.AddVertex(pos - norm * (scale - yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? rCap.xMax : rCap.x, fill == Ferr2DT_FillMode.InvertedClosed ? rCap.y : rCap.yMax)); int v4 = dMesh.AddVertex(pos + dir * width - norm * (scale - yOff), aDesc.zOffset, new Vector2(fill == Ferr2DT_FillMode.InvertedClosed ? rCap.x : rCap.xMax, fill == Ferr2DT_FillMode.InvertedClosed ? rCap.y : rCap.yMax)); dMesh.AddFace(v4, v3, v2, v1); } }
void ShowDirection(Ferr2DT_TerrainMaterial aMat, Ferr2DT_TerrainDirection aDir) { Ferr2DT_SegmentDescription desc = aMat.GetDescriptor(aDir); desc.zOffset = EditorGUILayout.FloatField("Z Offset", desc.zOffset); desc.yOffset = EditorGUILayout.FloatField("Y Offset", desc.yOffset); desc.capOffset = EditorGUILayout.FloatField("Cap Offset", desc.capOffset); simpleUVs = EditorGUILayout.Toggle("Simple", simpleUVs); if (simpleUVs) { Ferr2DT_TerrainMaterialUtility.EditUVsSimple(aMat, desc); } else { Ferr2DT_TerrainMaterialUtility.EditUVsComplex(aMat, desc, width, ref currBody); } }
public static bool IsSimple(Ferr2DT_SegmentDescription aDesc) { float height = aDesc.leftCap.height; bool noCaps = aDesc.leftCap.width == 0 && aDesc.rightCap.width == 0; bool heightSame = noCaps ? aDesc.body[0].height == aDesc.body[aDesc.body.Length - 1].height : aDesc.rightCap.height == height && aDesc.body[0].height == height; bool capSame = aDesc.leftCap.width == aDesc.rightCap.width; bool ySame = noCaps ? aDesc.body[0].y == aDesc.body[aDesc.body.Length - 1].y : aDesc.leftCap.y == aDesc.rightCap.y && aDesc.leftCap.y == aDesc.body[0].y && aDesc.leftCap.y == aDesc.body[aDesc.body.Length - 1].y; bool xSpaced = noCaps ? (aDesc.body[0].x - aDesc.body[aDesc.body.Length - 1].x) % aDesc.body[0].width == 0: aDesc.leftCap.xMax == aDesc.body[0].x && aDesc.rightCap.x == aDesc.body[aDesc.body.Length - 1].xMax; return(heightSame && capSame && ySame && xSpaced); }
public static bool IsSimple(Ferr2DT_SegmentDescription aDesc) { float y = aDesc.body[0].y; bool hasCaps = aDesc.leftCap.width != 0 || aDesc.rightCap.width != 0; float height = aDesc.body[0].height; if (hasCaps && (aDesc.leftCap.y != y || aDesc.rightCap.y != y)) { return(false); } if (hasCaps && aDesc.leftCap.xMax != aDesc.body[0].x) { return(false); } if (hasCaps && aDesc.rightCap.x != aDesc.body[aDesc.body.Length - 1].xMax) { return(false); } if (hasCaps && (aDesc.leftCap.height != height || aDesc.rightCap.height != height)) { return(false); } for (int i = 0; i < aDesc.body.Length; i++) { if (aDesc.body[i].y != aDesc.leftCap.y) { return(false); } if (aDesc.body[i].height != height) { return(false); } if (i + 1 < aDesc.body.Length && aDesc.body[i].xMax != aDesc.body[i + 1].x) { return(false); } } return(true); }
private Rect LegacyPickBody(Ferr2DT_SegmentDescription aDesc, List <CutOverrides> aCutOverrides, Vector2 aStartPos, int aCurrIndex, int aCurrCut) { int cutOverride = -1; Rect result = default(Rect); if (aCutOverrides[aCurrIndex].data != null && aCurrCut < aCutOverrides[aCurrIndex].data.Count) { cutOverride = aCutOverrides[aCurrIndex].data[aCurrCut] - 1; } if (cutOverride == -1 || cutOverride >= aDesc.body.Length) { result = LegacyGetRandomBodyRect(aStartPos, aDesc); } else { // trigger this so a random number is consumed LegacyGetRandomBodyRect(aStartPos, aDesc); result = TerrainMaterial.ToUV(aDesc.body[cutOverride]); } return(result); }
public static void ShowSample(IFerr2DTMaterial aMat, Ferr2DT_TerrainDirection aDir, float aWidth) { if (aMat.edgeMaterial == null || aMat.edgeMaterial.mainTexture == null) { return; } Ferr2DT_SegmentDescription desc = aMat.GetDescriptor(aDir); float totalWidth = desc.leftCap.width + desc.rightCap.width + (Mathf.Max(0, desc.body[0].width) * 3); float sourceHeight = MaxHeight(desc); Texture tex = aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture; float scale = Mathf.Min(aWidth / totalWidth, 64 / sourceHeight); float aspect = tex.height / tex.width; GUILayout.Space(sourceHeight * scale * aspect); float x = GUILayoutUtility.GetLastRect().x; float y = GUILayoutUtility.GetLastRect().y; if (desc.leftCap.width != 0) { float yOff = ((sourceHeight - desc.leftCap.height) / 2) * scale; GUI.DrawTextureWithTexCoords(new Rect(x, y + yOff, desc.leftCap.width * scale, desc.leftCap.height * scale * aspect), tex, aMat.ToUV(desc.leftCap)); x += desc.leftCap.width * scale; } for (int i = 0; i < 3; i++) { int id = (2 - i) % desc.body.Length; float yOff = ((sourceHeight - desc.body[id].height) / 2) * scale; GUI.DrawTextureWithTexCoords(new Rect(x, y + yOff, desc.body[id].width * scale, desc.body[id].height * scale * aspect), tex, aMat.ToUV(desc.body[id])); x += desc.body[id].width * scale; } if (desc.leftCap.width != 0) { float yOff = ((sourceHeight - desc.rightCap.height) / 2) * scale; GUI.DrawTextureWithTexCoords(new Rect(x, y + yOff, desc.rightCap.width * scale, desc.rightCap.height * scale * aspect), tex, aMat.ToUV(desc.rightCap)); } }
private void LegacyAddVertexColumn(Ferr2DT_SegmentDescription aDesc, List <Vector2> aSegment, List <float> aSegmentScale, bool aClosed, Ferr2D_DynamicMesh mesh, Rect body, float d, float yOff, bool aConnectFace, float slicePercent, int ptLocal, float pctLocal, ref int p1, ref int p2, ref int p3) { Vector2 pos1 = smoothPath ? Ferr2D_Path.HermiteGetPt(aSegment, ptLocal, pctLocal, aClosed) : Ferr2D_Path.LinearGetPt(aSegment, ptLocal, pctLocal, aClosed); Vector2 n1 = smoothPath ? Ferr2D_Path.HermiteGetNormal(aSegment, ptLocal, pctLocal, aClosed) : Ferr2D_Path.LinearGetNormal(aSegment, ptLocal, pctLocal, aClosed); float s = aClosed ? Mathf.Lerp(aSegmentScale[ptLocal], aSegmentScale[(ptLocal + 1) % aSegmentScale.Count], pctLocal) : Mathf.Lerp(aSegmentScale[ptLocal], aSegmentScale[Mathf.Min(ptLocal + 1, aSegmentScale.Count - 1)], pctLocal); // this compensates for scale distortion when corners are very sharp, but the normals are not long enough to keep the edge the appropriate width // not actually a problem for smooth paths if (!smoothPath) { n1.Normalize(); float rootScale = 1f / Mathf.Abs(Mathf.Cos(Vector2.Angle(Ferr2D_Path.GetSegmentNormal(ptLocal, aSegment, aClosed), n1) * Mathf.Deg2Rad)); s = s * rootScale; } int v1 = mesh.AddVertex(pos1.x + n1.x * (d * s + yOff), pos1.y + n1.y * (d * s + yOff), -slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, slicePercent), fill == Ferr2DT_FillMode.InvertedClosed ? body.yMax : body.y); int v2 = mesh.AddVertex(pos1.x - n1.x * (d * s - yOff), pos1.y - n1.y * (d * s - yOff), slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, slicePercent), fill == Ferr2DT_FillMode.InvertedClosed ? body.y : body.yMax); int v3 = splitMiddle ? mesh.AddVertex(pos1.x + n1.x * yOff, pos1.y + n1.y * yOff, aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, slicePercent), Mathf.Lerp(body.y, body.yMax, 0.5f)) : -1; if (aConnectFace) { if (!splitMiddle) { mesh.AddFace(v2, p2, p1, v1); } else { mesh.AddFace(v2, p2, p3, v3); mesh.AddFace(v3, p3, p1, v1); } } p1 = v1; p2 = v2; p3 = v3; }
public static float MaxHeight(Ferr2DT_SegmentDescription aDesc) { float sourceHeight = Mathf.Max( aDesc.leftCap.height, aDesc.rightCap.height ); float max = 0; for (int i = 0; i < aDesc.body.Length; i++) { if (aDesc.body[i].height > max) max = aDesc.body[i].height; } return Mathf.Max(max, sourceHeight); }
public static void EditUVsSimple(Ferr2DT_SegmentDescription desc) { float height = MaxHeight(desc); float capWidth = Mathf.Max(desc.leftCap.width, desc.rightCap.width); float bodyWidth = desc.body[0].width; int bodyCount = desc.body.Length; Vector2 pos = new Vector2(desc.leftCap.x, desc.leftCap.y); if (desc.leftCap.width == 0 && desc.leftCap.height == 0) pos = new Vector2(desc.body[0].x, desc.body[0].y); pos = EditorGUILayout.Vector2Field("Position", pos ); height = EditorGUILayout.FloatField ("Height", height ); capWidth = EditorGUILayout.FloatField ("Cap Width", capWidth ); bodyWidth = EditorGUILayout.FloatField ("Body Width", bodyWidth); bodyCount = Mathf.Max(1, EditorGUILayout.IntField ("Body slices", bodyCount)); if (bodyCount != desc.body.Length) { Array.Resize<Rect>(ref desc.body, bodyCount); } float currX = pos.x; desc.leftCap.x = currX; desc.leftCap.y = pos.y; desc.leftCap.width = capWidth; desc.leftCap.height = capWidth == 0 ? 0 : height; currX += capWidth; for (int i = 0; i < desc.body.Length; i++) { desc.body[i].x = currX; desc.body[i].y = pos.y; desc.body[i].width = bodyWidth; desc.body[i].height = height; currX += bodyWidth; } desc.rightCap.x = currX; desc.rightCap.y = pos.y; desc.rightCap.width = capWidth; desc.rightCap.height = capWidth == 0 ? 0 : height; }
public static bool IsSimple(Ferr2DT_SegmentDescription aDesc) { float height = aDesc.leftCap.height; bool noCaps = aDesc.leftCap.width == 0 && aDesc.rightCap.width == 0; bool heightSame = noCaps ? aDesc.body[0] .height == aDesc.body[aDesc.body.Length-1].height : aDesc.rightCap.height == height && aDesc.body[0].height == height; bool capSame = aDesc.leftCap.width == aDesc.rightCap.width; bool ySame = noCaps ? aDesc.body[0].y == aDesc.body[aDesc.body.Length-1].y : aDesc.leftCap.y == aDesc.rightCap.y && aDesc.leftCap.y == aDesc.body[0].y && aDesc.leftCap.y == aDesc.body[aDesc.body.Length-1].y; bool xSpaced = noCaps ? (aDesc.body[0].x - aDesc.body[aDesc.body.Length-1].x) % aDesc.body[0].width == 0: aDesc.leftCap.xMax == aDesc.body[0].x && aDesc.rightCap.x == aDesc.body[aDesc.body.Length-1].xMax; return heightSame && capSame && ySame && xSpaced; }
private void DoCutOverrideModeHandles(Ferr2D_Path path, Ferr2DT_PathTerrain terrain, Matrix4x4 mat, Transform camTransform) { List <List <int> > segments = new List <List <int> >(); List <Ferr2DT_TerrainDirection> dirs = new List <Ferr2DT_TerrainDirection>(); List <Vector2> rawVerts = path.GetVertsRaw(); // cut the terrain into segments, we need segment info to draw these points segments = terrain.GetSegments(rawVerts, out dirs); for (int s = 0; s < segments.Count; s++) { List <int> currSeg = segments[s]; List <Vector2> currVerts = Ferr2D_Path.IndicesToList(rawVerts, currSeg); List <Ferr2DT_PathTerrain.CutOverrides> overrides = Ferr2D_Path.IndicesToList(terrain.cutOverrides, currSeg); // find information about this segment Ferr2DT_TerrainDirection currDir = dirs[s]; Ferr2DT_SegmentDescription desc = default(Ferr2DT_SegmentDescription); if (currDir != Ferr2DT_TerrainDirection.None) { desc = terrain.TerrainMaterial.GetDescriptor(currDir); } else { desc = terrain.GetDescription(currSeg); } // if there's no body segment choices, don't bother with the rest of this if (desc.body.Length < 2) { continue; } Vector2 capLeftSlideDir = (currVerts[1] - currVerts[0]); Vector2 capRightSlideDir = (currVerts[currVerts.Count - 2] - currVerts[currVerts.Count - 1]); capLeftSlideDir.Normalize(); capRightSlideDir.Normalize(); currVerts[0] -= capLeftSlideDir * desc.capOffset; currVerts[currVerts.Count - 1] -= capRightSlideDir * desc.capOffset; float distance = Ferr2D_Path.GetSegmentLength(currVerts); // how many texture cuts are there on the segment float bodyWidth = desc.body[0].width * (terrain.TerrainMaterial.edgeMaterial.mainTexture.width / terrain.pixelsPerUnit); int textureCuts = Mathf.Max(1, Mathf.FloorToInt(distance / bodyWidth + 0.5f)); // data is attached to the points still, check if we've switched to a new point int activePt = -1; int activeLocalCut = -1; for (int c = 0; c < textureCuts; c++) { float pctGlobal = c / (float)textureCuts; int ptLocal = 0; float pctLocal = 0; Ferr2D_Path.PathGlobalPercentToLocal(currVerts, pctGlobal, out ptLocal, out pctLocal, distance, false); if (ptLocal != activePt) { // if they size down, we need to shorten the data too if (activePt != -1) { CapListSize <int>(ref overrides[activePt].data, activeLocalCut + 3); } activePt = ptLocal; activeLocalCut = 0; if (overrides[activePt].data == null) { overrides[activePt].data = new List <int>(); } } while (activeLocalCut >= overrides[activePt].data.Count) { overrides[activePt].data.Add(0); } CapFunction cap = CapDotAuto; int activeOverride = overrides[activePt].data[activeLocalCut]; if (activeOverride != 0) { if (activeOverride == 1) { cap = CapDot1; } else if (activeOverride == 2) { cap = CapDot2; } else if (activeOverride == 3) { cap = CapDot3; } else if (activeOverride == 4) { cap = CapDot4; } else if (activeOverride == 5) { cap = CapDot5; } else if (activeOverride >= 6) { cap = CapDotN; } } if (Event.current.alt) { cap = CapDotReset; } int ptShow = 0; float pctShow = 0; Ferr2D_Path.PathGlobalPercentToLocal(currVerts, pctGlobal + (1f / textureCuts) * 0.5f, out ptShow, out pctShow, distance, false); Vector2 pt = Ferr2D_Path.LinearGetPt(currVerts, ptShow, pctShow, false); Vector3 pos = mat.MultiplyPoint3x4(pt); float sc = HandleScale(pos) * 0.5f; if (Handles.Button(pos, camTransform.rotation, sc, sc, cap)) { Undo.RecordObject(terrain, "Lock Texture Segment"); overrides[activePt].data[activeLocalCut] = Event.current.alt ? 0 : (activeOverride + 1) % (desc.body.Length + 1); EditorUtility.SetDirty(terrain); GUI.changed = true; } activeLocalCut += 1; } if (activePt != -1) { CapListSize <int>(ref overrides[activePt].data, activeLocalCut + 3); } } }
public static void EditUVsSimple(IFerr2DTMaterial aMat, Ferr2DT_SegmentDescription desc) { Rect cap = aMat.ToPixels(desc.leftCap); Rect body = aMat.ToPixels(desc.body[0]); float height = body.height; float capWidth = cap.width; float bodyWidth = body.width; int bodyCount = desc.body.Length; Vector2 pos = new Vector2(cap.x, cap.y); if (cap.width == 0 && cap.height == 0) { pos = new Vector2(body.x, body.y); } Ferr.EditorTools.Box(2, () => { pos = EditorGUILayout.Vector2Field("Position", pos); height = EditorGUILayout.FloatField("Height", height); capWidth = EditorGUILayout.FloatField("Cap Width", capWidth); desc.SingleColliderCapOffset = EditorGUILayout.Slider("Cap Offset", desc.SingleColliderCapOffset, -1, 1); bodyWidth = Mathf.Max(1, EditorGUILayout.FloatField("Body Width", bodyWidth)); bodyCount = Mathf.Max(1, EditorGUILayout.IntField("Body slices", bodyCount)); EditorGUILayout.Space(); EditorGUILayout.LabelField("Colliders", EditorStyles.boldLabel); desc.SingleColliderCapType = (Ferr2D_CapColliderType)EditorGUILayout.EnumPopup("Collider Type", desc.SingleColliderCapType); desc.SingleColliderCapSize = EditorGUILayout.Slider("Collider Size", desc.SingleColliderCapSize, -1, 2); if (bodyCount != desc.body.Length) { Rect[] bodies = desc.body; Array.Resize <Rect>(ref bodies, bodyCount); desc.body = bodies; } float currX = pos.x; Rect leftCap = desc.leftCap; leftCap.x = currX; leftCap.y = pos.y; leftCap.width = capWidth; leftCap.height = capWidth == 0 ? 0 : height; desc.leftCap = aMat.ToNative(leftCap); currX += capWidth; for (int i = 0; i < desc.body.Length; i++) { desc.body[i].x = currX; desc.body[i].y = pos.y; desc.body[i].width = bodyWidth; desc.body[i].height = height; desc.body[i] = aMat.ToNative(desc.body[i]); currX += bodyWidth; } Rect rightCap = desc.rightCap; rightCap.x = currX; rightCap.y = pos.y; rightCap.width = capWidth; rightCap.height = capWidth == 0 ? 0 : height; desc.rightCap = aMat.ToNative(rightCap); }); }
private void AddCap (List<Vector2> aSegment, Ferr2DT_SegmentDescription aDesc, bool aInner, float aDir, float aScale, bool aSmooth) { int index = 0; Vector2 dir = Vector2.zero; if (aDir < 0) { index = 0; dir = aSegment[0] - aSegment[1]; } else { index = aSegment.Count-1; dir = aSegment[aSegment.Count-1] - aSegment[aSegment.Count-2]; } dir.Normalize(); Vector2 norm = aSmooth ? Ferr2D_Path.HermiteGetNormal(aSegment, index, 0, false): Ferr2D_Path.GetNormal(aSegment, index, false); Vector2 pos = aSegment[index]; float yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset; Rect cap; if (aDir < 0) { if (fill == Ferr2DT_FillMode.InvertedClosed) cap = (!aInner && aDesc.innerRightCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerRightCap) : terrainMaterial.ToUV(aDesc.rightCap); else cap = ( aInner && aDesc.innerLeftCap .width > 0) ? terrainMaterial.ToUV(aDesc.innerLeftCap ) : terrainMaterial.ToUV(aDesc.leftCap ); } else { if (fill == Ferr2DT_FillMode.InvertedClosed) cap = (!aInner && aDesc.innerLeftCap .width > 0) ? terrainMaterial.ToUV(aDesc.innerLeftCap ) : terrainMaterial.ToUV(aDesc.leftCap ); else cap = ( aInner && aDesc.innerRightCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerRightCap) : terrainMaterial.ToUV(aDesc.rightCap); } float width = cap.width * unitsPerUV.x; float scale = (cap.height/2) * unitsPerUV.y * aScale; float minU = fill == Ferr2DT_FillMode.InvertedClosed ? cap.xMax : cap.x; float maxU = fill == Ferr2DT_FillMode.InvertedClosed ? cap.x : cap.xMax; float minV = fill == Ferr2DT_FillMode.InvertedClosed ? cap.yMax : cap.y; float maxV = fill == Ferr2DT_FillMode.InvertedClosed ? cap.y : cap.yMax; if (aDir >= 0) { float t = minU; minU = maxU; maxU = t; } int v1 = DMesh.AddVertex(pos + dir * width + norm * (scale + yOff), -slantAmount + aDesc.zOffset, new Vector2(minU, minV)); int v2 = DMesh.AddVertex(pos + norm * (scale + yOff), -slantAmount + aDesc.zOffset, new Vector2(maxU, minV)); int v15 = splitMiddle ? DMesh.AddVertex(pos + dir * width + (norm * yOff), aDesc.zOffset, new Vector2(minU, cap.y + (cap.height / 2))) : -1; int v25 = splitMiddle ? DMesh.AddVertex(pos + (norm * yOff), aDesc.zOffset, new Vector2(maxU, cap.y + (cap.height / 2))) : -1; int v3 = DMesh.AddVertex(pos - norm * (scale - yOff), slantAmount + aDesc.zOffset, new Vector2(maxU, maxV)); int v4 = DMesh.AddVertex(pos + dir * width - norm * (scale - yOff), slantAmount + aDesc.zOffset, new Vector2(minU, maxV)); if (splitMiddle && aDir < 0) { DMesh.AddFace(v1, v2, v25, v15); DMesh.AddFace(v15, v25, v3, v4 ); } else if (splitMiddle && aDir >= 0) { DMesh.AddFace(v2, v1, v15, v25); DMesh.AddFace(v25, v15, v4, v3 ); } else if (aDir < 0){ DMesh.AddFace(v1, v2, v3, v4); } else { DMesh.AddFace(v2, v1, v4, v3); } }
public static void EditUVsComplex(IFerr2DTMaterial aMat, Ferr2DT_SegmentDescription desc, float aWidth, ref int aCurrBody) { int currBody = aCurrBody; int bodyID = 0; Ferr.EditorTools.Box(2, () => { if (desc.leftCap.width == 0 && desc.leftCap.height == 0 && desc.rightCap.width == 0 && desc.rightCap.height == 0) { desc.EditorLeftCapOffset = EditorGUILayout.Slider("Left Offset", desc.EditorLeftCapOffset, -1, 1); desc.EditorRightCapOffset = EditorGUILayout.Slider("Right Offset", desc.EditorRightCapOffset, -1, 1); } EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Body", GUILayout.Width(40f)); bodyID = Mathf.Clamp(currBody, 0, desc.body.Length); if (GUILayout.Button("<", GUILayout.Width(20f))) { currBody = Mathf.Clamp(currBody - 1, 0, desc.body.Length - 1); } EditorGUILayout.LabelField("" + (bodyID + 1), GUILayout.Width(12f)); if (GUILayout.Button(">", GUILayout.Width(20f))) { currBody = Mathf.Clamp(currBody + 1, 0, desc.body.Length - 1); } bodyID = Mathf.Clamp(currBody, 0, desc.body.Length - 1); int length = Math.Max(1, EditorGUILayout.IntField(desc.body.Length, GUILayout.Width(32f))); EditorGUILayout.LabelField("Total", GUILayout.Width(40f)); if (length != desc.body.Length) { Rect[] bodies = desc.body; Array.Resize <Rect>(ref bodies, length); desc.body = bodies; } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); desc.body[bodyID] = AtlasField(aMat, desc.body[bodyID], aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture); float pixelWidth = aMat.edgeMaterial == null || aMat.edgeMaterial.mainTexture == null ? 1f / 256 : 1f / aMat.edgeMaterial.mainTexture.width; if (desc.body[bodyID].width < pixelWidth) { desc.body[bodyID].width = pixelWidth; } }); aCurrBody = currBody; EditorGUILayout.Space(); Ferr.EditorTools.Box(2, () => { if (desc.leftCap.width == 0 && desc.leftCap.height == 0) { if (EditorGUILayout.Toggle("Left Cap", false)) { desc.leftCap = aMat.ToNative(new Rect(0, 0, 50, 50)); } } else { if (EditorGUILayout.Toggle("Left Cap", true)) { desc.EditorLeftCapOffset = EditorGUILayout.Slider("Cap Offset", desc.EditorLeftCapOffset, -1, 1); desc.leftCap = AtlasField(aMat, desc.leftCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture); } else { desc.leftCap = new Rect(0, 0, 0, 0); } } EditorGUI.indentLevel += 1; desc.EditorLeftCapType = Convert.ToInt32(EditorGUILayout.EnumPopup("Collider Type", (Ferr2D_CapColliderType)desc.EditorLeftCapType)); desc.EditorLeftCapColliderSize = EditorGUILayout.Slider("Collider Size", desc.EditorLeftCapColliderSize, -1, 2); EditorGUI.indentLevel -= 1; }); EditorGUILayout.Space(); Ferr.EditorTools.Box(2, () => { if (desc.innerLeftCap.width == 0 && desc.innerLeftCap.height == 0) { if (EditorGUILayout.Toggle("Inner Left Cap", false)) { desc.innerLeftCap = aMat.ToNative(new Rect(0, 0, 50, 50)); } } else { if (EditorGUILayout.Toggle("Inner Left Cap", true)) { Ferr.EditorTools.Box(2, () => { desc.EditorInnerLeftCapOffset = EditorGUILayout.Slider("Cap Offset", desc.EditorInnerLeftCapOffset, -1, 1); desc.innerLeftCap = AtlasField(aMat, desc.innerLeftCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture); }); } else { desc.innerLeftCap = new Rect(0, 0, 0, 0); } } EditorGUI.indentLevel += 1; desc.EditorInnerLeftCapType = Convert.ToInt32(EditorGUILayout.EnumPopup("Collider Type", (Ferr2D_CapColliderType)desc.EditorInnerLeftCapType)); desc.EditorInnerLeftCapColliderSize = EditorGUILayout.Slider("Collider Size", desc.EditorInnerLeftCapColliderSize, -1, 2); EditorGUI.indentLevel -= 1; }); EditorGUILayout.Space(); Ferr.EditorTools.Box(2, () => { if (desc.rightCap.width == 0 && desc.rightCap.height == 0) { if (EditorGUILayout.Toggle("Right Cap", false)) { desc.rightCap = aMat.ToNative(new Rect(0, 0, 50, 50)); } } else { if (EditorGUILayout.Toggle("Right Cap", true)) { Ferr.EditorTools.Box(2, () => { desc.EditorRightCapOffset = EditorGUILayout.Slider("Cap Offset", desc.EditorRightCapOffset, -1, 1); desc.rightCap = AtlasField(aMat, desc.rightCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture); }); } else { desc.rightCap = new Rect(0, 0, 0, 0); } } EditorGUI.indentLevel += 1; desc.EditorRightCapType = Convert.ToInt32(EditorGUILayout.EnumPopup("Collider Type", (Ferr2D_CapColliderType)desc.EditorRightCapType)); desc.EditorRightCapColliderSize = EditorGUILayout.Slider("Collider Size", desc.EditorRightCapColliderSize, -1, 2); EditorGUI.indentLevel -= 1; }); EditorGUILayout.Space(); Ferr.EditorTools.Box(2, () => { if (desc.innerRightCap.width == 0 && desc.innerRightCap.height == 0) { if (EditorGUILayout.Toggle("Inner Right Cap", false)) { desc.innerRightCap = aMat.ToNative(new Rect(0, 0, 50, 50)); } } else { if (EditorGUILayout.Toggle("Inner Right Cap", true)) { Ferr.EditorTools.Box(2, () => { desc.EditorInnerRightCapOffset = EditorGUILayout.Slider("Cap Offset", desc.EditorInnerRightCapOffset, -1, 1); desc.innerRightCap = AtlasField(aMat, desc.innerRightCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture); }); } else { desc.innerRightCap = new Rect(0, 0, 0, 0); } } EditorGUI.indentLevel += 1; desc.EditorInnerRightCapType = Convert.ToInt32(EditorGUILayout.EnumPopup("Collider Type", (Ferr2D_CapColliderType)desc.EditorInnerRightCapType)); desc.EditorInnerRightCapColliderSize = EditorGUILayout.Slider("Collider Size", desc.EditorInnerRightCapColliderSize, -1, 2); EditorGUI.indentLevel -= 1; }); }
private void SlicedQuad(List <Vector2> aSegment, int aVert, float aStart, float aEnd, int aCuts, bool aSmoothed, bool aClosed, Ferr2DT_SegmentDescription aDesc, float aStartScale, float aEndScale) { Vector2[] pos = new Vector2[aCuts]; Vector2[] norm = new Vector2[aCuts]; float [] scales = new float [aCuts]; Vector3 tn1 = Ferr2D_Path.GetNormal(aSegment, aVert, aClosed); Vector3 tn2 = Ferr2D_Path.GetNormal(aSegment, aVert + 1, aClosed); // get the data needed to make the quad for (int i = 0; i < aCuts; i++) { float percent = aStart + (i / (float)(aCuts - 1)) * (aEnd - aStart); if (aSmoothed) { pos [i] = Ferr2D_Path.HermiteGetPt(aSegment, aVert, percent, aClosed); norm[i] = Ferr2D_Path.HermiteGetNormal(aSegment, aVert, percent, aClosed); } else { pos [i] = Vector2.Lerp(aSegment[aVert], aSegment[aVert + 1], percent); norm[i] = Vector2.Lerp(tn1, tn2, percent); } scales[i] = Mathf.Lerp(aStartScale, aEndScale, (i / (float)(aCuts - 1))); } int tSeed = 0; if (randomByWorldCoordinates) { tSeed = UnityEngine.Random.seed; UnityEngine.Random.seed = (int)(pos[0].x * 700000 + pos[0].y * 30000); } Rect body = terrainMaterial.ToUV(aDesc.body[UnityEngine.Random.Range(0, aDesc.body.Length)]); float d = (body.height / 2) * unitsPerUV.y; float yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset; if (randomByWorldCoordinates) { UnityEngine.Random.seed = tSeed; } // put the data together into a mesh int p1 = 0, p2 = 0, p3 = 0; for (int i = 0; i < aCuts; i++) { float percent = (i / (float)(aCuts - 1)); Vector3 pos1 = pos [i]; Vector3 n1 = norm[i]; int v1 = DMesh.AddVertex(pos1.x + n1.x * (d * scales[i] + yOff), pos1.y + n1.y * (d * scales[i] + yOff), -slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), fill == Ferr2DT_FillMode.InvertedClosed ? body.yMax : body.y); int v2 = DMesh.AddVertex(pos1.x - n1.x * (d * scales[i] - yOff), pos1.y - n1.y * (d * scales[i] - yOff), slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), fill == Ferr2DT_FillMode.InvertedClosed ? body.y : body.yMax); int v3 = splitMiddle ? DMesh.AddVertex(pos1.x + n1.x * yOff, pos1.y + n1.y * yOff, aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), Mathf.Lerp(body.y, body.yMax, 0.5f)) : -1; if (i != 0) { if (!splitMiddle) { DMesh.AddFace(v2, p2, p1, v1); } else { DMesh.AddFace(v2, p2, p3, v3); DMesh.AddFace(v3, p3, p1, v1); } } p1 = v1; p2 = v2; p3 = v3; } }
private void AddCap(List <Vector2> aSegment, Ferr2DT_SegmentDescription aDesc, bool aInner, float aDir, float aScale, bool aSmooth) { int index = 0; Vector2 dir = Vector2.zero; if (aDir < 0) { index = 0; dir = aSegment[0] - aSegment[1]; } else { index = aSegment.Count - 1; dir = aSegment[aSegment.Count - 1] - aSegment[aSegment.Count - 2]; } dir.Normalize(); Vector2 norm = aSmooth ? Ferr2D_Path.HermiteGetNormal(aSegment, index, 0, false): Ferr2D_Path.GetNormal(aSegment, index, false); Vector2 pos = aSegment[index]; float yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset; Rect cap; if (aDir < 0) { if (fill == Ferr2DT_FillMode.InvertedClosed) { cap = (!aInner && aDesc.innerRightCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerRightCap) : terrainMaterial.ToUV(aDesc.rightCap); } else { cap = (aInner && aDesc.innerLeftCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerLeftCap) : terrainMaterial.ToUV(aDesc.leftCap); } } else { if (fill == Ferr2DT_FillMode.InvertedClosed) { cap = (!aInner && aDesc.innerLeftCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerLeftCap) : terrainMaterial.ToUV(aDesc.leftCap); } else { cap = (aInner && aDesc.innerRightCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerRightCap) : terrainMaterial.ToUV(aDesc.rightCap); } } float width = cap.width * unitsPerUV.x; float scale = (cap.height / 2) * unitsPerUV.y * aScale; float minU = fill == Ferr2DT_FillMode.InvertedClosed ? cap.xMax : cap.x; float maxU = fill == Ferr2DT_FillMode.InvertedClosed ? cap.x : cap.xMax; float minV = fill == Ferr2DT_FillMode.InvertedClosed ? cap.yMax : cap.y; float maxV = fill == Ferr2DT_FillMode.InvertedClosed ? cap.y : cap.yMax; if (aDir >= 0) { float t = minU; minU = maxU; maxU = t; } int v1 = DMesh.AddVertex(pos + dir * width + norm * (scale + yOff), -slantAmount + aDesc.zOffset, new Vector2(minU, minV)); int v2 = DMesh.AddVertex(pos + norm * (scale + yOff), -slantAmount + aDesc.zOffset, new Vector2(maxU, minV)); int v15 = splitMiddle ? DMesh.AddVertex(pos + dir * width + (norm * yOff), aDesc.zOffset, new Vector2(minU, cap.y + (cap.height / 2))) : -1; int v25 = splitMiddle ? DMesh.AddVertex(pos + (norm * yOff), aDesc.zOffset, new Vector2(maxU, cap.y + (cap.height / 2))) : -1; int v3 = DMesh.AddVertex(pos - norm * (scale - yOff), slantAmount + aDesc.zOffset, new Vector2(maxU, maxV)); int v4 = DMesh.AddVertex(pos + dir * width - norm * (scale - yOff), slantAmount + aDesc.zOffset, new Vector2(minU, maxV)); if (splitMiddle && aDir < 0) { DMesh.AddFace(v1, v2, v25, v15); DMesh.AddFace(v15, v25, v3, v4); } else if (splitMiddle && aDir >= 0) { DMesh.AddFace(v2, v1, v15, v25); DMesh.AddFace(v25, v15, v4, v3); } else if (aDir < 0) { DMesh.AddFace(v1, v2, v3, v4); } else { DMesh.AddFace(v2, v1, v4, v3); } }
public static bool IsSimple(Ferr2DT_SegmentDescription aDesc) { float y = aDesc.body[0].y; bool hasCaps = aDesc.leftCap.width != 0 || aDesc.rightCap.width != 0; float height = aDesc.body[0].height; if (hasCaps && (aDesc.leftCap.y != y || aDesc.rightCap.y != y)) return false; if (hasCaps && aDesc.leftCap.xMax != aDesc.body[0].x) return false; if (hasCaps && aDesc.rightCap.x != aDesc.body[aDesc.body.Length - 1].xMax) return false; if (hasCaps && (aDesc.leftCap.height != height || aDesc.rightCap.height != height)) return false; for (int i = 0; i < aDesc.body.Length; i++) { if (aDesc.body[i].y != aDesc.leftCap.y) return false; if (aDesc.body[i].height != height) return false; if (i + 1 < aDesc.body.Length && aDesc.body[i].xMax != aDesc.body[i + 1].x) return false; } return true; }
private void SlicedQuad(List<Vector2> aSegment, int aVert, float aStart, float aEnd, int aCuts, bool aSmoothed, bool aClosed, Ferr2DT_SegmentDescription aDesc, float aStartScale, float aEndScale) { Vector2[] pos = new Vector2[aCuts]; Vector2[] norm = new Vector2[aCuts]; float [] scales = new float [aCuts]; Vector3 tn1 = Ferr2D_Path.GetNormal(aSegment, aVert, aClosed); Vector3 tn2 = Ferr2D_Path.GetNormal(aSegment, aVert+1, aClosed); // get the data needed to make the quad for (int i = 0; i < aCuts; i++) { float percent = aStart + (i / (float)(aCuts - 1)) * (aEnd - aStart); if (aSmoothed) { pos [i] = Ferr2D_Path.HermiteGetPt (aSegment, aVert, percent, aClosed); norm[i] = Ferr2D_Path.HermiteGetNormal(aSegment, aVert, percent, aClosed); } else { pos [i] = Vector2.Lerp(aSegment[aVert], aSegment[aVert + 1], percent); norm[i] = Vector2.Lerp(tn1, tn2, percent); } scales[i] = Mathf.Lerp(aStartScale, aEndScale, (i / (float)(aCuts - 1))); } int tSeed = 0; if (randomByWorldCoordinates) { tSeed = UnityEngine.Random.seed; UnityEngine.Random.seed = (int)(pos[0].x * 700000 + pos[0].y * 30000); } Rect body = terrainMaterial.ToUV(aDesc.body[UnityEngine.Random.Range(0, aDesc.body.Length)]); float d = (body.height / 2) * unitsPerUV.y; float yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset; if (randomByWorldCoordinates) { UnityEngine.Random.seed = tSeed; } // put the data together into a mesh int p1=0, p2=0, p3=0; for (int i = 0; i < aCuts; i++) { float percent = (i/(float)(aCuts-1)); Vector3 pos1 = pos [i ]; Vector3 n1 = norm[i ]; int v1 = DMesh.AddVertex(pos1.x + n1.x * (d*scales[i] + yOff), pos1.y + n1.y * (d*scales[i] + yOff), -slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), fill == Ferr2DT_FillMode.InvertedClosed ? body.yMax : body.y ); int v2 = DMesh.AddVertex(pos1.x - n1.x * (d*scales[i] - yOff), pos1.y - n1.y * (d*scales[i] - yOff), slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), fill == Ferr2DT_FillMode.InvertedClosed ? body.y : body.yMax); int v3 = splitMiddle ? DMesh.AddVertex(pos1.x + n1.x * yOff, pos1.y + n1.y * yOff, aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), Mathf.Lerp(body.y,body.yMax,0.5f)) : -1; if (i != 0) { if (!splitMiddle) { DMesh.AddFace(v2, p2, p1, v1); } else { DMesh.AddFace(v2, p2, p3, v3); DMesh.AddFace(v3, p3, p1, v1); } } p1 = v1; p2 = v2; p3 = v3; } }
public static void EditUVsComplex(Ferr2DT_TerrainMaterial aMat, Ferr2DT_SegmentDescription desc, float aWidth, ref int aCurrBody) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Body", GUILayout.Width(40f)); int bodyID = Mathf.Clamp(aCurrBody, 0, desc.body.Length); if (GUILayout.Button("<", GUILayout.Width(20f))) { aCurrBody = Mathf.Clamp(aCurrBody - 1, 0, desc.body.Length - 1); } EditorGUILayout.LabelField("" + (bodyID + 1), GUILayout.Width(12f)); if (GUILayout.Button(">", GUILayout.Width(20f))) { aCurrBody = Mathf.Clamp(aCurrBody + 1, 0, desc.body.Length - 1); } bodyID = Mathf.Clamp(aCurrBody, 0, desc.body.Length - 1); int length = Math.Max(1, EditorGUILayout.IntField(desc.body.Length, GUILayout.Width(32f))); EditorGUILayout.LabelField("Total", GUILayout.Width(40f)); if (length != desc.body.Length) { Array.Resize <Rect>(ref desc.body, length); } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); desc.body[bodyID] = AtlasField(aMat, desc.body[bodyID], aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture); if (desc.leftCap.width == 0 && desc.leftCap.height == 0) { if (EditorGUILayout.Toggle("Left Cap", false)) { desc.leftCap = new Rect(0, 0, 30, 30); } } else { if (EditorGUILayout.Toggle("Left Cap", true)) { desc.leftCap = AtlasField(aMat, desc.leftCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture); } else { desc.leftCap = new Rect(0, 0, 0, 0); } } if (desc.innerLeftCap.width == 0 && desc.innerLeftCap.height == 0) { if (EditorGUILayout.Toggle("Inner Left Cap", false)) { desc.innerLeftCap = new Rect(0, 0, 30, 30); } } else { if (EditorGUILayout.Toggle("Inner Left Cap", true)) { desc.innerLeftCap = AtlasField(aMat, desc.innerLeftCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture); } else { desc.innerLeftCap = new Rect(0, 0, 0, 0); } } if (desc.rightCap.width == 0 && desc.rightCap.height == 0) { if (EditorGUILayout.Toggle("Right Cap", false)) { desc.rightCap = new Rect(0, 0, 30, 30); } } else { if (EditorGUILayout.Toggle("Right Cap", true)) { desc.rightCap = AtlasField(aMat, desc.rightCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture); } else { desc.rightCap = new Rect(0, 0, 0, 0); } } if (desc.innerRightCap.width == 0 && desc.innerRightCap.height == 0) { if (EditorGUILayout.Toggle("Inner Right Cap", false)) { desc.innerRightCap = new Rect(0, 0, 30, 30); } } else { if (EditorGUILayout.Toggle("Inner Right Cap", true)) { desc.innerRightCap = AtlasField(aMat, desc.innerRightCap, aMat.edgeMaterial != null ? aMat.edgeMaterial.mainTexture : EditorGUIUtility.whiteTexture); } else { desc.innerRightCap = new Rect(0, 0, 0, 0); } } }
public static void ShowPreviewDirection(Ferr2DT_TerrainMaterial aMat, Ferr2DT_TerrainDirection aDir, Rect aBounds, bool aSimpleUVs, bool aEditable) { Ferr2DT_SegmentDescription desc = aMat.GetDescriptor(aDir); if (!aMat.Has(aDir)) { return; } if (!aEditable) { for (int i = 0; i < desc.body.Length; i++) { Ferr.EditorTools.DrawRect(aMat.ToScreen(desc.body[i]), aBounds); } Ferr.EditorTools.DrawRect(aMat.ToScreen(desc.leftCap), aBounds); Ferr.EditorTools.DrawRect(aMat.ToScreen(desc.rightCap), aBounds); Ferr.EditorTools.DrawRect(aMat.ToScreen(desc.innerLeftCap), aBounds); Ferr.EditorTools.DrawRect(aMat.ToScreen(desc.innerRightCap), aBounds); } else if (aSimpleUVs) { float height = MaxHeight(desc); float capWidth = Mathf.Max(desc.leftCap.width, desc.rightCap.width); float bodyWidth = desc.body[0].width; int bodyCount = desc.body.Length; float texWidth = aMat.edgeMaterial.mainTexture != null ? aMat.edgeMaterial.mainTexture.width : 1; float texHeight = aMat.edgeMaterial.mainTexture != null ? aMat.edgeMaterial.mainTexture.height : 1; Vector2 pos = new Vector2(desc.leftCap.x, desc.leftCap.y); if (desc.leftCap.width == 0 && desc.leftCap.height == 0) { pos = new Vector2(desc.body[0].x, desc.body[0].y); } Rect bounds = new Rect(pos.x, pos.y, capWidth * 2 + bodyWidth * bodyCount, height); bounds = aMat.ToNative(Ferr.EditorTools.UVRegionRect(aMat.ToPixels(bounds), aBounds)); bounds = ClampRect(bounds, (Texture2D)aMat.edgeMaterial.mainTexture); Ferr.EditorTools.DrawVLine(new Vector2((pos.x + capWidth) * texWidth + aBounds.x, (pos.y * texHeight) + 2), height * texHeight); for (int i = 1; i <= desc.body.Length; i++) { Ferr.EditorTools.DrawVLine(new Vector2((pos.x + capWidth + bodyWidth * i) * texWidth + aBounds.x, (pos.y * texHeight) + 2), height * texHeight); } height = bounds.height; bodyWidth = (bounds.width - capWidth * 2) / bodyCount; pos.x = bounds.x; pos.y = bounds.y; float currX = pos.x; desc.leftCap.x = currX; desc.leftCap.y = pos.y; desc.leftCap.width = capWidth; desc.leftCap.height = capWidth == 0 ? 0 : height; currX += capWidth; for (int i = 0; i < desc.body.Length; i++) { desc.body[i].x = currX; desc.body[i].y = pos.y; desc.body[i].width = bodyWidth; desc.body[i].height = height; currX += bodyWidth; } desc.rightCap.x = currX; desc.rightCap.y = pos.y; desc.rightCap.width = capWidth; desc.rightCap.height = capWidth == 0 ? 0 : height; } else { for (int i = 0; i < desc.body.Length; i++) { desc.body[i] = ClampRect(aMat.ToNative(Ferr.EditorTools.UVRegionRect(aMat.ToPixels(desc.body[i]), aBounds)), (Texture2D)aMat.edgeMaterial.mainTexture); } if (desc.leftCap.width != 0 && desc.leftCap.height != 0) { desc.leftCap = ClampRect(aMat.ToNative(Ferr.EditorTools.UVRegionRect(aMat.ToPixels(desc.leftCap), aBounds)), (Texture2D)aMat.edgeMaterial.mainTexture); } if (desc.rightCap.width != 0 && desc.rightCap.height != 0) { desc.rightCap = ClampRect(aMat.ToNative(Ferr.EditorTools.UVRegionRect(aMat.ToPixels(desc.rightCap), aBounds)), (Texture2D)aMat.edgeMaterial.mainTexture); } if (desc.innerLeftCap.width != 0 && desc.innerLeftCap.height != 0) { desc.innerLeftCap = ClampRect(aMat.ToNative(Ferr.EditorTools.UVRegionRect(aMat.ToPixels(desc.innerLeftCap), aBounds)), (Texture2D)aMat.edgeMaterial.mainTexture); } if (desc.innerRightCap.width != 0 && desc.innerRightCap.height != 0) { desc.innerRightCap = ClampRect(aMat.ToNative(Ferr.EditorTools.UVRegionRect(aMat.ToPixels(desc.innerRightCap), aBounds)), (Texture2D)aMat.edgeMaterial.mainTexture); } } }