public FerrTerrainBuilder(List<Polygon2D> polygons, Ferr2D_Path ferrPathPrototype, float cellWidth, float cellHeight) { this.polygons = polygons; this.ferrPathPrototype = ferrPathPrototype; this.cellWidth = cellWidth; this.cellHeight = cellHeight; }
public FerrTerrainBuilder(List<Polygon2D> polygons, Ferr2D_Path ferrPathPrototype, Vector2 entranceCell, Vector2 exitCell, float cellWidth, float cellHeight, bool randomizeVertexColor = false) { this.polygons = polygons; this.ferrPathPrototype = ferrPathPrototype; this.cellWidth = cellWidth; this.cellHeight = cellHeight; this.entrancePoint.x = cellWidth * entranceCell.x; this.entrancePoint.y = cellHeight * entranceCell.y; this.exitPoint.x = cellWidth * exitCell.x; this.exitPoint.y = cellHeight * exitCell.y; this.randomizeVertexColor = randomizeVertexColor; }
private void OnSceneGUI() { if (!Ferr2DT_PathTerrain.showGUI) { return; } Ferr2D_Path path = (Ferr2D_Path)target; Ferr2DT_PathTerrain terrain = path.GetComponent <Ferr2DT_PathTerrain>(); GUIStyle iconStyle = new GUIStyle(); iconStyle.alignment = TextAnchor.MiddleCenter; snap = new Vector3(EditorPrefs.GetFloat("MoveSnapX", 1), EditorPrefs.GetFloat("MoveSnapY", 1), EditorPrefs.GetFloat("MoveSnapZ", 1)); // setup undoing things Undo.RecordObject(target, "Modified Path"); if (Event.current.type == EventType.Repaint && terrain != null) { Ferr2DT_PathTerrainEditor.DrawColliderEdge(terrain); } // draw the path line if (Event.current.type == EventType.Repaint) { DoPath(path); } // Check for drag-selecting multiple points DragSelect(path); // do adding verts in when the shift key is down! if (Event.current.shift && !Event.current.control) { DoShiftAdd(path, iconStyle); } // draw and interact with all the path handles DoHandles(path, iconStyle); // if this was an undo, refresh stuff too if (Event.current.type == EventType.ValidateCommand) { switch (Event.current.commandName) { case "UndoRedoPerformed": // Only rebuild this from an undo if the inspector is not visible. UnityEngine.Object[] objs = Resources.FindObjectsOfTypeAll(Type.GetType("UnityEditor.InspectorWindow, UnityEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", true)); if (objs == null || objs.Length == 0) { path.UpdateDependants(true); if (OnChanged != null) { OnChanged(); } } break; } } // update everything that relies on this path, if the GUI changed if (GUI.changed) { if (PrefabUtility.GetCorrespondingObjectFromSource(target) != null) { NudgeArray(pathVerts); serializedObject.ApplyModifiedProperties(); } UpdateDependentsSmart(path, false, false); EditorUtility.SetDirty(target); prevChanged = true; } else if (Event.current.type == EventType.Used) { if (prevChanged == true) { UpdateDependentsSmart(path, false, true); } prevChanged = false; } }
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) * Ferr2D_Visual.HandleSize, 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 = Ferr2D_Visual.IndicesColor; Handles.Label(labelPos, "" + i); Handles.color = Ferr2D_Visual.HandleColor; } if (!Ferr2DT_SceneOverlay.segmentLockMode) { float scale = HandleScale(pos) * Ferr2D_Visual.SmallHandleSize; 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) * Ferr2D_Visual.HandleSize; 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) { Handles.color = new Color(1, 1, 1, 0); for (int i = 0; i < path.pathVerts.Count; i++) { Vector3 pos = path.transform.position + new Vector3(path.pathVerts[i].x, path.pathVerts[i].y, 0); // check if we want to remove points if (Event.current.control) { if (Handles.Button(pos + offset, Quaternion.identity, 0.6f, 0.6f, Handles.CircleCap)) { path.pathVerts.RemoveAt(i); i--; GUI.changed = true; } if (SetScale(pos + offset, texMinus, ref iconStyle)) Handles.Label(pos + offset, new GUIContent(texMinus), iconStyle); } else { // check for moving the point if (SetScale(pos + offset, texMinus, ref iconStyle)) Handles.Label(pos + offset, new GUIContent(texDot), iconStyle); Vector3 result = Handles.FreeMoveHandle( pos + offset, Quaternion.identity, 0.6f, Vector3.zero, Handles.CircleCap); path.pathVerts[i] = new Vector2( result.x - path.transform.position.x, result.y - path.transform.position.y); // 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 + new Vector3(path.pathVerts[index].x, path.pathVerts[index].y, 0); Vector3 mid = (pos + pos2) / 2; if (Handles.Button(mid + offset, Quaternion.identity, 0.4f, 0.4f, Handles.CircleCap)) { path.pathVerts.Insert(index, new Vector2(mid.x - path.transform.position.x, mid.y - path.transform.position.y)); } if (SetScale(mid + offset, texDotPlus, ref iconStyle)) Handles.Label(mid + offset, new GUIContent(texDotPlus), iconStyle); } } } }
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 UpdateDependentsSmart(Ferr2D_Path aPath, bool aForce, bool aFullUpdate) { if (aForce || Ferr2DT_Menu.UpdateTerrainSkipFrames == 0 || updateCount % Ferr2DT_Menu.UpdateTerrainSkipFrames == 0) { aPath.UpdateDependants(aFullUpdate); if (Application.isPlaying) aPath.UpdateColliders(); if (OnChanged != null) OnChanged(); } updateCount += 1; }
private void DoShiftAdd (Ferr2D_Path path, GUIStyle iconStyle) { Vector3 snap = Event.current.control ? new Vector3(EditorPrefs.GetFloat("MoveSnapX"), EditorPrefs.GetFloat("MoveSnapY"), EditorPrefs.GetFloat("MoveSnapZ")) : Vector3.zero; Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent<Ferr2DT_PathTerrain>(); Transform transform = path.transform; Transform camTransform = SceneView.lastActiveSceneView.camera.transform; Vector3 pos = transform.InverseTransformPoint( GetMousePos(Event.current.mousePosition, transform) ); bool hasDummy = path.pathVerts.Count <= 0; if (hasDummy) path.pathVerts.Add(Vector2.zero); int closestID = path.GetClosestSeg(pos); int secondID = closestID + 1 >= path.Count ? 0 : closestID + 1; float firstDist = Vector2.Distance(pos, path.pathVerts[closestID]); float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]); Vector3 local = pos; if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapLocal ) local = SnapVector(local, snap); Vector3 global = transform.TransformPoint(pos); if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapGlobal) global = SnapVector(global, snap); Handles.color = Color.white; if (!(secondID == 0 && !path.closed && firstDist > secondDist)) { Handles.DrawLine( global, transform.TransformPoint(path.pathVerts[closestID])); } if (!(secondID == 0 && !path.closed && firstDist < secondDist)) { Handles.DrawLine( global, transform.TransformPoint(path.pathVerts[secondID])); } Handles.color = new Color(1, 1, 1, 1); Vector3 handlePos = transform.TransformPoint(pos); float scale = HandleScale(handlePos); if (Handles.Button(handlePos, camTransform.rotation, scale, scale, CapDotPlus)) { Vector3 finalPos = transform.InverseTransformPoint(global); if (secondID == 0) { if (firstDist < secondDist) { if (terrain) terrain.AddPoint(finalPos); else path.pathVerts.Add(finalPos); } else { if (terrain) terrain.AddPoint(finalPos, 0); else path.pathVerts.Insert(0, finalPos); } } else { if (terrain) terrain.AddPoint(finalPos, Mathf.Max(closestID, secondID)); else path.pathVerts.Insert(Mathf.Max(closestID, secondID), finalPos); } selectedPoints.Clear(); GUI.changed = true; } if (hasDummy) path.pathVerts.RemoveAt(0); }
private void DoPath (Ferr2D_Path path) { Handles.color = Color.white; Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent<Ferr2DT_PathTerrain>(); List<Vector2> verts = terrain == null ? path.GetVertsRaw() : path.GetVerts(false, 2, terrain.splitCorners); for (int i = 0; i < verts.Count - 1; i++) { Vector3 pos = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[i ].x, verts[i ].y, 0), path.transform.localScale); Vector3 pos2 = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[i + 1].x, verts[i + 1].y, 0), path.transform.localScale); Handles.DrawLine(pos + offset, pos2 + offset); } if (path.closed) { Vector3 pos = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[0 ].x, verts[0 ].y, 0), path.transform.localScale); Vector3 pos2 = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[verts.Count - 1].x, verts[verts.Count - 1].y, 0), path.transform.localScale); Handles.DrawLine(pos + offset, pos2 + offset); } }
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 DoHandles(Ferr2D_Path path, GUIStyle iconStyle) { #if FERR2D_TERRAIN Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent <Ferr2DT_PathTerrain>(); if (terrain) { terrain.MatchOverrides(); } #endif Handles.color = new Color(1, 1, 1, 0); for (int i = 0; i < path.pathVerts.Count; i++) { Vector3 pos = path.transform.position + Vector3.Scale(new Vector3(path.pathVerts[i].x, path.pathVerts[i].y, 0), path.transform.localScale); // check if we want to remove points if (Event.current.control) { if (Handles.Button(pos + offset, Quaternion.identity, HandleScale(pos + offset), HandleScale(pos + offset), Handles.CircleCap)) { path.pathVerts.RemoveAt(i); #if FERR2D_TERRAIN if (terrain) { terrain.directionOverrides.RemoveAt(i); } #endif i--; GUI.changed = true; } if (SetScale(pos + offset, texMinus, ref iconStyle)) { Handles.Label(pos + offset, new GUIContent(texMinus), iconStyle); } } else { // check for moving the point if (SetScale(pos + offset, texMinus, ref iconStyle)) { Handles.Label(pos + offset, new GUIContent(texDot), iconStyle); } Vector3 result = Handles.FreeMoveHandle( pos + offset, Quaternion.identity, HandleScale(pos + offset), Vector3.zero, Handles.CircleCap); path.pathVerts[i] = new Vector2( (result.x - path.transform.position.x) / path.transform.localScale.x, (result.y - path.transform.position.y) / path.transform.localScale.y); // if using terrain, check to see for any edge overrides #if FERR2D_TERRAIN if (terrain && i + 1 < path.pathVerts.Count) { float scale = HandleScale(pos + offset) * 0.5f; Vector3 dirOff = Vector3.zero; if (i + 1 < path.pathVerts.Count || path.closed == true) { int index = path.closed && i + 1 == path.pathVerts.Count ? 0 : i + 1; Vector3 delta = path.pathVerts[index] - path.pathVerts[i]; delta.Normalize(); Vector3 norm = new Vector3(-delta.y, delta.x, 0); dirOff = delta * scale * 3 + new Vector3(norm.x, norm.y, 0) * scale * 2; } if (SetScale(pos + offset + dirOff, texMinus, ref iconStyle, 0.5f)) { Handles.Label(pos + offset + dirOff, new GUIContent(GetDirIcon(terrain.directionOverrides[i])), iconStyle); } if (Handles.Button(pos + offset + dirOff, Quaternion.identity, scale, scale, Handles.CircleCap)) { terrain.directionOverrides[i] = NextDir(terrain.directionOverrides[i]); GUI.changed = true; } } #endif // 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 + Vector3.Scale(new Vector3(path.pathVerts[index].x, path.pathVerts[index].y, 0), path.transform.localScale); Vector3 mid = (pos + pos2) / 2; if (Handles.Button(mid + offset, Quaternion.identity, HandleScale(mid + offset), HandleScale(mid + offset), Handles.CircleCap)) { path.pathVerts.Insert(index, new Vector2((mid.x - path.transform.position.x) / path.transform.localScale.x, (mid.y - path.transform.position.y) / path.transform.localScale.y)); #if FERR2D_TERRAIN if (terrain) { terrain.directionOverrides.Insert(index, Ferr2DT_TerrainDirection.None); } #endif } if (SetScale(mid + offset, texDotPlus, ref iconStyle)) { Handles.Label(mid + offset, new GUIContent(texDotPlus), iconStyle); } } } } }
private void DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle) { #if FERR2D_TERRAIN Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent<Ferr2DT_PathTerrain>(); #endif Quaternion inv = Quaternion.Inverse(path.transform.rotation); Vector2 pos = GetMousePos(Event.current.mousePosition, path.transform.position.z) - new Vector2(path.transform.position.x, path.transform.position.y); bool hasDummy = path.pathVerts.Count <= 0; if (hasDummy) path.pathVerts.Add(Vector2.zero); int closestID = path.GetClosestSeg(inv * new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y)); int secondID = closestID + 1 >= path.Count ? 0 : closestID + 1; float firstDist = Vector2.Distance(pos, path.pathVerts[closestID]); float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]); Vector3 local = pos; if (Ferr_Menu.SnapMode == Ferr2DT_SnapMode.Local ) local = SnapVector(local ); Vector3 global = path.transform.position + local; if (Ferr_Menu.SnapMode == Ferr2DT_SnapMode.Global) global = SnapVector(global); Handles.color = Color.white; if (!(secondID == 0 && !path.closed && firstDist > secondDist)) { Handles.DrawLine( global, path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[closestID].x, path.pathVerts[closestID].y, 0), path.transform.localScale)); } if (!(secondID == 0 && !path.closed && firstDist < secondDist)) { Handles.DrawLine( global, path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[secondID].x, path.pathVerts[secondID].y, 0), path.transform.localScale)); } Handles.color = new Color(1, 1, 1, 0); Vector3 handlePos = new Vector3(pos.x, pos.y, 0) + path.transform.position + offset; if (Handles.Button(handlePos, Quaternion.identity, HandleScale(handlePos), HandleScale(handlePos), Handles.CircleCap)) { Vector3 finalPos = inv * (new Vector3(global.x / path.transform.localScale.x, global.y / path.transform.localScale.y, 0) - path.transform.position); if (secondID == 0) { if (firstDist < secondDist) { path.pathVerts.Add(finalPos); #if FERR2D_TERRAIN if (terrain) terrain.directionOverrides.Add(Ferr2DT_TerrainDirection.None); #endif } else { path.pathVerts.Insert(0, finalPos); #if FERR2D_TERRAIN if (terrain) terrain.directionOverrides.Insert(0, Ferr2DT_TerrainDirection.None); #endif } } else { path.pathVerts.Insert(Mathf.Max(closestID, secondID), finalPos); #if FERR2D_TERRAIN if (terrain) terrain.directionOverrides.Insert(Mathf.Max(closestID, secondID), Ferr2DT_TerrainDirection.None); #endif } GUI.changed = true; } if (SetScale(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, texDotPlus, ref iconStyle)) Handles.Label(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, new GUIContent(texDotPlus), iconStyle); if (hasDummy) path.pathVerts.RemoveAt(0); }
private void DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle) { #if FERR2D_TERRAIN Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent <Ferr2DT_PathTerrain>(); #endif Vector2 pos = GetMousePos(Event.current.mousePosition, path.transform.position.z) - new Vector2(path.transform.position.x, path.transform.position.y); int closestID = path.GetClosestSeg(new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y)); int secondID = closestID + 1 >= path.Count ? 0 : closestID + 1; float firstDist = Vector2.Distance(pos, path.pathVerts[closestID]); float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]); Handles.color = Color.white; if (!(secondID == 0 && !path.closed && firstDist > secondDist)) { Handles.DrawLine( path.transform.position + new Vector3(pos.x, pos.y, 0), path.transform.position + Vector3.Scale(new Vector3(path.pathVerts[closestID].x, path.pathVerts[closestID].y, 0), path.transform.localScale)); } if (!(secondID == 0 && !path.closed && firstDist < secondDist)) { Handles.DrawLine( path.transform.position + new Vector3(pos.x, pos.y, 0), path.transform.position + Vector3.Scale(new Vector3(path.pathVerts[secondID].x, path.pathVerts[secondID].y, 0), path.transform.localScale)); } Handles.color = new Color(1, 1, 1, 0); Vector3 handlePos = new Vector3(pos.x, pos.y, 0) + path.transform.position + offset; if (Handles.Button(handlePos, Quaternion.identity, HandleScale(handlePos), HandleScale(handlePos), Handles.CircleCap)) { if (secondID == 0) { if (firstDist < secondDist) { path.pathVerts.Add(new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y)); #if FERR2D_TERRAIN if (terrain) { terrain.directionOverrides.Add(Ferr2DT_TerrainDirection.None); } #endif } else { path.pathVerts.Insert(0, new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y)); #if FERR2D_TERRAIN if (terrain) { terrain.directionOverrides.Insert(0, Ferr2DT_TerrainDirection.None); } #endif } } else { path.pathVerts.Insert(Mathf.Max(closestID, secondID), new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y)); #if FERR2D_TERRAIN if (terrain) { terrain.directionOverrides.Insert(Mathf.Max(closestID, secondID), Ferr2DT_TerrainDirection.None); } #endif } GUI.changed = true; } if (SetScale(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, texDotPlus, ref iconStyle)) { Handles.Label(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, new GUIContent(texDotPlus), iconStyle); } }
private void AddEdge() { // split the path into segments based on the split angle List <List <int> > segments = new List <List <int> >(); List <Ferr2DT_TerrainDirection> dirs = new List <Ferr2DT_TerrainDirection>(); List <int> order = new List <int>(); segments = GetSegments(Path.GetVertsRaw(), out dirs); if (dirs.Count < segments.Count) { dirs.Add(directionOverrides[directionOverrides.Count - 1]); } for (int i = 0; i < segments.Count; i++) { order.Add(i); } order.Sort( new Ferr_LambdaComparer <int>( (x, y) => { Ferr2DT_TerrainDirection dirx = dirs[x] == Ferr2DT_TerrainDirection.None ? Ferr2D_Path.GetDirection(Path.pathVerts, segments[x], 0, fill == Ferr2DT_FillMode.InvertedClosed) : dirs[x]; Ferr2DT_TerrainDirection diry = dirs[y] == Ferr2DT_TerrainDirection.None ? Ferr2D_Path.GetDirection(Path.pathVerts, segments[y], 0, fill == Ferr2DT_FillMode.InvertedClosed) : dirs[y]; return(terrainMaterial.GetDescriptor(diry).zOffset.CompareTo(terrainMaterial.GetDescriptor(dirx).zOffset)); } )); // process the segments into meshes for (int i = 0; i < order.Count; i++) { AddSegment(Ferr2D_Path.IndicesToPath(Path.pathVerts, segments[order[i]]), GetScalesFromIndices(segments[order[i]]), order.Count <= 1 && Path.closed, smoothPath, dirs[order[i]]); } }
private void DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle) { Vector2 pos = GetMousePos(Event.current.mousePosition, path.transform.position.z) - new Vector2(path.transform.position.x, path.transform.position.y); int closestID = path.GetClosestSeg(pos); int secondID = closestID + 1 >= path.Count ? 0 : closestID + 1; float firstDist = Vector2.Distance(pos, path.pathVerts[closestID]); float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]); Handles.color = Color.white; if (!(secondID == 0 && !path.closed && firstDist > secondDist)) { Handles.DrawLine( path.transform.position + new Vector3(pos.x, pos.y, 0), path.transform.position + new Vector3(path.pathVerts[closestID].x, path.pathVerts[closestID].y, 0)); } if (!(secondID == 0 && !path.closed && firstDist < secondDist)) { Handles.DrawLine( path.transform.position + new Vector3(pos.x, pos.y, 0), path.transform.position + new Vector3(path.pathVerts[secondID].x, path.pathVerts[secondID].y, 0)); } Handles.color = new Color(1, 1, 1, 0); if (Handles.Button(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, Quaternion.identity, 0.4f, 0.4f, Handles.CircleCap)) { if (secondID == 0) { if (firstDist < secondDist) { path.pathVerts.Add(new Vector2(pos.x, pos.y)); } else { path.pathVerts.Insert(0, new Vector2(pos.x, pos.y)); } } else { path.pathVerts.Insert(Mathf.Max(closestID, secondID), new Vector2(pos.x, pos.y)); } GUI.changed = true; } if (SetScale(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, texDotPlus, ref iconStyle)) Handles.Label(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, new GUIContent(texDotPlus), iconStyle); }
private Vector3 GetRelativeMovementWithSnap(Vector3 aHandlePos, Matrix4x4 aInvMat, int i, Ferr2D_Path aPath) { if (!(Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapRelative)) { aHandlePos = GetRealPoint(aHandlePos, aPath.transform); } Vector3 global = aHandlePos; if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapGlobal) { global = SnapVector(global, snap); } Vector3 local = aInvMat.MultiplyPoint3x4(global); if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapLocal) { local = SnapVector(local, snap); } if (!Event.current.control && Ferr2DT_Menu.SmartSnap) { local = SmartSnap(local, aPath.pathVerts, selectedPoints, Ferr2DT_Menu.SmartSnapDist); } return(new Vector2(local.x, local.y) - aPath.pathVerts[i]); }
private void UpdateDependentsSmart(Ferr2D_Path aPath, bool aForce) { if (aForce || Ferr_Menu.UpdateTerrainSkipFrames == 0 || updateCount % Ferr_Menu.UpdateTerrainSkipFrames == 0) { aPath.UpdateDependants(); } updateCount += 1; }
public override void OnInspectorGUI() { Undo.RecordObject(target, "Modified Path"); Ferr2D_Path path = (Ferr2D_Path)target; // if this was an undo, refresh stuff too if (Event.current.type == EventType.ValidateCommand) { switch (Event.current.commandName) { case "UndoRedoPerformed": path.UpdateDependants(true); if (OnChanged != null) { OnChanged(); } return; } } path.closed = EditorGUILayout.Toggle("Closed", path.closed); if (path) { // display the path verts list info showVerts = EditorGUILayout.Foldout(showVerts, "Path Vertices"); } EditorGUI.indentLevel = 2; if (showVerts) { int size = EditorGUILayout.IntField("Count: ", path.pathVerts.Count); while (path.pathVerts.Count > size) { path.pathVerts.RemoveAt(path.pathVerts.Count - 1); } while (path.pathVerts.Count < size) { path.pathVerts.Add(new Vector2(0, 0)); } } // draw all the verts! Long list~ for (int i = 0; showVerts && i < path.pathVerts.Count; i++) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("#" + i, GUILayout.Width(60)); path.pathVerts[i] = new Vector2( EditorGUILayout.FloatField(path.pathVerts[i].x), EditorGUILayout.FloatField(path.pathVerts[i].y)); EditorGUILayout.EndHorizontal(); } // button for updating the origin of the object if (GUILayout.Button("Center Position")) { path.ReCenter(); } bool updateClosed = false; Ferr2DT_PathTerrain terrain = path.GetComponent <Ferr2DT_PathTerrain>(); if (!path.closed && terrain != null && (terrain.fill == Ferr2DT_FillMode.Closed || terrain.fill == Ferr2DT_FillMode.InvertedClosed || terrain.fill == Ferr2DT_FillMode.FillOnlyClosed)) { path.closed = true; updateClosed = true; } if (terrain != null && path.closed && (terrain.fill == Ferr2DT_FillMode.FillOnlySkirt || terrain.fill == Ferr2DT_FillMode.Skirt)) { path.closed = false; updateClosed = true; } // update dependants when it changes if (GUI.changed || updateClosed) { path.UpdateDependants(false); EditorUtility.SetDirty(target); } }
private void DoHandles (Ferr2D_Path path, GUIStyle iconStyle) { #if FERR2D_TERRAIN Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent<Ferr2DT_PathTerrain>(); if (terrain) terrain.MatchOverrides(); #endif 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); // check if we want to remove points if (Event.current.control) { if (Handles.Button(pos + offset, Quaternion.identity, HandleScale(pos+offset), HandleScale(pos+offset), Handles.CircleCap)) { path.pathVerts.RemoveAt(i); #if FERR2D_TERRAIN if (terrain) terrain.directionOverrides.RemoveAt(i); #endif i--; GUI.changed = true; } if (SetScale(pos + offset, texMinus, ref iconStyle)) Handles.Label(pos + offset, new GUIContent(texMinus), iconStyle); } else { // check for moving the point if (SetScale(pos + offset, texMinus, ref iconStyle)) Handles.Label(pos + offset, new GUIContent(texDot), iconStyle); Vector3 result = Handles.FreeMoveHandle( pos + offset, Quaternion.identity, HandleScale(pos+offset), Vector3.zero, Handles.CircleCap); Vector3 global = (result - offset); if (Ferr_Menu.SnapMode == Ferr2DT_SnapMode.Global) global = SnapVector(global); Vector3 local = inv * (global - path.transform.position); if (Ferr_Menu.SnapMode == Ferr2DT_SnapMode.Local ) local = SnapVector(local); path.pathVerts[i] = new Vector2( local.x / path.transform.localScale.x, local.y / path.transform.localScale.y); // if using terrain, check to see for any edge overrides #if FERR2D_TERRAIN if (terrain && i+1 < path.pathVerts.Count) { float scale = HandleScale(pos+offset) * 0.5f; Vector3 dirOff = Vector3.zero; if (i + 1 < path.pathVerts.Count || path.closed == true) { int index = path.closed && i + 1 == path.pathVerts.Count ? 0 : i + 1; Vector3 delta = path.pathVerts[index] - path.pathVerts[i]; delta.Normalize(); Vector3 norm = new Vector3(-delta.y, delta.x, 0); dirOff = delta * scale * 3 + new Vector3(norm.x, norm.y, 0) * scale * 2; } if (SetScale(pos + offset + dirOff, texMinus, ref iconStyle, 0.5f)) Handles.Label(pos + offset + dirOff, new GUIContent(GetDirIcon(terrain.directionOverrides[i])), iconStyle); if (Handles.Button( pos + offset + dirOff, Quaternion.identity, scale, scale, Handles.CircleCap)) { terrain.directionOverrides[i] = NextDir(terrain.directionOverrides[i]); GUI.changed = true; } } #endif // 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; if (Handles.Button(mid + offset, Quaternion.identity, HandleScale(mid+offset), HandleScale(mid+offset), Handles.CircleCap)) { path.pathVerts.Insert(index, inv * new Vector2((mid.x - path.transform.position.x) / path.transform.localScale.x, (mid.y - path.transform.position.y) / path.transform.localScale.y)); #if FERR2D_TERRAIN if (terrain) terrain.directionOverrides.Insert(index, Ferr2DT_TerrainDirection.None); #endif } if (SetScale(mid + offset, texDotPlus, ref iconStyle)) Handles.Label(mid + offset, new GUIContent(texDotPlus), iconStyle); } } } }
/// <summary> /// The Ferr2DT_IPath method, gets called automatically whenever the Ferr2DT path gets updated in the /// editor. This will completely recreate the the visual mesh (only) for the terrain. If you want /// To recreate the collider as well, that's a separate call to RecreateCollider. /// </summary> public void RecreatePath() { //System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); //sw.Start(); if (path == null) { path = GetComponent <Ferr2D_Path> (); } if (dMesh == null) { dMesh = new Ferr2DT_DynamicMesh(); } if (terrainMaterial == null) { Debug.LogWarning("Cannot create terrain without a Terrain Material!"); return; } MatchOverrides(); // double check the materials! ForceMaterial(terrainMaterial, true, false); dMesh.Clear(); dMesh.color = vertexColor; if (path.Count < 2) { GetComponent <MeshFilter>().sharedMesh = null; return; } // make sure we can keep a consistent scale for the texture if (terrainMaterial.edgeMaterial.mainTexture != null && terrainMaterial.edgeMaterial.mainTexture != null) { unitsPerUV.x = terrainMaterial.edgeMaterial.mainTexture.width / pixelsPerUnit; unitsPerUV.y = terrainMaterial.edgeMaterial.mainTexture.height / pixelsPerUnit; } if (fill != Ferr2DT_FillMode.FillOnlyClosed && fill != Ferr2DT_FillMode.FillOnlySkirt) { // split the path into segments based on the split angle List <List <Vector2> > segments = new List <List <Vector2> > (); List <Ferr2DT_TerrainDirection> dirs = new List <Ferr2DT_TerrainDirection>(); segments = GetSegments(path.GetVerts(smoothPath, splitDist, splitCorners), out dirs); if (dirs.Count < segments.Count) { dirs.Add(directionOverrides[directionOverrides.Count - 1]); } List <int> order = new List <int>(); for (int i = 0; i < segments.Count; i++) { order.Add(i); } order.Sort( new Ferr2DT_Comparer <int>( (x, y) => GetDescription(segments[y]).zOffset.CompareTo(GetDescription(segments[x]).zOffset) )); // process the segments into meshes for (int i = 0; i < order.Count; i++) { AddSegment(segments[order[i]], order.Count <= 1 && path.closed, dirs[order[i]]); } } int[] submesh1 = dMesh.GetCurrentTriangleList(); // add a fill if the user desires if ((fill == Ferr2DT_FillMode.Skirt || fill == Ferr2DT_FillMode.FillOnlySkirt) && terrainMaterial.fillMaterial != null) { AddFill(true); } else if ((fill == Ferr2DT_FillMode.Closed || fill == Ferr2DT_FillMode.InvertedClosed || fill == Ferr2DT_FillMode.FillOnlyClosed) && terrainMaterial.fillMaterial != null) { AddFill(false); } else if (fill == Ferr2DT_FillMode.None) { } int[] submesh2 = dMesh.GetCurrentTriangleList(submesh1.Length); // compile the mesh! Mesh m = GetComponent <MeshFilter>().sharedMesh; string name = "Ferr2DT_PathMesh_" + gameObject.name + gameObject.GetInstanceID(); if (m == null || m.name != name) { GetComponent <MeshFilter>().sharedMesh = m = new Mesh(); m.name = name; } dMesh.Build(ref m); // set up submeshes and submaterials m.subMeshCount = 2; if (renderer.sharedMaterials.Length < 2) { Material[] old = renderer.sharedMaterials; renderer.sharedMaterials = new Material[2]; if (old.Length > 0) { renderer.sharedMaterials[0] = old[0]; } } m.SetTriangles(submesh1, 1); m.SetTriangles(submesh2, 0); //sw.Stop(); //Debug.Log("Creating mesh took: " + sw.Elapsed.TotalMilliseconds + "ms"); }
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 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 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 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 = 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.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 = 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)) { 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.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) { 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]; 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)) { 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.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 = 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 (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 DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle) { #if FERR2D_TERRAIN Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent<Ferr2DT_PathTerrain>(); #endif Vector2 pos = GetMousePos(Event.current.mousePosition, path.transform.position.z) - new Vector2(path.transform.position.x, path.transform.position.y); int closestID = path.GetClosestSeg(new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y)); int secondID = closestID + 1 >= path.Count ? 0 : closestID + 1; float firstDist = Vector2.Distance(pos, path.pathVerts[closestID]); float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]); Handles.color = Color.white; if (!(secondID == 0 && !path.closed && firstDist > secondDist)) { Handles.DrawLine( path.transform.position + new Vector3(pos.x, pos.y, 0), path.transform.position + Vector3.Scale(new Vector3(path.pathVerts[closestID].x, path.pathVerts[closestID].y, 0), path.transform.localScale)); } if (!(secondID == 0 && !path.closed && firstDist < secondDist)) { Handles.DrawLine( path.transform.position + new Vector3(pos.x, pos.y, 0), path.transform.position + Vector3.Scale(new Vector3(path.pathVerts[secondID].x, path.pathVerts[secondID].y, 0), path.transform.localScale)); } Handles.color = new Color(1, 1, 1, 0); Vector3 handlePos = new Vector3(pos.x, pos.y, 0) + path.transform.position + offset; if (Handles.Button(handlePos, Quaternion.identity, HandleScale(handlePos), HandleScale(handlePos), Handles.CircleCap)) { if (secondID == 0) { if (firstDist < secondDist) { path.pathVerts.Add(new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y)); #if FERR2D_TERRAIN if (terrain) terrain.directionOverrides.Add(Ferr2DT_TerrainDirection.None); #endif } else { path.pathVerts.Insert(0, new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y)); #if FERR2D_TERRAIN if (terrain) terrain.directionOverrides.Insert(0, Ferr2DT_TerrainDirection.None); #endif } } else { path.pathVerts.Insert(Mathf.Max(closestID, secondID), new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y)); #if FERR2D_TERRAIN if (terrain) terrain.directionOverrides.Insert(Mathf.Max(closestID, secondID), Ferr2DT_TerrainDirection.None); #endif } GUI.changed = true; } if (SetScale(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, texDotPlus, ref iconStyle)) Handles.Label(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, new GUIContent(texDotPlus), iconStyle); }
private void AddEdge() { // split the path into segments based on the split angle List <List <int> > segments = new List <List <int> >(); List <Ferr2DT_TerrainDirection> dirs = new List <Ferr2DT_TerrainDirection>(); List <int> order = new List <int>(); segments = GetSegments(Path.GetVertsRaw(), out dirs); if (dirs.Count < segments.Count) { dirs.Add(directionOverrides[directionOverrides.Count - 1]); } for (int i = 0; i < segments.Count; i++) { order.Add(i); } order.Sort( new Ferr.LambdaComparer <int>( (x, y) => { Ferr2DT_TerrainDirection dirx = dirs[x] == Ferr2DT_TerrainDirection.None ? Ferr2D_Path.GetDirection(Path.pathVerts, segments[x], 0, fill == Ferr2DT_FillMode.InvertedClosed) : dirs[x]; Ferr2DT_TerrainDirection diry = dirs[y] == Ferr2DT_TerrainDirection.None ? Ferr2D_Path.GetDirection(Path.pathVerts, segments[y], 0, fill == Ferr2DT_FillMode.InvertedClosed) : dirs[y]; return(terrainMaterial.GetDescriptor(diry).zOffset.CompareTo(terrainMaterial.GetDescriptor(dirx).zOffset)); } )); // process the segments into meshes for (int i = 0; i < order.Count; i++) { List <int> currSeg = segments[order[i]]; List <int> prevSeg = order[i] - 1 < 0 ? segments[segments.Count - 1] : segments[order[i] - 1]; List <int> nextSeg = segments[(order[i] + 1) % segments.Count]; int curr = currSeg[0]; int prev = prevSeg[prevSeg.Count - 2]; int next = currSeg[1]; Vector2 p1 = Path.pathVerts[prev] - Path.pathVerts[curr]; Vector2 p2 = Path.pathVerts[next] - Path.pathVerts[curr]; bool leftInner = Mathf.Atan2(p1.x * p2.y - p1.y * p2.x, Vector2.Dot(p1, p2)) < 0; curr = currSeg[currSeg.Count - 1]; prev = currSeg[currSeg.Count - 2]; next = nextSeg[1]; p1 = Path.pathVerts[prev] - Path.pathVerts[curr]; p2 = Path.pathVerts[next] - Path.pathVerts[curr]; bool rightInner = Mathf.Atan2(p1.x * p2.y - p1.y * p2.x, Vector2.Dot(p1, p2)) < 0; AddSegment(Ferr2D_Path.IndicesToPath(Path.pathVerts, segments[order[i]]), leftInner, rightInner, GetScalesFromIndices(segments[order[i]]), order.Count <= 1 && Path.closed, smoothPath, dirs[order[i]]); } }
private void DoPath(Ferr2D_Path path) { Handles.color = Color.white; List<Vector2> verts = path.GetVertsRaw(); for (int i = 0; i < verts.Count - 1; i++) { Vector3 pos = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[i ].x, verts[i ].y, 0), path.transform.localScale); Vector3 pos2 = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[i + 1].x, verts[i + 1].y, 0), path.transform.localScale); Handles.DrawLine(pos + offset, pos2 + offset); } if (path.closed) { Vector3 pos = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[0 ].x, verts[0 ].y, 0), path.transform.localScale); Vector3 pos2 = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[verts.Count - 1].x, verts[verts.Count - 1].y, 0), path.transform.localScale); Handles.DrawLine(pos + offset, pos2 + offset); } }
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 DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle) { Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent<Ferr2DT_PathTerrain>(); Quaternion inv = Quaternion.Inverse(path.transform.rotation); Vector2 pos = GetMousePos(Event.current.mousePosition, path.transform.position.z) - new Vector2(path.transform.position.x, path.transform.position.y); bool hasDummy = path.pathVerts.Count <= 0; if (hasDummy) path.pathVerts.Add(Vector2.zero); int closestID = path.GetClosestSeg(inv * new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y)); int secondID = closestID + 1 >= path.Count ? 0 : closestID + 1; float firstDist = Vector2.Distance(pos, path.pathVerts[closestID]); float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]); Vector3 local = pos; if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapLocal ) local = SnapVector(local ); Vector3 global = path.transform.position + local; if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapGlobal) global = SnapVector(global); Handles.color = Color.white; if (!(secondID == 0 && !path.closed && firstDist > secondDist)) { Handles.DrawLine( global, path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[closestID].x, path.pathVerts[closestID].y, 0), path.transform.localScale)); } if (!(secondID == 0 && !path.closed && firstDist < secondDist)) { Handles.DrawLine( global, path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[secondID].x, path.pathVerts[secondID].y, 0), path.transform.localScale)); } Handles.color = new Color(1, 1, 1, 0); Vector3 handlePos = new Vector3(pos.x, pos.y, 0) + path.transform.position + offset; if (IsVisible(handlePos)) { if (Handles.Button(handlePos, SceneView.lastActiveSceneView.camera.transform.rotation, HandleScale(handlePos), HandleScale(handlePos), Handles.CircleCap)) { Vector3 finalPos = inv * (new Vector3(global.x / path.transform.localScale.x, global.y / path.transform.localScale.y, 0) - path.transform.position); if (secondID == 0) { if (firstDist < secondDist) { if (terrain) terrain.AddPoint(finalPos); else path.pathVerts.Add(finalPos); } else { if (terrain) terrain.AddPoint(finalPos, 0); else path.pathVerts.Insert(0, finalPos); } } else { if (terrain) terrain.AddPoint(finalPos, Mathf.Max(closestID, secondID)); else path.pathVerts.Insert(Mathf.Max(closestID, secondID), finalPos); } selectedPoints.Clear(); GUI.changed = true; } SetScale(handlePos, texDotPlus, ref iconStyle); Handles.Label(handlePos, new GUIContent(texDotPlus), iconStyle); } if (hasDummy) path.pathVerts.RemoveAt(0); }
private void DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle) { Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent <Ferr2DT_PathTerrain>(); Quaternion inv = Quaternion.Inverse(path.transform.rotation); Vector2 pos = GetMousePos(Event.current.mousePosition, path.transform.position.z) - new Vector2(path.transform.position.x, path.transform.position.y); bool hasDummy = path.pathVerts.Count <= 0; if (hasDummy) { path.pathVerts.Add(Vector2.zero); } int closestID = path.GetClosestSeg(inv * new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y)); int secondID = closestID + 1 >= path.Count ? 0 : closestID + 1; float firstDist = Vector2.Distance(pos, path.pathVerts[closestID]); float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]); Vector3 local = pos; if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapLocal) { local = SnapVector(local); } Vector3 global = path.transform.position + local; if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapGlobal) { global = SnapVector(global); } Handles.color = Color.white; if (!(secondID == 0 && !path.closed && firstDist > secondDist)) { Handles.DrawLine( global, path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[closestID].x, path.pathVerts[closestID].y, 0), path.transform.localScale)); } if (!(secondID == 0 && !path.closed && firstDist < secondDist)) { Handles.DrawLine( global, path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[secondID].x, path.pathVerts[secondID].y, 0), path.transform.localScale)); } Handles.color = new Color(1, 1, 1, 0); Vector3 handlePos = new Vector3(pos.x, pos.y, 0) + path.transform.position + offset; if (IsVisible(handlePos)) { if (Handles.Button(handlePos, SceneView.lastActiveSceneView.camera.transform.rotation, HandleScale(handlePos), HandleScale(handlePos), Handles.CircleCap)) { Vector3 finalPos = inv * (new Vector3(global.x / path.transform.localScale.x, global.y / path.transform.localScale.y, 0) - path.transform.position); if (secondID == 0) { if (firstDist < secondDist) { if (terrain) { terrain.AddPoint(finalPos); } else { path.pathVerts.Add(finalPos); } } else { if (terrain) { terrain.AddPoint(finalPos, 0); } else { path.pathVerts.Insert(0, finalPos); } } } else { if (terrain) { terrain.AddPoint(finalPos, Mathf.Max(closestID, secondID)); } else { path.pathVerts.Insert(Mathf.Max(closestID, secondID), finalPos); } } if (selectedPoints != null) { selectedPoints.Clear(); } GUI.changed = true; } SetScale(handlePos, texDotPlus, ref iconStyle); Handles.Label(handlePos, new GUIContent(texDotPlus), iconStyle); } if (hasDummy) { path.pathVerts.RemoveAt(0); } }
/// <summary> /// This method will close a list of split segments, merging and adding points to the end chunks. /// </summary> /// <param name="aSegmentList">List of split segments that make up the path.</param> /// <param name="aCorners">If there are corners or not.</param> /// <returns>A closed loop of segments.</returns> public static bool CloseEnds(List <Vector2> aPath, ref List <List <int> > aSegmentList, ref List <Ferr2DT_TerrainDirection> aSegmentDirections, bool aCorners, bool aInverted) { int startID = aSegmentList[0][0]; Vector2 start = aPath[startID]; Vector2 startNext = aPath[aSegmentList[0][1]]; int endID = aSegmentList[aSegmentList.Count - 1][aSegmentList[aSegmentList.Count - 1].Count - 1]; Vector2 end = aPath[endID]; Vector2 endPrev = aPath[aSegmentList[aSegmentList.Count - 1][aSegmentList[aSegmentList.Count - 1].Count - 2]]; if (aCorners == false) { aSegmentList[0].Add(startID); return(true); } bool endCorner = Ferr2D_Path.GetDirection(endPrev, end) != Ferr2D_Path.GetDirection(end, start); bool startCorner = Ferr2D_Path.GetDirection(end, start) != Ferr2D_Path.GetDirection(start, startNext); if (endCorner && startCorner) { List <int> lastSeg = new List <int>(); lastSeg.Add(endID); lastSeg.Add(startID); aSegmentList.Add(lastSeg); Ferr2DT_TerrainDirection dir = GetDirection(start, end); if (aInverted && dir == Ferr2DT_TerrainDirection.Top) { dir = Ferr2DT_TerrainDirection.Bottom; } if (aInverted && dir == Ferr2DT_TerrainDirection.Bottom) { dir = Ferr2DT_TerrainDirection.Top; } if (aInverted && dir == Ferr2DT_TerrainDirection.Right) { dir = Ferr2DT_TerrainDirection.Left; } if (aInverted && dir == Ferr2DT_TerrainDirection.Left) { dir = Ferr2DT_TerrainDirection.Right; } aSegmentDirections.Add(dir); } else if (endCorner && !startCorner) { aSegmentList[0].Insert(0, endID); } else if (!endCorner && startCorner) { aSegmentList[aSegmentList.Count - 1].Add(startID); } else { aSegmentList[0].InsertRange(0, aSegmentList[aSegmentList.Count - 1]); aSegmentList.RemoveAt(aSegmentList.Count - 1); aSegmentDirections.RemoveAt(aSegmentDirections.Count - 1); } return(true); }
public override void OnInspectorGUI() { Ferr2D_Path path = (Ferr2D_Path)target; bool updateMesh = false; // if this was an undo, refresh stuff too if (Event.current.type == EventType.ValidateCommand) { switch (Event.current.commandName) { case "UndoRedoPerformed": path.UpdateDependants(true); if (OnChanged != null) { OnChanged(); } return; } } EditorGUILayout.PropertyField(closed); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(pathVerts, true); if (EditorGUI.EndChangeCheck() && PrefabUtility.GetCorrespondingObjectFromSource(target) != null) { NudgeArray(pathVerts); } // button for updating the origin of the object if (GUILayout.Button("Center Position")) { Undo.RecordObject(target, "Modified Path"); path.ReCenter(); updateMesh = true; } Ferr2DT_PathTerrain terrain = path.GetComponent <Ferr2DT_PathTerrain>(); if (!path.closed && (terrain.fill == Ferr2DT_FillMode.Closed || terrain.fill == Ferr2DT_FillMode.InvertedClosed || terrain.fill == Ferr2DT_FillMode.FillOnlyClosed)) { Undo.RecordObject(target, "Modified Path"); path.closed = true; updateMesh = true; } if (path.closed && (terrain.fill == Ferr2DT_FillMode.FillOnlySkirt || terrain.fill == Ferr2DT_FillMode.Skirt)) { Undo.RecordObject(target, "Modified Path"); path.closed = false; updateMesh = true; } // update dependants when it changes if (updateMesh || serializedObject.ApplyModifiedProperties()) { if (OnChanged != null) { OnChanged(); } path.UpdateDependants(true); EditorUtility.SetDirty(target); } }
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); }
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) * Ferr2D_Visual.SmallHandleSize; 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 Ferr2DT_SegmentDescription GetDescription(List <int> aSegment) { Ferr2DT_TerrainDirection dir = Ferr2D_Path.GetDirection(Path.pathVerts, aSegment, 0, fill == Ferr2DT_FillMode.InvertedClosed); return(TerrainMaterial.GetDescriptor(dir)); }
void OnTriggerExit2D(Collider2D collider) { if (collider.tag == "terrain") { if (terrainsTransform.Contains(collider.transform.position)) { return; } //for (int i = 0; i < terrainsTransform.Count; i++) { // // if (collider.transform == terrainsTransform[i]) Debug.Log(123); //} terrainsTransform.Add(collider.transform.position); exitPoint = transform.position; Vector2 diff = exitPoint - enterPoint; float pointBDiffC = Mathf.Sqrt(diff.x * diff.x + diff.y * diff.y); float diffX = 15 / pointBDiffC * diff.x; float diffY = 15 / pointBDiffC * diff.y; exitPoint = new Vector2(diffX, diffY) + enterPoint; //Debug.Log ("exit: " + collider.name + exitPoint); Ferr2D_Path terrain = collider.GetComponent <Ferr2D_Path>(); List <Vector2> pos = new List <Vector2>(); List <int> point = new List <int>(); Vector2 firstPoint = new Vector2(0, 0); Vector2 secondPoint = new Vector2(0, 0); int firstPointA = -1, secondPointA = -1; Vector2 posTemp, posA, posB; int terrainCount = terrain.Count; for (int i = 0; i < terrainCount; i++) { if (i == terrainCount - 1) { posA = terrain.pathVerts[0] + new Vector2(collider.transform.position.x, collider.transform.position.y); posB = terrain.pathVerts[i] + new Vector2(collider.transform.position.x, collider.transform.position.y); posTemp = lineIntersectPos(enterPoint, exitPoint, posA, posB); } else { posA = terrain.pathVerts[i + 1] + new Vector2(collider.transform.position.x, collider.transform.position.y); posB = terrain.pathVerts[i] + new Vector2(collider.transform.position.x, collider.transform.position.y); posTemp = lineIntersectPos(enterPoint, exitPoint, posA, posB); } if (posTemp.x != 10000) { if (Mathf.Abs(posTemp.x - posA.x) <= 0.02F && Mathf.Abs(posTemp.y - posA.y) <= 0.02F) { posTemp = posA; } if (Mathf.Abs(posTemp.x - posB.x) <= 0.02F && Mathf.Abs(posTemp.y - posB.y) <= 0.02F) { posTemp = posB; } //Debug.Log("enterPoint: " + enterPoint); //Debug.Log("exitPoint: " + exitPoint); //Debug.Log("posA: " + posA); //Debug.Log("posB: " + posB); //Debug.Log("pos: " + posTemp); pos.Add(posTemp); point.Add(i); } //Debug.Log("pos.x: " + pos.x); } //sorting float minLength = 100; List <Vector2> posSort = new List <Vector2>(); List <int> pointSort = new List <int>(); int j = -1; for (int i = 0; i < pos.Count; i++) { for (int y = 0; y < pos.Count; y++) { if ((pos[y] - enterPoint).magnitude < minLength) { minLength = (pos[y] - enterPoint).magnitude; j = y; } } minLength = 100; posSort.Add(pos[j]); pos[j] = new Vector2(100, 100); pointSort.Add(point[j]); } for (int y = 0; y < posSort.Count - 1; y += 2) { terrain = collider.GetComponent <Ferr2D_Path>(); int g = 0; if (y > 0) { //Debug.Log("terrain.pathVerts[1]: " + terrain.pathVerts[1]); //Debug.Log("posSort[y - 1]: " + posSort[y - 1]); if (terrain.pathVerts[1] == posSort[y - 1] - new Vector2(collider.transform.position.x, collider.transform.position.y)) { g = y - 1; } else { g = y - 2; } for (int q = y; q < posSort.Count; q++) { //Debug.Log ("pointSort[q]: " + pointSort[q]); //Debug.Log ("pointSort[g]: " + pointSort[g]); //Debug.Log ("g: " + g); pointSort[q] = pointSort[q] - pointSort[g] + 1; if (pointSort[q] < 0) { pointSort[q] += terrainCount; } } } firstPointA = pointSort[y]; secondPointA = pointSort[y + 1]; firstPoint = posSort[y] - new Vector2(collider.transform.position.x, collider.transform.position.y); secondPoint = posSort[y + 1] - new Vector2(collider.transform.position.x, collider.transform.position.y); //Debug.Log ("fp: " + firstPoint); //Debug.Log ("sp: " + secondPoint); bool flag = true; int i = -1; List <Vector2> firstFigure = new List <Vector2>(); List <Vector2> secondFigure = new List <Vector2>(); terrainCount = terrain.Count; //Debug.Log("pathVerts: "); //for (int e = 0; e < terrainCount; e++) Debug.Log(terrain.pathVerts[e]); while (flag) { if (i == -1) { //i = firstPointA; //Debug.Log (firstPointA); firstFigure.Add(firstPoint); //terrain.pathVerts.Add(firstPoint); //Debug.Log (secondPointA); firstFigure.Add(secondPoint); i = secondPointA + 1; } if (i >= terrainCount) { i = 0; } if (i == firstPointA) { flag = false; } //Debug.Log (i); if (terrain.pathVerts[i] != firstPoint && terrain.pathVerts[i] != secondPoint) { firstFigure.Add(terrain.pathVerts[i]); } i++; } flag = true; i = -1; while (flag) { if (i == -1) { secondFigure.Add(secondPoint); secondFigure.Add(firstPoint); i = firstPointA + 1; } if (i >= terrainCount) { i = 0; } if (i == secondPointA) { flag = false; } //Debug.Log(i); if (terrain.pathVerts[i] != firstPoint && terrain.pathVerts[i] != secondPoint) { secondFigure.Add(terrain.pathVerts[i]); } i++; } terrain.pathVerts.Clear(); if (getSq(firstFigure) >= getSq(secondFigure)) { terrain.pathVerts.AddRange(firstFigure); } else { terrain.pathVerts.AddRange(secondFigure); } //Debug.Log (terrain.pathVerts[0]); //terrain.UpdateDependants(); Ferr2DT_PathTerrain pathTerrain = collider.GetComponent <Ferr2DT_PathTerrain>(); pathTerrain.RecreatePath(); pathTerrain.RecreateCollider(); } for (int i = 0; i < gGrootClass.terrainGrootChains.Count; i++) { gGrootClass.terrainGrootChain terr = gGrootClass.terrainGrootChains[i]; if (terr.terrain == collider.gameObject) { if (!terr.terrain.GetComponent <Collider2D>().OverlapPoint(terr.chain.transform.position)) { terr.chain.transform.parent.SendMessage("OnMouseDown"); gGrootClass.terrainGrootChains.Remove(terr); i--; } } } } }
public void LegacyUpgrade() { if (!IsLegacy) { return; } #if UNITY_EDITOR UnityEditor.Undo.RecordObject(gameObject, "Upgrade Ferr2D Terrain"); #endif Ferr2D_Path oldPath = GetComponent <Ferr2D_Path>(); MatchOverrides(); // upgrade the path pathData = new Ferr2DPath(); pathData.Closed = oldPath.closed; for (int i = 0; i < oldPath.pathVerts.Count; i++) { int next = Ferr.PathUtil.WrapIndex(i - 1, Path.Count, Path.closed); Ferr.PointType pointType = Ferr.PointType.Sharp; if (smoothPath) { Ferr2DT_TerrainDirection prevSegmentDirection = Ferr2D_Path.GetDirection(Path.pathVerts, next, fill == Ferr2DT_FillMode.InvertedClosed, Path.closed, directionOverrides); Ferr2DT_TerrainDirection nextSegmentDirection = Ferr2D_Path.GetDirection(Path.pathVerts, i, fill == Ferr2DT_FillMode.InvertedClosed, Path.closed, directionOverrides); if (prevSegmentDirection == nextSegmentDirection) { pointType = Ferr.PointType.Auto; } } Ferr2D_PointData data = new Ferr2D_PointData(); data.scale = vertScales[next]; data.directionOverride = (int)directionOverrides[next]; data.cutOverrides = cutOverrides[next].data; pathData.Add(oldPath.pathVerts[i], data, pointType); } pathData.ReverseSelf(); pathData.SetDirty(); // remove old path values directionOverrides = null; cutOverrides = null; vertScales = null; // upgrade collider settings if (createCollider) { if (useEdgeCollider) { colliderMode = Ferr2D_ColliderMode.Edge2D; } else if (create3DCollider) { colliderMode = Ferr2D_ColliderMode.Mesh3D; } else { colliderMode = Ferr2D_ColliderMode.Polygon2D; } } else { colliderMode = Ferr2D_ColliderMode.None; } // upgrade the fill settings switch (fill) { case Ferr2DT_FillMode.None: edgeMode = Ferr2D_SectionMode.Normal; fillMode = Ferr2D_SectionMode.None; break; case Ferr2DT_FillMode.Closed: edgeMode = Ferr2D_SectionMode.Normal; fillMode = Ferr2D_SectionMode.Normal; break; case Ferr2DT_FillMode.InvertedClosed: edgeMode = Ferr2D_SectionMode.Invert; fillMode = Ferr2D_SectionMode.Invert; break; case Ferr2DT_FillMode.FillOnlyClosed: edgeMode = Ferr2D_SectionMode.None; fillMode = Ferr2D_SectionMode.Normal; break; case Ferr2DT_FillMode.Skirt: edgeMode = Ferr2D_SectionMode.Normal; fillMode = Ferr2D_SectionMode.Normal; useSkirt = true; break; case Ferr2DT_FillMode.FillOnlySkirt: edgeMode = Ferr2D_SectionMode.None; fillMode = Ferr2D_SectionMode.Normal; useSkirt = true; break; } isLegacy = false; #if UNITY_EDITOR UnityEditor.Undo.DestroyObjectImmediate(oldPath); #else Destroy(oldPath); #endif Build(true); #if UNITY_EDITOR UnityEditor.SceneView.RepaintAll(); #endif }
private void DragSelect(Ferr2D_Path path) { if (Event.current.type == EventType.Repaint) { if (drag) { Vector3 pt1 = HandleUtility.GUIPointToWorldRay(dragStart).GetPoint(0.2f); Vector3 pt2 = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).GetPoint(0.2f); Vector3 pt3 = HandleUtility.GUIPointToWorldRay(new Vector2(dragStart.x, Event.current.mousePosition.y)).GetPoint(0.2f); Vector3 pt4 = HandleUtility.GUIPointToWorldRay(new Vector2(Event.current.mousePosition.x, dragStart.y)).GetPoint(0.2f); Handles.DrawSolidRectangleWithOutline(new Vector3[] { pt1, pt3, pt2, pt4 }, new Color(0, 0.5f, 0.25f, 0.25f), new Color(0, 0.5f, 0.25f, 0.5f)); } } if (Event.current.shift && Event.current.control) { switch (Event.current.type) { case EventType.MouseDrag: SceneView.RepaintAll(); break; case EventType.MouseMove: SceneView.RepaintAll(); break; case EventType.MouseDown: dragStart = Event.current.mousePosition; drag = true; break; case EventType.MouseUp: Vector2 dragEnd = Event.current.mousePosition; selectedPoints.Clear(); for (int i = 0; i < path.pathVerts.Count; i += 1) { float left = Mathf.Min(dragStart.x, dragStart.x + (dragEnd.x - dragStart.x)); float right = Mathf.Max(dragStart.x, dragStart.x + (dragEnd.x - dragStart.x)); float top = Mathf.Min(dragStart.y, dragStart.y + (dragEnd.y - dragStart.y)); float bottom = Mathf.Max(dragStart.y, dragStart.y + (dragEnd.y - dragStart.y)); Rect r = new Rect(left, top, right - left, bottom - top); if (r.Contains(HandleUtility.WorldToGUIPoint(path.transform.TransformPoint(path.pathVerts[i])))) { selectedPoints.Add(i); } } HandleUtility.AddDefaultControl(0); drag = false; Repaint(); break; case EventType.Layout: HandleUtility.AddDefaultControl(GetHashCode()); break; } } else if (drag == true) { drag = false; Repaint(); } }
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; }
private void DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle) { Vector3 snap = Event.current.control ? new Vector3(EditorPrefs.GetFloat("MoveSnapX"), EditorPrefs.GetFloat("MoveSnapY"), EditorPrefs.GetFloat("MoveSnapZ")) : Vector3.zero; Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent <Ferr2DT_PathTerrain>(); Transform transform = path.transform; Transform camTransform = SceneView.lastActiveSceneView.camera.transform; Vector3 pos = transform.InverseTransformPoint(GetMousePos(Event.current.mousePosition, transform)); bool hasDummy = path.pathVerts.Count <= 0; if (hasDummy) { path.pathVerts.Add(Vector2.zero); } int closestID = path.GetClosestSeg(pos); int secondID = closestID + 1 >= path.Count ? 0 : closestID + 1; float firstDist = Vector2.Distance(pos, path.pathVerts[closestID]); float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]); Vector3 local = pos; if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapLocal) { local = SnapVector(local, snap); } Vector3 global = transform.TransformPoint(pos); if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapGlobal) { global = SnapVector(global, snap); } Handles.color = Color.white; if (!(secondID == 0 && !path.closed && firstDist > secondDist)) { Handles.DrawLine(global, transform.TransformPoint(path.pathVerts[closestID])); } if (!(secondID == 0 && !path.closed && firstDist < secondDist)) { Handles.DrawLine(global, transform.TransformPoint(path.pathVerts[secondID])); } Handles.color = new Color(1, 1, 1, 1); Vector3 handlePos = transform.TransformPoint(pos); float scale = HandleScale(handlePos); if (Handles.Button(handlePos, camTransform.rotation, scale, scale, CapDotPlus)) { Vector3 finalPos = transform.InverseTransformPoint(global); if (secondID == 0) { if (firstDist < secondDist) { if (terrain) { terrain.AddPoint(finalPos); } else { path.pathVerts.Add(finalPos); } } else { if (terrain) { terrain.AddPoint(finalPos, 0); } else { path.pathVerts.Insert(0, finalPos); } } } else { if (terrain) { terrain.AddPoint(finalPos, Mathf.Max(closestID, secondID)); } else { path.pathVerts.Insert(Mathf.Max(closestID, secondID), finalPos); } } selectedPoints.Clear(); GUI.changed = true; } if (hasDummy) { path.pathVerts.RemoveAt(0); } }
public override void OnInspectorGUI() { EditorTools.TitleField("地板編輯工具"); Undo.RecordObject(target, "Modified Path"); Ferr2D_Path path = (Ferr2D_Path)target; // if this was an undo, refresh stuff too if (Event.current.type == EventType.ValidateCommand) { switch (Event.current.commandName) { case "UndoRedoPerformed": path.UpdateDependants(true); if (OnChanged != null) { OnChanged(); } return; } } path.closed = EditorGUILayout.Toggle("封閉地面", path.closed); if (path) { // display the path verts list info showVerts = EditorGUILayout.Foldout(showVerts, "頂點座標"); } EditorGUI.indentLevel = 2; if (showVerts) { int size = EditorGUILayout.IntField("數量: ", path.pathVerts.Count); while (path.pathVerts.Count > size) { path.pathVerts.RemoveAt(path.pathVerts.Count - 1); } while (path.pathVerts.Count < size) { path.pathVerts.Add(new Vector2(0, 0)); } } // draw all the verts! Long list~ for (int i = 0; showVerts && i < path.pathVerts.Count; i++) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("#" + i, GUILayout.Width(60)); path.pathVerts[i] = new Vector2( EditorGUILayout.FloatField(path.pathVerts[i].x), EditorGUILayout.FloatField(path.pathVerts[i].y)); EditorGUILayout.EndHorizontal(); } // button for updating the origin of the object if (GUILayout.Button("座標重置")) { path.ReCenter(); } bool updateClosed = false; Ferr2DT_PathTerrain terrain = path.GetComponent <Ferr2DT_PathTerrain>(); if (!path.closed && terrain != null && (terrain.fill == Ferr2DT_FillMode.Closed || terrain.fill == Ferr2DT_FillMode.InvertedClosed || terrain.fill == Ferr2DT_FillMode.FillOnlyClosed)) { path.closed = true; updateClosed = true; } if (terrain != null && path.closed && (terrain.fill == Ferr2DT_FillMode.FillOnlySkirt || terrain.fill == Ferr2DT_FillMode.Skirt)) { path.closed = false; updateClosed = true; } // update dependants when it changes if (GUI.changed || updateClosed) { path.UpdateDependants(false); EditorUtility.SetDirty(target); } sizeX = EditorTools.IntField(sizeX, "寬"); sizeY = EditorTools.IntField(sizeY, "長"); if (GUILayout.Button("地板格式化")) { path.pathVerts = new List <Vector2>(); path.pathVerts.Add(new Vector2(sizeX, sizeY) * 0.5F); path.pathVerts.Add(new Vector2(sizeX, -sizeY) * 0.5F); path.pathVerts.Add(new Vector2(-sizeX, -sizeY) * 0.5F); path.pathVerts.Add(new Vector2(-sizeX, sizeY) * 0.5F); UpdateDependentsSmart(path, false, false); EditorUtility.SetDirty(target); prevChanged = true; BoxCollider2D box2D = path.GetComponent <BoxCollider2D>(); if (box2D) { path.GetComponent <BoxCollider2D>().size = new Vector2(sizeX, sizeY); EditorUtility.SetDirty(path.GetComponent <BoxCollider2D>()); } } if (GUILayout.Button("進階地板設定")) { GroundBase groundBase = path.GetComponent <GroundBase>(); if (!groundBase) { path.gameObject.AddComponent <GroundBase>(); } } EditorTools.Mig(); }
private Ferr2DT_SegmentDescription GetDescription(List <Vector2> aSegment) { Ferr2DT_TerrainDirection dir = Ferr2D_Path.GetDirection(aSegment, 0, fill == Ferr2DT_FillMode.InvertedClosed); return(terrainMaterial.GetDescriptor(dir)); }
void OnGUI() { radius = EditorGUILayout.FloatField("Radius", radius); placeAround = (Transform)EditorGUILayout.ObjectField(placeAround, typeof(Transform), true); GUILayout.Label("Parent Transform for Points", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); doTransform = EditorGUILayout.Toggle(doTransform, GUILayout.Width(14f)); parentItem = (Transform)EditorGUILayout.ObjectField(parentItem, typeof(Transform), true); EditorGUILayout.EndHorizontal(); GUILayout.Label("EdgeCollider GameObject", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); doEdgeCollider = EditorGUILayout.Toggle(doEdgeCollider, GUILayout.Width(14f)); edgeCollider = (EdgeCollider2D)EditorGUILayout.ObjectField(edgeCollider, typeof(EdgeCollider2D), true); EditorGUILayout.EndHorizontal(); GUILayout.Label("Ferr2D terrain points", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); doFerrTerrain = EditorGUILayout.Toggle(doFerrTerrain, GUILayout.Width(14f)); path = (Ferr2D_Path)EditorGUILayout.ObjectField(path, typeof(Ferr2D_Path), true); EditorGUILayout.EndHorizontal(); if (GUI.Button(new Rect(3, 170, position.width - 6, 20), "Make a Circle")) { if (doTransform && parentItem) { Transform[] transforms = parentItem.GetComponentsInChildren <Transform>(); Vector2[] tempPoints = new Vector2[transforms.Length]; int i = 0; foreach (Transform t in transforms) { tempPoints[i].x = t.position.x; tempPoints[i].y = t.position.y; i++; } if (placeAround) { PlacePointsInACircle(ref tempPoints, radius, placeAround.position); } else { PlacePointsInACircle(ref tempPoints, radius, Vector2.zero); } i = 0; foreach (Vector2 p in tempPoints) { transforms[i].position = new Vector3(p.x, p.y, 0f); i++; } } if (doEdgeCollider && edgeCollider) { Vector2[] tempPoints = edgeCollider.points; if (placeAround) { PlacePointsInACircle(ref tempPoints, radius, placeAround.position); } else { PlacePointsInACircle(ref tempPoints, radius, Vector2.zero); } edgeCollider.points = tempPoints; } if (doFerrTerrain && path) { Vector2[] tempPoints = path.GetVertsRaw().ToArray(); if (placeAround) { PlacePointsInACircle(ref tempPoints, radius, placeAround.position, false); } else { PlacePointsInACircle(ref tempPoints, radius, Vector2.zero, false); } path.pathVerts = new List <Vector2>(tempPoints); path.UpdateColliders(); path.UpdateDependants(true); } } }
private void DragSelect (Ferr2D_Path path) { if (Event.current.type == EventType.repaint) { if (drag) { Vector3 pt1 = HandleUtility.GUIPointToWorldRay(dragStart).GetPoint(0.2f); Vector3 pt2 = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).GetPoint(0.2f); Vector3 pt3 = HandleUtility.GUIPointToWorldRay(new Vector2(dragStart.x, Event.current.mousePosition.y)).GetPoint(0.2f); Vector3 pt4 = HandleUtility.GUIPointToWorldRay(new Vector2(Event.current.mousePosition.x, dragStart.y)).GetPoint(0.2f); Handles.DrawSolidRectangleWithOutline(new Vector3[] { pt1, pt3, pt2, pt4 }, new Color(0, 0.5f, 0.25f, 0.25f), new Color(0, 0.5f, 0.25f, 0.5f)); } } if (Event.current.shift && Event.current.control) { switch(Event.current.type) { case EventType.mouseDrag: SceneView.RepaintAll(); break; case EventType.mouseMove: SceneView.RepaintAll(); break; case EventType.mouseDown: dragStart = Event.current.mousePosition; drag = true; break; case EventType.mouseUp: Vector2 dragEnd = Event.current.mousePosition; selectedPoints.Clear(); for (int i=0;i<path.pathVerts.Count;i+=1) { float left = Mathf.Min(dragStart.x, dragStart.x + (dragEnd.x - dragStart.x)); float right = Mathf.Max(dragStart.x, dragStart.x + (dragEnd.x - dragStart.x)); float top = Mathf.Min(dragStart.y, dragStart.y + (dragEnd.y - dragStart.y)); float bottom = Mathf.Max(dragStart.y, dragStart.y + (dragEnd.y - dragStart.y)); Rect r = new Rect(left, top, right-left, bottom-top); if (r.Contains(HandleUtility.WorldToGUIPoint(path.transform.TransformPoint( path.pathVerts[i]) ) )) { selectedPoints.Add(i); } } HandleUtility.AddDefaultControl(0); drag = false; Repaint(); break; case EventType.layout : HandleUtility.AddDefaultControl(GetHashCode()); break; } } else if (drag == true) { drag = false; Repaint(); } }
Mesh GetMesh() { MeshFilter filter = GetComponent<MeshFilter>(); string newName = GetMeshName(); Mesh result = filter.sharedMesh; if (IsPrefab()) { #if UNITY_EDITOR if (filter.sharedMesh == null || filter.sharedMesh.name != newName) { string path = UnityEditor.AssetDatabase.GetAssetPath(this) + "/Meshes/" + newName + ".asset"; Mesh assetMesh = UnityEditor.AssetDatabase.LoadAssetAtPath(path, typeof(Mesh)) as Mesh; if (assetMesh != null) { result = assetMesh; } else { path = System.IO.Path.GetDirectoryName(UnityEditor.AssetDatabase.GetAssetPath(this)) + "/Meshes"; string assetName = "/" + newName + ".asset"; result = new Mesh(); result.name = newName; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } try { UnityEditor.AssetDatabase.CreateAsset(result, path + assetName); UnityEditor.AssetDatabase.Refresh(); } catch { Debug.LogError("Unable to save terrain prefab mesh! Likely, you deleted the mesh files, and the prefab is still referencing them. Restarting your Unity editor should solve this minor issue."); } } } #endif } else { if (filter.sharedMesh == null || filter.sharedMesh.name != newName) { result = new Mesh(); } } result.name = newName; return result; }
private Vector3 GetTickerOffset (Ferr2D_Path path, Vector3 aRootPos, int aIndex) { float scale = HandleScale(aRootPos) * 0.5f; Vector3 result = Vector3.zero; int index = (aIndex + 1) % path.pathVerts.Count; Vector3 delta = Vector3.Normalize(path.pathVerts[index] - path.pathVerts[aIndex]); Vector3 norm = new Vector3(-delta.y, delta.x, 0); result = delta * scale * 3 + new Vector3(norm.x, norm.y, 0) * scale * 2; return result; }
private void RecreateCollider2D() { List <Collider2D> colliders = new List <Collider2D>(1); List <List <Vector2> > segs = GetColliderVerts(); bool closed = collidersBottom && collidersLeft && collidersRight && collidersTop; if (useEdgeCollider) { EdgeCollider2D[] edges = GetComponents <EdgeCollider2D>(); List <EdgeCollider2D> edgePool = new List <EdgeCollider2D>(edges); int extra = edges.Length - segs.Count; if (extra > 0) { // we have too many, remove a few for (int i = 0; i < extra; i += 1) { Destroy(edgePool[0]); edgePool.RemoveAt(0); } } else { // we have too few, add in a few for (int i = 0; i < Mathf.Abs(extra); i += 1) { edgePool.Add(gameObject.AddComponent <EdgeCollider2D>()); } } for (int i = 0; i < segs.Count; i++) { EdgeCollider2D edge = edgePool[i]; edge.points = segs[i].ToArray(); colliders.Add(edge); } } else { // make sure there's a collider component on this object PolygonCollider2D poly = GetComponent <PolygonCollider2D>(); if (poly == null) { poly = gameObject.AddComponent <PolygonCollider2D>(); } colliders.Add(poly); poly.pathCount = segs.Count; if (segs.Count > 1 || !closed) { for (int i = 0; i < segs.Count; i++) { poly.SetPath(i, ExpandColliderPath(segs[i], colliderThickness).ToArray()); } } else { if (fill == Ferr2DT_FillMode.InvertedClosed) { Rect bounds = Ferr2D_Path.GetBounds(segs[0]); poly.pathCount = 2; poly.SetPath(0, segs[0].ToArray()); poly.SetPath(1, new Vector2[] { new Vector2(bounds.xMin - bounds.width, bounds.yMax + bounds.height), new Vector2(bounds.xMax + bounds.width, bounds.yMax + bounds.height), new Vector2(bounds.xMax + bounds.width, bounds.yMin - bounds.height), new Vector2(bounds.xMin - bounds.width, bounds.yMin - bounds.height) }); } else { if (segs.Count > 0 && segs[0].Count > 0) { poly.SetPath(0, segs[0].ToArray()); } } } } for (int i = 0; i < colliders.Count; i += 1) { colliders[i].isTrigger = isTrigger; colliders[i].sharedMaterial = physicsMaterial2D; #if UNITY_5 colliders[i].usedByEffector = usedByEffector; #endif } }
private void DoPath (Ferr2D_Path path) { Handles.color = Color.white; List<Vector2> verts = path.GetVertsRaw(); Matrix4x4 mat = path.transform.localToWorldMatrix; for (int i = 0; i < verts.Count - 1; i++) { Vector3 pos = mat.MultiplyPoint3x4(verts[i]); Vector3 pos2 = mat.MultiplyPoint3x4(verts[i + 1]); Handles.DrawLine(pos, pos2); } if (path.closed) { Vector3 pos = mat.MultiplyPoint3x4(verts[0]); Vector3 pos2 = mat.MultiplyPoint3x4(verts[verts.Count - 1]); Handles.DrawLine(pos, pos2); } }
/// <summary> /// Retrieves a list of line segments that directly represent the collision volume of the terrain. This includes offsets and removed edges. /// </summary> /// <returns>A list of line segments.</returns> public List <List <Vector2> > GetColliderVerts() { List <Vector2> tVerts = Path.GetVertsRaw(); // drop a skirt on skirt-based terrain if ((fill == Ferr2DT_FillMode.Skirt || fill == Ferr2DT_FillMode.FillOnlySkirt) && tVerts.Count > 0) { Vector2 start = tVerts[0]; Vector2 end = tVerts[tVerts.Count - 1]; tVerts.Add(new Vector2(end.x, fillY)); tVerts.Add(new Vector2(start.x, fillY)); tVerts.Add(new Vector2(start.x, start.y)); } float fillDist = (terrainMaterial.ToUV(terrainMaterial.GetBody((Ferr2DT_TerrainDirection)0, 0)).width *(terrainMaterial.edgeMaterial.mainTexture.width / pixelsPerUnit)) / (Mathf.Max(1, splitCount)) * splitDist; List <Ferr2DT_TerrainDirection> dirs = new List <Ferr2DT_TerrainDirection>(); List <List <Vector2> > result = new List <List <Vector2> >(); List <List <int> > list = GetSegments(tVerts, out dirs); List <Vector2> curr = new List <Vector2>(); // remove segments that aren't on the terrain for (int i = 0; i < list.Count; i++) { if ((dirs[i] == Ferr2DT_TerrainDirection.Bottom && !collidersBottom) || (dirs[i] == Ferr2DT_TerrainDirection.Left && !collidersLeft) || (dirs[i] == Ferr2DT_TerrainDirection.Top && !collidersTop) || (dirs[i] == Ferr2DT_TerrainDirection.Right && !collidersRight)) { if (curr.Count > 0) { result.Add(new List <Vector2>(curr)); curr.Clear( ); } } else { // create a list of verts and scales for this edge List <float> tScales = null; List <Vector2> tList = null; Ferr2D_Path.IndicesToPath(tVerts, vertScales, list[i], out tList, out tScales); // smooth it! if (smoothPath && tList.Count > 2) { Ferr2D_Path.SmoothSegment(tList, tScales, fillDist, false, out tList, out tScales); } // offset the verts based on scale and terrain edge info tList = OffsetColliderVerts(tList, tScales, dirs[i]); // sharpen corners properly! if (curr.Count > 0 && sharpCorners) { MergeCorner(ref curr, ref tList); } curr.AddRange(tList); } } if (sharpCorners) { MergeCorner(ref curr, ref curr); } if (curr.Count > 0) { result.Add(curr); } return(result); }