private void UndoRedoPerformed() { LatticeDeformer latticeDeformer = ((LatticeDeformer)target); newResolution = latticeDeformer.Resolution; CacheResizePositionsFromChange(); }
protected override void OnEnable() { base.OnEnable(); properties = new Properties(serializedObject); LatticeDeformer latticeDeformer = ((LatticeDeformer)target); newResolution = latticeDeformer.Resolution; CacheResizePositionsFromChange(); Undo.undoRedoPerformed += UndoRedoPerformed; }
public override void OnInspectorGUI() { base.OnInspectorGUI(); LatticeDeformer latticeDeformer = ((LatticeDeformer)target); serializedObject.UpdateIfRequiredOrScript(); EditorGUI.BeginChangeCheck(); newResolution = EditorGUILayout.Vector3IntField(Content.Resolution, newResolution); // Make sure we have at least two control points per axis newResolution = Vector3Int.Max(newResolution, new Vector3Int(2, 2, 2)); // Don't let the lattice resolution get ridiculously high newResolution = Vector3Int.Min(newResolution, new Vector3Int(32, 32, 32)); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Update Lattice"); latticeDeformer.GenerateControlPoints(newResolution, cachedResizePositions, cachedResizeResolution); selectedIndices.Clear(); } if (GUILayout.Button("Reset Lattice Points")) { Undo.RecordObject(target, "Reset Lattice Points"); latticeDeformer.GenerateControlPoints(newResolution); selectedIndices.Clear(); CacheResizePositionsFromChange(); } if (latticeDeformer.CanAutoFitBounds) { if (GUILayout.Button("Auto-Fit Bounds")) { Undo.RecordObject(latticeDeformer.transform, "Auto-Fit Bounds"); latticeDeformer.FitBoundsToParentDeformable(); } } serializedObject.ApplyModifiedProperties(); EditorApplication.QueuePlayerLoopUpdate(); }
private void DrawLattice(LatticeDeformer lattice, DeformHandles.LineMode lineMode) { var resolution = lattice.Resolution; var controlPoints = lattice.ControlPoints; for (int z = 0; z < resolution.z - 1; z++) { for (int y = 0; y < resolution.y - 1; y++) { for (int x = 0; x < resolution.x - 1; x++) { int index000 = lattice.GetIndex(x, y, z); int index100 = lattice.GetIndex(x + 1, y, z); int index010 = lattice.GetIndex(x, y + 1, z); int index110 = lattice.GetIndex(x + 1, y + 1, z); int index001 = lattice.GetIndex(x, y, z + 1); int index101 = lattice.GetIndex(x + 1, y, z + 1); int index011 = lattice.GetIndex(x, y + 1, z + 1); int index111 = lattice.GetIndex(x + 1, y + 1, z + 1); DeformHandles.Line(controlPoints[index000], controlPoints[index100], lineMode); DeformHandles.Line(controlPoints[index010], controlPoints[index110], lineMode); DeformHandles.Line(controlPoints[index001], controlPoints[index101], lineMode); DeformHandles.Line(controlPoints[index011], controlPoints[index111], lineMode); DeformHandles.Line(controlPoints[index000], controlPoints[index010], lineMode); DeformHandles.Line(controlPoints[index100], controlPoints[index110], lineMode); DeformHandles.Line(controlPoints[index001], controlPoints[index011], lineMode); DeformHandles.Line(controlPoints[index101], controlPoints[index111], lineMode); DeformHandles.Line(controlPoints[index000], controlPoints[index001], lineMode); DeformHandles.Line(controlPoints[index100], controlPoints[index101], lineMode); DeformHandles.Line(controlPoints[index010], controlPoints[index011], lineMode); DeformHandles.Line(controlPoints[index110], controlPoints[index111], lineMode); } } } }
public override void OnSceneGUI() { base.OnSceneGUI(); LatticeDeformer lattice = target as LatticeDeformer; Transform transform = lattice.transform; float3[] controlPoints = lattice.ControlPoints; Event e = Event.current; using (new Handles.DrawingScope(transform.localToWorldMatrix)) { var cachedZTest = Handles.zTest; // Change the depth testing to only show handles in front of solid objects (i.e. typical depth testing) Handles.zTest = CompareFunction.LessEqual; DrawLattice(lattice, DeformHandles.LineMode.Solid); // Change the depth testing to only show handles *behind* solid objects Handles.zTest = CompareFunction.Greater; DrawLattice(lattice, DeformHandles.LineMode.Light); // Restore the original z test value now we're done with our drawing Handles.zTest = cachedZTest; var resolution = lattice.Resolution; for (int z = 0; z < resolution.z; z++) { for (int y = 0; y < resolution.y; y++) { for (int x = 0; x < resolution.x; x++) { var controlPointHandleID = GUIUtility.GetControlID("LatticeDeformerControlPoint".GetHashCode(), FocusType.Passive); var activeColor = DeformEditorSettings.SolidHandleColor; var controlPointIndex = lattice.GetIndex(x, y, z); if (GUIUtility.hotControl == controlPointHandleID || selectedIndices.Contains(controlPointIndex)) { activeColor = Handles.selectedColor; } else if (HandleUtility.nearestControl == controlPointHandleID) { activeColor = Handles.preselectionColor; } if (e.type == EventType.MouseDown && HandleUtility.nearestControl == controlPointHandleID && e.button == 0 && MouseActionAllowed) { BeginSelectionChangeRegion(); GUIUtility.hotControl = controlPointHandleID; GUIUtility.keyboardControl = controlPointHandleID; e.Use(); bool modifierKeyPressed = e.control || e.shift || e.command; if (modifierKeyPressed && selectedIndices.Contains(controlPointIndex)) { // Pressed a modifier key so toggle the selection selectedIndices.Remove(controlPointIndex); } else { if (!modifierKeyPressed) { selectedIndices.Clear(); } if (!selectedIndices.Contains(controlPointIndex)) { selectedIndices.Add(controlPointIndex); } } EndSelectionChangeRegion(); } if (Tools.current != Tool.None && selectedIndices.Count != 0) { // If the user changes tool, change our internal mode to match but disable the corresponding Unity tool // (e.g. they hit W key or press on the Rotate Tool button on the top left toolbar) activeTool = Tools.current; Tools.current = Tool.None; } using (new Handles.DrawingScope(activeColor)) { var position = controlPoints[controlPointIndex]; var size = HandleUtility.GetHandleSize(position) * DeformEditorSettings.ScreenspaceLatticeHandleCapSize; Handles.DotHandleCap( controlPointHandleID, position, Quaternion.identity, size, e.type); } } } } } var defaultControl = DeformUnityObjectSelection.DisableSceneViewObjectSelection(); if (selectedIndices.Count != 0) { var currentPivotPosition = float3.zero; if (Tools.pivotMode == PivotMode.Center) { // Get the average position foreach (var index in selectedIndices) { currentPivotPosition += controlPoints[index]; } currentPivotPosition /= selectedIndices.Count; } else { // Match the scene view behaviour that Pivot mode uses the last selected object as pivot currentPivotPosition = controlPoints[selectedIndices.Last()]; } float3 handlePosition = transform.TransformPoint(currentPivotPosition); if (e.type == EventType.MouseDown) { // Potentially started interacting with a handle so reset everything handleScale = Vector3.one; // Make sure we cache the positions just before the interaction changes them CacheOriginalPositions(); } var originalPivotPosition = float3.zero; if (Tools.pivotMode == PivotMode.Center) { // Get the average position foreach (var originalPosition in selectedOriginalPositions) { originalPivotPosition += originalPosition; } originalPivotPosition /= selectedIndices.Count; } else { // Match the scene view behaviour that Pivot mode uses the last selected object as pivot originalPivotPosition = selectedOriginalPositions.Last(); } var handleRotation = transform.rotation; if (Tools.pivotRotation == PivotRotation.Global) { handleRotation = Quaternion.identity; } if (activeTool == Tool.Move) { EditorGUI.BeginChangeCheck(); float3 newPosition = Handles.PositionHandle(handlePosition, handleRotation); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Update Lattice"); var delta = newPosition - handlePosition; delta = transform.InverseTransformVector(delta); foreach (var selectedIndex in selectedIndices) { controlPoints[selectedIndex] += delta; } CacheResizePositionsFromChange(); } } else if (activeTool == Tool.Rotate) { EditorGUI.BeginChangeCheck(); quaternion newRotation = Handles.RotationHandle(handleRotation, handlePosition); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Update Lattice"); for (var index = 0; index < selectedIndices.Count; index++) { if (Tools.pivotRotation == PivotRotation.Global) { controlPoints[selectedIndices[index]] = originalPivotPosition + (float3)transform.InverseTransformDirection(mul(newRotation, transform.TransformDirection(selectedOriginalPositions[index] - originalPivotPosition))); } else { controlPoints[selectedIndices[index]] = originalPivotPosition + mul(mul(inverse(handleRotation), newRotation), (selectedOriginalPositions[index] - originalPivotPosition)); } } CacheResizePositionsFromChange(); } } else if (activeTool == Tool.Scale) { var size = HandleUtility.GetHandleSize(handlePosition); EditorGUI.BeginChangeCheck(); handleScale = Handles.ScaleHandle(handleScale, handlePosition, handleRotation, size); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Update Lattice"); for (var index = 0; index < selectedIndices.Count; index++) { if (Tools.pivotRotation == PivotRotation.Global) { controlPoints[selectedIndices[index]] = originalPivotPosition + (float3)transform.InverseTransformDirection(handleScale * transform.TransformDirection(selectedOriginalPositions[index] - originalPivotPosition)); } else { controlPoints[selectedIndices[index]] = originalPivotPosition + handleScale * (selectedOriginalPositions[index] - originalPivotPosition); } } CacheResizePositionsFromChange(); } } Handles.BeginGUI(); if (GUI.Button(new Rect((EditorGUIUtility.currentViewWidth - 200) / 2, SceneView.currentDrawingSceneView.position.height - 60, 200, 30), Content.StopEditing)) { DeselectAll(); } Handles.EndGUI(); } if (e.button == 0) // Left Mouse Button { if (e.type == EventType.MouseDown && HandleUtility.nearestControl == defaultControl && MouseActionAllowed) { mouseDownPosition = e.mousePosition; mouseDragState = MouseDragState.Eligible; } else if (e.type == EventType.MouseDrag && mouseDragState == MouseDragState.Eligible) { mouseDragState = MouseDragState.InProgress; SceneView.currentDrawingSceneView.Repaint(); } else if (GUIUtility.hotControl == 0 && (e.type == EventType.MouseUp || (mouseDragState == MouseDragState.InProgress && e.rawType == EventType.MouseUp))) // Have they released the mouse outside the scene view while doing marquee select? { if (mouseDragState == MouseDragState.InProgress) { var mouseUpPosition = e.mousePosition; Rect marqueeRect = Rect.MinMaxRect(Mathf.Min(mouseDownPosition.x, mouseUpPosition.x), Mathf.Min(mouseDownPosition.y, mouseUpPosition.y), Mathf.Max(mouseDownPosition.x, mouseUpPosition.x), Mathf.Max(mouseDownPosition.y, mouseUpPosition.y)); BeginSelectionChangeRegion(); if (!e.shift && !e.control && !e.command) { selectedIndices.Clear(); } for (var index = 0; index < controlPoints.Length; index++) { Camera camera = SceneView.currentDrawingSceneView.camera; var screenPoint = DeformEditorGUIUtility.WorldToGUIPoint(camera, transform.TransformPoint(controlPoints[index])); if (screenPoint.z < 0) { // Don't consider points that are behind the camera continue; } if (marqueeRect.Contains(screenPoint)) { if (e.control || e.command) // Remove selection { selectedIndices.Remove(index); } else { selectedIndices.Add(index); } } } EndSelectionChangeRegion(); } else { if (selectedIndices.Count == 0) // This shouldn't be called if you have any points selected (we want to allow you to deselect the points) { DeformUnityObjectSelection.AttemptMouseUpObjectSelection(); } else { DeselectAll(); } } mouseDragState = MouseDragState.NotActive; } } if (e.type == EventType.Repaint && mouseDragState == MouseDragState.InProgress) { var mouseUpPosition = e.mousePosition; Rect marqueeRect = Rect.MinMaxRect(Mathf.Min(mouseDownPosition.x, mouseUpPosition.x), Mathf.Min(mouseDownPosition.y, mouseUpPosition.y), Mathf.Max(mouseDownPosition.x, mouseUpPosition.x), Mathf.Max(mouseDownPosition.y, mouseUpPosition.y)); DeformUnityObjectSelection.DrawUnityStyleMarquee(marqueeRect); SceneView.RepaintAll(); } // If the lattice is visible, override Unity's built-in Select All so that it selects all control points if (DeformUnityObjectSelection.SelectAllPressed) { BeginSelectionChangeRegion(); selectedIndices.Clear(); var resolution = lattice.Resolution; for (int z = 0; z < resolution.z; z++) { for (int y = 0; y < resolution.y; y++) { for (int x = 0; x < resolution.x; x++) { var controlPointIndex = lattice.GetIndex(x, y, z); selectedIndices.Add(controlPointIndex); } } } EndSelectionChangeRegion(); e.Use(); } if (e.type == EventType.KeyDown && e.keyCode == KeyCode.Escape) { DeselectAll(); } EditorApplication.QueuePlayerLoopUpdate(); }