private void DoResetModeHandles(Ferr2D_Path path, Ferr2DT_PathTerrain terrain, int i, Matrix4x4 mat, Matrix4x4 invMat, Transform camTransform) { int nextId = i == path.Count - 1?(path.closed?i % path.Count:i - 1):i + 1; Vector3 pos = mat.MultiplyPoint3x4(path.pathVerts[i]); Vector3 posNext = mat.MultiplyPoint3x4(path.pathVerts[nextId]); Vector3 normal = -(Vector3)Ferr2D_Path.GetNormal(path.pathVerts, i, path.closed); Vector3 posStart = pos; bool isSelected = false; if (selectedPoints != null) { isSelected = selectedPoints.Contains(i); } float handleScale = HandleScale(posStart); CapFunction cap = (isSelected || selectedPoints.Count <= 0) ? (CapFunction)CapDotMinusSelected : (CapFunction)CapDotMinus; if (Handles.Button(posStart, camTransform.rotation, handleScale, handleScale, cap)) { EnsureVertSelected(i, ref isSelected); deleteSelected = true; GUI.changed = true; } else if (!Ferr2DT_SceneOverlay.segmentLockMode) { handleScale = handleScale * 0.5f; // do scaling Vector3 displayPos = pos + normal * terrain.vertScales[i] * 2 * Ferr2DT_Menu.PathScale; if (IsVisible(displayPos) && Handles.Button(displayPos, camTransform.rotation, handleScale, handleScale, CapDotReset)) { EnsureVertSelected(i, ref isSelected); Undo.RecordObject(terrain, "Scale Path Vert"); for (int s = 0; s < selectedPoints.Count; s++) { terrain.vertScales[selectedPoints[s]] = 1; } EditorUtility.SetDirty(terrain); GUI.changed = true; } // do edge overrides displayPos = GetOverridePos(i, path, mat, pos, posNext); if (IsVisible(displayPos) && Handles.Button(displayPos, camTransform.rotation, handleScale, handleScale, CapDotReset)) { EnsureVertSelected(i, ref isSelected); Undo.RecordObject(terrain, "Override Vert Direction"); for (int s = 0; s < selectedPoints.Count; s++) { terrain.directionOverrides[selectedPoints[s]] = Ferr2DT_TerrainDirection.None; } EditorUtility.SetDirty(terrain); GUI.changed = true; } } }
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; }
private List <Vector2> ExpandColliderPath(List <Vector2> aList, float aAmount) { int count = aList.Count; for (int i = count - 1; i >= 0; i--) { Vector2 norm = Ferr2D_Path.GetNormal(aList, i, false); aList.Add(aList [i] + new Vector2(norm.x * aAmount, norm.y * aAmount)); } return(aList); }
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); } }
private List <Vector2> GetColliderVerts() { Ferr2D_Path path = GetComponent <Ferr2D_Path> (); List <Vector2> verts = path.GetVerts(smoothPath, splitDist, splitCorners); if (path.closed && smoothPath == false) { verts.Add(verts [0]); } List <Vector2> raw = new List <Vector2> (verts); MatchOverrides(); // consider the offset values for the collider. Also, if it's not filled, make sure we add in // extra path verts for the underside of the path int count = raw.Count; for (int i = count - 1; i >= 0; i--) { Vector2 norm = Ferr2D_Path.GetNormal(raw, i, path.closed); if (fill == Ferr2DT_FillMode.None) { verts.Add(raw [i] + new Vector2(norm.x * surfaceOffset [(int)Ferr2DT_TerrainDirection.Top], norm.y * surfaceOffset [(int)Ferr2DT_TerrainDirection.Top])); verts [i] += new Vector2(norm.x * -surfaceOffset [(int)Ferr2DT_TerrainDirection.Bottom], norm.y * -surfaceOffset [(int)Ferr2DT_TerrainDirection.Bottom]); } else { Vector2 offset = GetOffset(raw, i, path.closed); verts [i] += new Vector2(norm.x * -offset.x, norm.y * -offset.y); } } if (fill == Ferr2DT_FillMode.Skirt || fill == Ferr2DT_FillMode.FillOnlySkirt) { Vector2 start = verts [0]; Vector2 end = verts [verts.Count - 1]; verts.Add(new Vector2(end.x, fillY)); verts.Add(new Vector2(Mathf.Lerp(end.x, start.x, 0.33f), fillY)); verts.Add(new Vector2(Mathf.Lerp(end.x, start.x, 0.66f), fillY)); verts.Add(new Vector2(start.x, fillY)); } else if (fill == Ferr2DT_FillMode.None) { } return(verts); }
private void DoNormalModeHandles(Ferr2D_Path path, Ferr2DT_PathTerrain terrain, int i, Matrix4x4 mat, Matrix4x4 invMat, Transform camTransform) { int nextId = i == path.Count - 1?(path.closed?0:i - 1):i + 1; Vector3 pos = mat.MultiplyPoint3x4(path.pathVerts[i]); Vector3 posNext = mat.MultiplyPoint3x4(path.pathVerts[nextId]); Vector3 normal = -(Vector3)Ferr2D_Path.GetNormal(path.pathVerts, i, path.closed); bool isSelected = false; if (selectedPoints != null) { isSelected = selectedPoints.Contains(i); } // check for moving the point CapFunction cap = CapDot; if (Event.current.control) { cap = isSelected ? (CapFunction)CapDotSelectedSnap : (CapFunction)CapDotSnap; } else { cap = isSelected ? (CapFunction)CapDotSelected : (CapFunction)CapDot; } Vector3 result = Handles.FreeMoveHandle(pos, camTransform.rotation, HandleScale(pos), snap, cap); if (result != pos) { EnsureVertSelected(i, ref isSelected); Vector2 relative = GetRelativeMovementWithSnap(result, invMat, i, path); for (int s = 0; s < selectedPoints.Count; s++) { path.pathVerts[selectedPoints[s]] += relative; } } if (Ferr2DT_SceneOverlay.showIndices) { Vector3 labelPos = pos + normal; Handles.color = Color.white; Handles.Label(labelPos, "" + i); } if (!Ferr2DT_SceneOverlay.segmentLockMode) { float scale = HandleScale(pos) * 0.5f; Vector3 displayPos = pos; if (path.closed || i + 1 < path.pathVerts.Count) { displayPos = GetOverridePos(i, path, mat, pos, posNext); if (IsVisible(displayPos) && terrain.directionOverrides != null) { cap = Event.current.alt ? (CapFunction)CapDotReset : GetDirIcon(terrain.directionOverrides[i]); if (Handles.Button(displayPos, camTransform.rotation, scale, scale, cap)) { EnsureVertSelected(i, ref isSelected); Undo.RecordObject(terrain, "Override Vert Direction"); Ferr2DT_TerrainDirection dir = NextDir(terrain.directionOverrides[i]); for (int s = 0; s < selectedPoints.Count; s++) { terrain.directionOverrides[selectedPoints[s]] = dir; } EditorUtility.SetDirty(terrain); GUI.changed = true; } } } displayPos = pos + normal * terrain.vertScales[i] * 2 * Ferr2DT_Menu.PathScale; if (IsVisible(displayPos)) { cap = Event.current.alt ? (CapFunction)CapDotReset : (CapFunction)CapDotScale; Vector3 scaleMove = Handles.FreeMoveHandle(displayPos, camTransform.rotation, scale, Vector3.zero, cap); float scaleAmt = Vector3.Distance(displayPos, scaleMove); if (Mathf.Abs(scaleAmt) > 0.01f) { EnsureVertSelected(i, ref isSelected); Undo.RecordObject(terrain, "Scale Path Vert"); float vertScale = Vector3.Distance(scaleMove, pos) / 2 / Ferr2DT_Menu.PathScale; vertScale = Mathf.Clamp(vertScale, 0.2f, 3f); for (int s = 0; s < selectedPoints.Count; s++) { terrain.vertScales[selectedPoints[s]] = vertScale; } EditorUtility.SetDirty(terrain); GUI.changed = true; } } // make sure we can add new point at the midpoints! if (i + 1 < path.pathVerts.Count || path.closed == true) { Vector3 mid = (pos + posNext) / 2; float handleScale = HandleScale(mid); if (Handles.Button(mid, camTransform.rotation, handleScale, handleScale, CapDotPlus)) { Vector2 pt = invMat.MultiplyPoint3x4(mid); terrain.AddPoint(pt, nextId); EditorUtility.SetDirty(terrain); GUI.changed = true; } } } }
private void DoHandles(Ferr2D_Path path, GUIStyle iconStyle) { Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent <Ferr2DT_PathTerrain>(); if (terrain) { terrain.MatchOverrides(); } Quaternion inv = Quaternion.Inverse(path.transform.rotation); Handles.color = new Color(1, 1, 1, 0); for (int i = 0; i < path.pathVerts.Count; i++) { Vector3 pos = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[i].x, path.pathVerts[i].y, 0), path.transform.localScale); Vector3 posOff = pos + offset; bool isSelected = false; if (selectedPoints != null) { isSelected = selectedPoints.Contains(i); } // check if we want to remove points if (Event.current.alt) { float handleScale = HandleScale(posOff); if (IsVisible(posOff)) { SetScale(posOff, texMinus, ref iconStyle); //Handles.Label(posOff, new GUIContent((isSelected || selectedPoints.Count <= 0) ? texMinusSelected : texMinus), iconStyle); } if (Handles.Button(posOff, SceneView.lastActiveSceneView.camera.transform.rotation, handleScale, handleScale, Handles.CircleCap)) { if (!isSelected && selectedPoints != null) { selectedPoints.Clear(); selectedPoints.Add(i); } if (selectedPoints != null) { for (int s = 0; s < selectedPoints.Count; s++) { if (terrain) { terrain.RemovePoint(selectedPoints[s]); } else { path.pathVerts.RemoveAt(selectedPoints[s]); } if (selectedPoints[s] <= i) { i--; } for (int u = 0; u < selectedPoints.Count; u++) { if (selectedPoints[u] > selectedPoints[s]) { selectedPoints[u] -= 1; } } } } if (selectedPoints != null) { selectedPoints.Clear(); } GUI.changed = true; } else if (Ferr2DT_SceneOverlay.editMode != Ferr2DT_EditMode.None) { if (terrain && i + 1 < path.pathVerts.Count) { float scale = handleScale * 0.5f; Vector3 dirOff = GetTickerOffset(path, pos, i); Vector3 posDirOff = posOff + dirOff; if (IsVisible(posDirOff)) { Texture2D icon = null; if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override) { icon = GetDirIcon(terrain.directionOverrides[i]); } else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale) { icon = texScale; } if (Event.current.alt) { icon = texReset; } SetScale(posDirOff, icon, ref iconStyle, 0.5f); Handles.Label(posDirOff, new GUIContent(icon), iconStyle); if (Handles.Button(posDirOff, SceneView.lastActiveSceneView.camera.transform.rotation, scale, scale, Handles.CircleCap) && selectedPoints != null) { if (selectedPoints.Count < 2 || isSelected == false) { selectedPoints.Clear(); selectedPoints.Add(i); isSelected = true; } for (int s = 0; s < selectedPoints.Count; s++) { if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override) { terrain.directionOverrides[selectedPoints[s]] = Ferr2DT_TerrainDirection.None; } else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale) { terrain.vertScales[selectedPoints[s]] = 1; } } GUI.changed = true; } } } } } else { // check for moving the point Texture2D tex = null; if (Event.current.control) { tex = isSelected ? texDotSelectedSnap : texDotSnap; } else { tex = isSelected ? texDotSelected : texDot; } if (IsVisible(posOff)) { SetScale(posOff, texMinus, ref iconStyle); Handles.Label(posOff, new GUIContent(tex), iconStyle); } Vector3 snap = Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapRelative ? new Vector3(EditorPrefs.GetFloat("MoveSnapX"), EditorPrefs.GetFloat("MoveSnapY"), EditorPrefs.GetFloat("MoveSnapZ")) : Vector3.zero; Vector3 result = Handles.FreeMoveHandle( posOff, SceneView.lastActiveSceneView.camera.transform.rotation, HandleScale(pos + offset), snap, Handles.CircleCap); if (result != posOff) { if (selectedPoints != null) { if (selectedPoints.Count < 2 || isSelected == false) { selectedPoints.Clear(); selectedPoints.Add(i); isSelected = true; } } if (!(Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapRelative)) { result = GetRealPoint(result, path.transform.position.z); } Vector3 global = (result - offset); if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapGlobal) { global = SnapVector(global); } Vector3 local = inv * (global - path.transform.position); if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapLocal) { local = SnapVector(local); } if (!Event.current.control && Ferr2DT_SceneOverlay.smartSnap && selectedPoints != null) { local = SmartSnap(local, path.pathVerts, selectedPoints, Ferr_Menu.SmartSnapDist); } Vector2 relative = new Vector2( local.x / path.transform.localScale.x, local.y / path.transform.localScale.y) - path.pathVerts[i]; if (selectedPoints != null) { for (int s = 0; s < selectedPoints.Count; s++) { path.pathVerts[selectedPoints[s]] += relative; } } } // if using terrain, check to see for any edge overrides if (Ferr2DT_SceneOverlay.showIndices) { Vector3 labelPos = posOff + (Vector3)Ferr2D_Path.GetNormal(path.pathVerts, i, path.closed); Handles.color = Color.white; Handles.Label(labelPos, "" + i); Handles.color = new Color(1, 1, 1, 0); } if (terrain) {// && i+1 < path.pathVerts.Count) { float scale = HandleScale(pos + offset) * 0.5f; Vector3 dirOff = GetTickerOffset(path, pos, i); Vector3 posDirOff = posOff + dirOff; if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override && i + 1 < path.pathVerts.Count) { if (IsVisible(posDirOff)) { SetScale(posDirOff, texMinus, ref iconStyle, 0.5f); Handles.Label(posDirOff, new GUIContent(Event.current.alt ? texReset : GetDirIcon(terrain.directionOverrides[i])), iconStyle); if (Handles.Button(posDirOff, SceneView.lastActiveSceneView.camera.transform.rotation, scale, scale, Handles.CircleCap) && selectedPoints != null) { if (selectedPoints.Count < 2 || isSelected == false) { selectedPoints.Clear(); selectedPoints.Add(i); isSelected = true; } Ferr2DT_TerrainDirection dir = NextDir(terrain.directionOverrides[i]); for (int s = 0; s < selectedPoints.Count; s++) { terrain.directionOverrides[selectedPoints[s]] = dir; } GUI.changed = true; } } } else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale) { if (IsVisible(posDirOff)) { SetScale(posDirOff, texMinus, ref iconStyle, 0.5f); Handles.Label(posDirOff, new GUIContent(Event.current.alt ? texReset : texScale), iconStyle); Vector3 scaleMove = Handles.FreeMoveHandle(posDirOff, SceneView.lastActiveSceneView.camera.transform.rotation, scale, Vector3.zero, Handles.CircleCap); float scaleAmt = scaleMove.y - posDirOff.y; if (Mathf.Abs(scaleAmt) > 0.01f) { if (selectedPoints != null && selectedPoints.Count < 2 || isSelected == false) { selectedPoints.Clear(); selectedPoints.Add(i); isSelected = true; } float vertScale = terrain.vertScales[i] - Event.current.delta.y / 100f; vertScale = Mathf.Clamp(vertScale, 0.2f, 3f); if (selectedPoints != null) { for (int s = 0; s < selectedPoints.Count; s++) { terrain.vertScales[selectedPoints[s]] = vertScale; } } GUI.changed = true; } } } } // make sure we can add new point at the midpoints! if (i + 1 < path.pathVerts.Count || path.closed == true) { int index = path.closed && i + 1 == path.pathVerts.Count ? 0 : i + 1; Vector3 pos2 = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[index].x, path.pathVerts[index].y, 0), path.transform.localScale); Vector3 mid = (pos + pos2) / 2; float handleScale = HandleScale(mid + offset); if (Handles.Button(mid + offset, SceneView.lastActiveSceneView.camera.transform.rotation, handleScale, handleScale, Handles.CircleCap)) { Vector2 pt = inv * new Vector2((mid.x - path.transform.position.x) / path.transform.localScale.x, (mid.y - path.transform.position.y) / path.transform.localScale.y); if (terrain) { terrain.AddPoint(pt, index); } else { path.pathVerts.Insert(index, pt); } } if (IsVisible(mid + offset)) { SetScale(mid + offset, texDotPlus, ref iconStyle); Handles.Label(mid + offset, new GUIContent(texDotPlus), iconStyle); } } } } if (selectedPoints != null && Event.current.type == EventType.keyDown && Event.current.keyCode == KeyCode.Delete && selectedPoints.Count > 0) { for (int s = 0; s < selectedPoints.Count; s++) { if (terrain) { terrain.RemovePoint(selectedPoints[s]); } else { path.pathVerts.RemoveAt(selectedPoints[s]); } for (int u = 0; u < selectedPoints.Count; u++) { if (selectedPoints[u] > selectedPoints[s]) { selectedPoints[u] -= 1; } } } selectedPoints.Clear(); GUI.changed = true; Event.current.Use(); } }
private void DoHandles(Ferr2D_Path path, GUIStyle iconStyle) { Vector3 snap = Event.current.control ? new Vector3(EditorPrefs.GetFloat("MoveSnapX"), EditorPrefs.GetFloat("MoveSnapY"), EditorPrefs.GetFloat("MoveSnapZ")) : Vector3.zero; Transform transform = path.transform; Matrix4x4 mat = transform.localToWorldMatrix; Matrix4x4 invMat = transform.worldToLocalMatrix; Transform camTransform = SceneView.lastActiveSceneView.camera.transform; Ferr2DT_PathTerrain terrain = path.GetComponent <Ferr2DT_PathTerrain>(); if (terrain) { terrain.MatchOverrides(); } Handles.color = new Color(1, 1, 1, 1); for (int i = 0; i < path.pathVerts.Count; i++) { Vector3 pos = mat.MultiplyPoint3x4(path.pathVerts[i]); Vector3 posStart = pos; bool isSelected = false; if (selectedPoints != null) { isSelected = selectedPoints.Contains(i); } // check if we want to remove points if (Event.current.alt) { float handleScale = HandleScale(posStart); Handles.DrawCapFunction cap = (isSelected || selectedPoints.Count <= 0) ? (Handles.DrawCapFunction)CapDotMinusSelected : (Handles.DrawCapFunction)CapDotMinus; if (Handles.Button(posStart, camTransform.rotation, handleScale, handleScale, cap)) { if (!isSelected) { selectedPoints.Clear(); selectedPoints.Add(i); } for (int s = 0; s < selectedPoints.Count; s++) { if (terrain) { terrain.RemovePoint(selectedPoints[s]); } else { path.pathVerts.RemoveAt(selectedPoints[s]); } if (selectedPoints[s] <= i) { i--; } for (int u = 0; u < selectedPoints.Count; u++) { if (selectedPoints[u] > selectedPoints[s]) { selectedPoints[u] -= 1; } } } selectedPoints.Clear(); GUI.changed = true; } else if (Ferr2DT_SceneOverlay.editMode != Ferr2DT_EditMode.None) { if (terrain && i + 1 < path.pathVerts.Count) { float scale = handleScale * 0.5f; Vector3 dirOff = GetTickerOffset(path, pos, i); Vector3 posDirOff = posStart + dirOff; if (IsVisible(posDirOff)) { cap = null; if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override) { cap = GetDirIcon(terrain.directionOverrides[i]); } else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale) { cap = CapDotScale; } if (Event.current.alt) { cap = CapDotReset; } if (Handles.Button(posDirOff, camTransform.rotation, scale, scale, cap)) { if (selectedPoints.Count < 2 || isSelected == false) { selectedPoints.Clear(); selectedPoints.Add(i); isSelected = true; } for (int s = 0; s < selectedPoints.Count; s++) { if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override) { terrain.directionOverrides[selectedPoints[s]] = Ferr2DT_TerrainDirection.None; } else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale) { terrain.vertScales [selectedPoints[s]] = 1; } } GUI.changed = true; } } } } } else { // check for moving the point Handles.DrawCapFunction cap = CapDot; if (Event.current.control) { cap = isSelected ? (Handles.DrawCapFunction)CapDotSelectedSnap : (Handles.DrawCapFunction)CapDotSnap; } else { cap = isSelected ? (Handles.DrawCapFunction)CapDotSelected : (Handles.DrawCapFunction)CapDot; } Vector3 result = Handles.FreeMoveHandle( posStart, camTransform.rotation, HandleScale(pos), snap, cap); if (result != posStart) { if (selectedPoints.Count < 2 || isSelected == false) { selectedPoints.Clear(); selectedPoints.Add(i); isSelected = true; } if (!(Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapRelative)) { result = GetRealPoint(result, transform); } Vector3 global = result; if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapGlobal) { global = SnapVector(global, snap); } Vector3 local = invMat.MultiplyPoint3x4(global); if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapLocal) { local = SnapVector(local, snap); } if (!Event.current.control && Ferr2DT_SceneOverlay.smartSnap) { local = SmartSnap(local, path.pathVerts, selectedPoints, Ferr2DT_Menu.SmartSnapDist); } Vector2 relative = new Vector2(local.x, local.y) - path.pathVerts[i]; for (int s = 0; s < selectedPoints.Count; s++) { path.pathVerts[selectedPoints[s]] += relative; } } // if using terrain, check to see for any edge overrides if (Ferr2DT_SceneOverlay.showIndices) { Vector3 labelPos = posStart + (Vector3)Ferr2D_Path.GetNormal(path.pathVerts, i, path.closed); Handles.color = Color.white; Handles.Label(labelPos, "" + i); Handles.color = new Color(1, 1, 1, 0); } if (terrain) { float scale = HandleScale(pos) * 0.5f; Vector3 dirOff = GetTickerOffset(path, pos, i); Vector3 posDirOff = posStart + dirOff; if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override && i + 1 < path.pathVerts.Count) { if (IsVisible(posDirOff) && terrain.directionOverrides != null) { cap = Event.current.alt ? (Handles.DrawCapFunction)CapDotReset : GetDirIcon(terrain.directionOverrides[i]); if (Handles.Button(posDirOff, camTransform.rotation, scale, scale, cap)) { if (selectedPoints.Count < 2 || isSelected == false) { selectedPoints.Clear(); selectedPoints.Add(i); isSelected = true; } Ferr2DT_TerrainDirection dir = NextDir(terrain.directionOverrides[i]); for (int s = 0; s < selectedPoints.Count; s++) { terrain.directionOverrides[selectedPoints[s]] = dir; } GUI.changed = true; } } } else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale) { if (IsVisible(posDirOff)) { cap = Event.current.alt ? (Handles.DrawCapFunction)CapDotReset : (Handles.DrawCapFunction)CapDotScale; Vector3 scaleMove = Handles.FreeMoveHandle(posDirOff, camTransform.rotation, scale, Vector3.zero, cap); float scaleAmt = scaleMove.y - posDirOff.y; if (Mathf.Abs(scaleAmt) > 0.01f) { if (selectedPoints.Count < 2 || isSelected == false) { selectedPoints.Clear(); selectedPoints.Add(i); isSelected = true; } float vertScale = terrain.vertScales[i] - Event.current.delta.y / 100f; vertScale = Mathf.Clamp(vertScale, 0.2f, 3f); for (int s = 0; s < selectedPoints.Count; s++) { terrain.vertScales[selectedPoints[s]] = vertScale; } GUI.changed = true; } } } } // make sure we can add new point at the midpoints! if (i + 1 < path.pathVerts.Count || path.closed == true) { int index = path.closed && i + 1 == path.pathVerts.Count ? 0 : i + 1; Vector3 pos2 = mat.MultiplyPoint3x4(path.pathVerts[index]); Vector3 mid = (pos + pos2) / 2; float handleScale = HandleScale(mid); if (Handles.Button(mid, camTransform.rotation, handleScale, handleScale, CapDotPlus)) { Vector2 pt = invMat.MultiplyPoint3x4(mid); if (terrain) { terrain.AddPoint(pt, index); } else { path.pathVerts.Insert(index, pt); } } } } } if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Delete && selectedPoints.Count > 0) { for (int s = 0; s < selectedPoints.Count; s++) { if (terrain) { terrain.RemovePoint(selectedPoints[s]); } else { path.pathVerts.RemoveAt(selectedPoints[s]); } for (int u = 0; u < selectedPoints.Count; u++) { if (selectedPoints[u] > selectedPoints[s]) { selectedPoints[u] -= 1; } } } selectedPoints.Clear(); GUI.changed = true; Event.current.Use(); } }
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); } }
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; } }
List <Vector2> OffsetColliderVerts(List <Vector2> aSegment, List <float> aSegmentScales, Ferr2DT_TerrainDirection aDir) { List <Vector2> result = new List <Vector2>(aSegment); int count = aSegment.Count; for (int v = count - 1; v >= 0; v--) { Vector2 norm = smoothPath ? Ferr2D_Path.HermiteGetNormal(aSegment, v, 0, false) : Ferr2D_Path.GetNormal(aSegment, v, false); float scale = v >= aSegmentScales.Count ? 1 : aSegmentScales[v]; if (fill == Ferr2DT_FillMode.None) { result.Add(aSegment[v] + new Vector2(norm.x * surfaceOffset[(int)Ferr2DT_TerrainDirection.Top], norm.y * surfaceOffset[(int)Ferr2DT_TerrainDirection.Top]) * scale); result[v] += new Vector2(norm.x * -surfaceOffset[(int)Ferr2DT_TerrainDirection.Bottom], norm.y * -surfaceOffset[(int)Ferr2DT_TerrainDirection.Bottom]) * scale; } else { float dist = surfaceOffset[(int)aDir]; Vector2 offset = new Vector2(dist, dist); result[v] += new Vector2(norm.x * -offset.x, norm.y * -offset.y) * scale; } } return(result); }
private List <Vector2> LegacyOffsetColliderVerts(List <Vector2> aSegment, List <float> aSegmentScales, Ferr2DT_TerrainDirection aDir) { List <Vector2> result = new List <Vector2>(aSegment); int count = aSegment.Count; for (int v = count - 1; v >= 0; v--) { Vector2 norm = smoothPath ? Ferr2D_Path.HermiteGetNormal(aSegment, v, 0, false) : Ferr2D_Path.GetNormal(aSegment, v, false); Vector2 segNormal = Ferr2D_Path.GetSegmentNormal(v, aSegment, false); float scale = v >= aSegmentScales.Count ? 1 : aSegmentScales[v]; float rootScale = smoothPath ? 1 : 1f / Mathf.Abs(Mathf.Cos(Vector2.Angle(-segNormal, norm) * Mathf.Deg2Rad)); scale = scale * rootScale; if (fill == Ferr2DT_FillMode.None) { result.Add(aSegment[v] + new Vector2(norm.x * surfaceOffset[(int)Ferr2DT_TerrainDirection.Top], norm.y * surfaceOffset[(int)Ferr2DT_TerrainDirection.Top]) * scale); result[v] += new Vector2(norm.x * -surfaceOffset[(int)Ferr2DT_TerrainDirection.Bottom], norm.y * -surfaceOffset[(int)Ferr2DT_TerrainDirection.Bottom]) * scale; } else { float dist = surfaceOffset[(int)aDir]; Vector2 offset = new Vector2(dist, dist); result[v] += new Vector2(norm.x * -offset.x, norm.y * -offset.y) * scale; } } return(result); }
void OnSceneGUI() { Ferr2DT_PathTerrain collider = (Ferr2DT_PathTerrain)target; Ferr2D_Path path = collider.gameObject.GetComponent <Ferr2D_Path>(); EditorUtility.SetSelectedWireframeHidden(collider.gameObject.renderer, Ferr_Menu.HideMeshes); if (collider.enabled == false || path == null || path.pathVerts.Count <= 1 || !collider.createCollider) { return; } Handles.color = new Color(0, 1, 0, 1); List <Vector2> verts = path.GetVerts(collider.smoothPath, collider.splitDist, collider.splitCorners); if (path.closed && collider.smoothPath == false) { verts.Add(verts[0]); } Vector2 norm = Ferr2D_Path.GetNormal(verts, 0, path.closed); Vector2 tmp = Vector2.zero; Vector2 tmpBottom = Vector2.zero; if (collider.fill == Ferr2DT_FillMode.None) { tmp = verts[0] + new Vector2(norm.x * -collider.surfaceOffset[(int)Ferr2DT_TerrainDirection.Top], norm.y * -collider.surfaceOffset[(int)Ferr2DT_TerrainDirection.Top]); tmpBottom = verts[0] + new Vector2(norm.x * collider.surfaceOffset[(int)Ferr2DT_TerrainDirection.Bottom], norm.y * collider.surfaceOffset[(int)Ferr2DT_TerrainDirection.Bottom]); } else { Vector2 offset = collider.GetOffset(path.pathVerts, 0, path.closed); tmp = verts[0] + new Vector2(norm.x * -offset.x, norm.y * -offset.y); } Vector3 startPos = path.gameObject.transform.position + Ferr2D_PathEditor.offset + Vector3.Scale(new Vector3(tmp.x, tmp.y, 0), path.transform.localScale); Vector3 currBottom = path.gameObject.transform.position + Ferr2D_PathEditor.offset + Vector3.Scale(new Vector3(tmpBottom.x, tmpBottom.y, 0), path.transform.localScale); Vector3 curr = startPos; if (collider.fill == Ferr2DT_FillMode.None) { Handles.DrawLine(curr, currBottom); } for (int i = 0; i < verts.Count - 1; i++) { norm = Ferr2D_Path.GetNormal(verts, i + 1, path.closed); if (collider.fill == Ferr2DT_FillMode.None) { tmp = verts[i + 1] + new Vector2(norm.x * -collider.surfaceOffset[(int)Ferr2DT_TerrainDirection.Top], norm.y * -collider.surfaceOffset[(int)Ferr2DT_TerrainDirection.Top]); tmpBottom = verts[i + 1] + new Vector2(norm.x * collider.surfaceOffset[(int)Ferr2DT_TerrainDirection.Bottom], norm.y * collider.surfaceOffset[(int)Ferr2DT_TerrainDirection.Bottom]); Vector3 pos = path.gameObject.transform.position + Ferr2D_PathEditor.offset + Vector3.Scale(new Vector3(tmp.x, tmp.y, 0), path.transform.localScale); Vector3 posBottom = path.gameObject.transform.position + Ferr2D_PathEditor.offset + Vector3.Scale(new Vector3(tmpBottom.x, tmpBottom.y, 0), path.transform.localScale); if (ColliderNormValid(collider, verts[i], verts[i + 1])) { Handles.DrawLine(curr, pos); } if (ColliderNormValid(collider, verts[i + 1], verts[i])) { Handles.DrawLine(currBottom, posBottom); } curr = pos; currBottom = posBottom; } else { Vector2 offset = collider.GetOffset(verts, i + 1, path.closed); tmp = verts[i + 1] + new Vector2(norm.x * -offset.x, norm.y * -offset.y); Vector3 pos = path.gameObject.transform.position + Ferr2D_PathEditor.offset + Vector3.Scale(new Vector3(tmp.x, tmp.y, 0), path.transform.localScale); if (i + 1 == verts.Count - 1 && path.closed) { pos = startPos; } if (ColliderNormValid(collider, verts[i], verts[i + 1])) { Handles.DrawLine(curr, pos); } curr = pos; } } if (collider.fill == Ferr2DT_FillMode.None) { Handles.DrawLine(curr, currBottom); } if (collider.fill == Ferr2DT_FillMode.Skirt || collider.fill == Ferr2DT_FillMode.FillOnlySkirt) { Vector3 start = startPos; Vector3 end = curr; Vector3 skirtStart = new Vector3(start.x, collider.transform.position.y + collider.fillY, start.z); Vector3 skirtEnd = new Vector3(end.x, collider.transform.position.y + collider.fillY, end.z); Handles.DrawLine(start, skirtStart); Handles.DrawLine(skirtStart, skirtEnd); Handles.DrawLine(skirtEnd, end); } }