From b41e08da6e65c1a448757443d7d21f004f35a584 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Thu, 18 Oct 2018 15:05:48 -0400 Subject: [PATCH 01/27] initial commit --- .../Editor/EditorCore/EditorEnum.cs | 23 -- .../Editor/EditorCore/EditorHandleUtility.cs | 35 ++ .../Editor/EditorCore/MeshSelection.cs | 72 ++++ .../Editor/EditorCore/MoveTool.cs | 320 ++++++++++++++++++ .../Editor/EditorCore/MoveTool.cs.meta | 11 + .../Editor/EditorCore/ProBuilderEditor.cs | 114 +++---- .../Interaction/ToggleHandleAlignment.cs | 4 +- .../Runtime/Core/HandleOrientation.cs | 25 ++ .../Runtime/Core/HandleOrientation.cs.meta | 11 + .../Runtime/Core/PivotPoint.cs | 27 ++ .../Runtime/Core/PivotPoint.cs.meta | 11 + 11 files changed, 552 insertions(+), 101 deletions(-) create mode 100644 com.unity.probuilder/Editor/EditorCore/MoveTool.cs create mode 100644 com.unity.probuilder/Editor/EditorCore/MoveTool.cs.meta create mode 100644 com.unity.probuilder/Runtime/Core/HandleOrientation.cs create mode 100644 com.unity.probuilder/Runtime/Core/HandleOrientation.cs.meta create mode 100644 com.unity.probuilder/Runtime/Core/PivotPoint.cs create mode 100644 com.unity.probuilder/Runtime/Core/PivotPoint.cs.meta diff --git a/com.unity.probuilder/Editor/EditorCore/EditorEnum.cs b/com.unity.probuilder/Editor/EditorCore/EditorEnum.cs index b12f54891..542d42198 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorEnum.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorEnum.cs @@ -16,29 +16,6 @@ enum SceneToolbarLocation BottomRight } - /// - /// How the handle gizmo is oriented with regards to the current element selection. - /// - /// - /// This overrides the Unity Pivot / Global setting when editing vertices, faces, or edges. - /// - /// Editor only. - public enum HandleOrientation - { - /// - /// The gizmo is aligned in world space. - /// - World = 0, - /// - /// The gizmo is aligned relative to the mesh transform. Also called coordinate or model space. - /// - Local = 1, - /// - /// The gizmo is aligned relative to the currently selected face. When editing vertices or edges, this falls back to alignment. - /// - Normal = 2 - } - /// /// When drag selecting mesh elements, this defines how the Shift key will modify the selection. /// diff --git a/com.unity.probuilder/Editor/EditorCore/EditorHandleUtility.cs b/com.unity.probuilder/Editor/EditorCore/EditorHandleUtility.cs index d50e68b40..38d9fc901 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorHandleUtility.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorHandleUtility.cs @@ -521,5 +521,40 @@ public static Vector3 ClosestPointToPolyLine(List vertices, out int ind return trs != null ? trs.InverseTransformPoint(p) : p; } + + internal static HandleOrientation ProBuilderHandleOrientation(this PivotRotation rotation) + { + if (rotation == PivotRotation.Global) + return HandleOrientation.World; + + if (rotation == PivotRotation.Local) + return HandleOrientation.Local; + + return HandleOrientation.Normal; + } + + internal static PivotRotation UnityPivotRotation(this HandleOrientation orientation) + { + if (orientation == HandleOrientation.World) + return PivotRotation.Global; + + return PivotRotation.Local; + } + + internal static PivotMode UnityPivot(this PivotPoint pivotPoint) + { + if (pivotPoint == PivotPoint.WorldBoundingBoxCenter) + return PivotMode.Center; + + return PivotMode.Pivot; + } + + internal static PivotPoint ProBuilderPivot(this PivotMode pivotMode) + { + if (pivotMode == PivotMode.Center) + return PivotPoint.WorldBoundingBoxCenter; + + return PivotPoint.ModelBoundingBoxCenter; + } } } diff --git a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs index 06ef0ea03..bf3f48d1e 100644 --- a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs +++ b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs @@ -322,5 +322,77 @@ public static void ClearElementAndObjectSelection() ProBuilderEditor.instance.ClearElementSelection(); Selection.objects = new Object[0]; } + + internal static Vector3 GetHandlePosition() + { + switch (Tools.pivotMode) + { + case PivotMode.Pivot: + { + ProBuilderMesh mesh; + Face face; + + if (!GetFirstSelectedFace(out mesh, out face)) + goto default; + + return mesh.transform.TransformPoint(Math.Average(mesh.positionsInternal, face.distinctIndexesInternal)); + } + + default: + RecalculateSelectionBounds(); + return bounds.center; + } + } + + internal static Quaternion GetHandleRotation(HandleOrientation orientation) + { + Quaternion localRotation = Selection.activeTransform == null ? Quaternion.identity : Selection.activeTransform.rotation; + + switch (orientation) + { + case HandleOrientation.Normal: + + ProBuilderMesh mesh; + Face face; + + if(!GetFirstSelectedFace(out mesh, out face)) + goto default; + + // use average normal, tangent, and bi-tangent to calculate rotation relative to local space + var tup = Math.NormalTangentBitangent(mesh, face); + Vector3 nrm = tup.normal, bitan = tup.bitangent; + + if (nrm == Vector3.zero || bitan == Vector3.zero) + { + nrm = Vector3.up; + bitan = Vector3.right; + } + + return localRotation * Quaternion.LookRotation(nrm, bitan); + + case HandleOrientation.Local: + return localRotation; + + default: + return Quaternion.identity; + } + } + + static bool GetFirstSelectedFace(out ProBuilderMesh mesh, out Face face) + { + foreach (var m in topInternal) + { + if (m.selectedFaceCount > 0) + { + mesh = m; + face = mesh.selectedFacesInternal[0]; + return true; + } + } + + mesh = null; + face = null; + return false; + } } } diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs new file mode 100644 index 000000000..1b3f7b9ee --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs @@ -0,0 +1,320 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEditor.ProBuilder; +using UnityEngine; +using UnityEngine.ProBuilder; + +struct MeshAndElementSelection +{ + ProBuilderMesh m_Mesh; + Vector3[] m_Positions; + List m_Selection; + + public ProBuilderMesh mesh + { + get { return m_Mesh; } + } + + public Vector3[] positions + { + get { return m_Positions; } + } + + public List selection + { + get { return m_Selection; } + } + + public MeshAndElementSelection(ProBuilderMesh mesh, List groups) + { + m_Mesh = mesh; + m_Positions = mesh.positions.ToArray(); + m_Selection = groups; + } +} + +struct ElementGroup +{ + List m_Indices; + Matrix4x4 m_Matrix; + bool m_ApplyDeltaInWorldSpace; + + public List indices + { + get { return m_Indices; } + } + + public Matrix4x4 matrix + { + get { return m_Matrix; } + } + + public bool applyDeltaInWorldSpace + { + get { return m_ApplyDeltaInWorldSpace; } + } + + public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List groups) + { + Matrix4x4 matrix = Matrix4x4.identity; + bool applyDeltaInWorldSpace; + + switch (pivot) + { + case PivotPoint.ModelBoundingBoxCenter: + matrix = Matrix4x4.identity; + applyDeltaInWorldSpace = false; + break; + + case PivotPoint.IndividualOrigins: + applyDeltaInWorldSpace = false; + break; + +// case PivotPoint.WorldBoundingBoxCenter: +// case PivotPoint.Custom: + default: + matrix = mesh.transform.localToWorldMatrix; + applyDeltaInWorldSpace = true; + break; + } + + groups.Add(new ElementGroup() + { + m_Indices = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal), + m_Matrix = matrix, + m_ApplyDeltaInWorldSpace = applyDeltaInWorldSpace + }); + } +} + +abstract class VertexManipulationTool +{ + Vector3 m_HandlePosition; + Quaternion m_HandleRotation; + + Vector3 m_HandlePositionOrigin; + Quaternion m_HandleRotationOrigin; + Matrix4x4 m_HandleMatrixInverse; + + protected Vector3 handlePositionOrigin + { + get { return m_HandlePositionOrigin; } + } + + protected Quaternion handleRotationOrigin + { + get { return m_HandleRotationOrigin; } + } + + protected List m_Selection = new List(); + + protected bool m_IsEditing; + + protected void BeginEdit() + { + if (m_IsEditing) + return; + + m_IsEditing = true; + + m_HandlePositionOrigin = m_HandlePosition; + m_HandleRotationOrigin = m_HandleRotation; + m_HandleMatrixInverse = Matrix4x4.TRS(m_HandlePosition, m_HandleRotation, Vector3.one).inverse; + + ProBuilderEditor.instance.OnBeginVertexMovement(); + + m_Selection.Clear(); + + foreach (var mesh in MeshSelection.topInternal) + { + var groups = new List(); + var pivotMode = Tools.pivotMode.ProBuilderPivot(); + var orientation = ProBuilderEditor.handleOrientation; + ElementGroup.GetElementGroups(mesh, pivotMode, groups); + m_Selection.Add(new MeshAndElementSelection(mesh, groups)); + } + } + + /// + /// + /// + /// The translation to apply in handle coordinates (usually this corresponds to world space). + protected void ApplyTranslation(Vector3 translation) + { + var t = Quaternion.Inverse(m_HandleRotationOrigin) * translation; + + foreach (var selectionGroup in m_Selection) + { + var mesh = selectionGroup.mesh; + var origins = selectionGroup.positions; + var positions = mesh.positionsInternal; + + foreach (var group in selectionGroup.selection) + { + foreach (var index in group.indices) + { + positions[index] = origins[index] + t; + } + } + + mesh.mesh.vertices = positions; + +// mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); +// mesh.Refresh(RefreshMask.Normals); +// mesh.mesh.RecalculateBounds(); + } + + ProBuilderEditor.UpdateMeshHandles(); + } + + protected void FinishEdit() + { + if (!m_IsEditing) + return; + + ProBuilderEditor.instance.OnFinishVertexModification(); + + m_IsEditing = false; + } + + public void OnSceneGUI(Event evt) + { + if (evt.alt) + return; + + m_HandlePosition = MeshSelection.GetHandlePosition(); + m_HandleRotation = MeshSelection.GetHandleRotation(ProBuilderEditor.handleOrientation); + + DoTool(m_HandlePosition, m_HandleRotation); + + if (evt.type == EventType.MouseUp || evt.type == EventType.Ignore) + FinishEdit(); + + } + + protected abstract void DoTool(Vector3 handlePosition, Quaternion handleRotation); +} + +class MoveTool : VertexManipulationTool +{ + Vector3 m_HandlePosition; + Vector3 delta = Vector3.zero; + + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) + { + if (!m_IsEditing) + m_HandlePosition = handlePosition; + + EditorGUI.BeginChangeCheck(); + + m_HandlePosition = Handles.PositionHandle(m_HandlePosition, handleRotation); + + if (EditorGUI.EndChangeCheck()) + { + if(!m_IsEditing) + BeginEdit(); + + delta = m_HandlePosition - handlePositionOrigin; + + ApplyTranslation(delta); + } + + Handles.BeginGUI(); + GUILayout.Label(delta.ToString()); + Handles.EndGUI(); + +// +// if (!m_IsMovingElements) +// m_ElementHandlePosition = m_HandlePosition; +// +// m_ElementHandleCachedPosition = m_ElementHandlePosition; +// +// m_ElementHandlePosition = Handles.PositionHandle(m_ElementHandlePosition, m_HandleRotation); +// +// if (m_CurrentEvent.alt) +// return; +// +// if (m_ElementHandlePosition != m_ElementHandleCachedPosition) +// { +// Vector3 diff = m_ElementHandlePosition - m_ElementHandleCachedPosition; +// +// Vector3 mask = diff.ToMask(Math.handleEpsilon); +// +// if (m_DoSnapToVertex) +// { +// Vector3 v; +// +// if (FindNearestVertex(m_CurrentEvent.mousePosition, out v)) +// diff = Vector3.Scale(v - m_ElementHandleCachedPosition, mask); +// } +// else if (m_DoSnapToFace) +// { +// ProBuilderMesh obj = null; +// RaycastHit hit; +// Dictionary> ignore = new Dictionary>(); +// foreach (ProBuilderMesh pb in selection) +// ignore.Add(pb, new HashSet(pb.selectedFacesInternal)); +// +// if (EditorHandleUtility.FaceRaycast(m_CurrentEvent.mousePosition, out obj, out hit, ignore)) +// { +// if (mask.IntSum() == 1) +// { +// Ray r = new Ray(m_ElementHandleCachedPosition, -mask); +// Plane plane = new Plane(obj.transform.TransformDirection(hit.normal).normalized, +// obj.transform.TransformPoint(hit.point)); +// +// float forward, backward; +// plane.Raycast(r, out forward); +// plane.Raycast(r, out backward); +// float planeHit = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; +// r.direction = -r.direction; +// plane.Raycast(r, out forward); +// plane.Raycast(r, out backward); +// float rev = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; +// if (Mathf.Abs(rev) > Mathf.Abs(planeHit)) +// planeHit = rev; +// +// if (Mathf.Abs(planeHit) > Mathf.Epsilon) +// diff = mask * -planeHit; +// } +// else +// { +// diff = Vector3.Scale(obj.transform.TransformPoint(hit.point) - m_ElementHandleCachedPosition, mask.Abs()); +// } +// } +// } +// +// if (!m_IsMovingElements) +// { +// m_IsMovingElements = true; +// m_TranslateOrigin = m_ElementHandleCachedPosition; +// m_RotateOrigin = m_HandleRotation.eulerAngles; +// m_ScaleOrigin = m_HandleScale; +// +// OnBeginVertexMovement(); +// +// if (Event.current.modifiers == EventModifiers.Shift) +// ShiftExtrude(); +// +// ProGridsInterface.OnHandleMove(mask); +// } +// +// for (int i = 0; i < selection.Length; i++) +// { +// var mesh = selection[i]; +// +// mesh.TranslateVerticesInWorldSpace(mesh.selectedIndexesInternal, +// diff, +// m_SnapEnabled ? m_SnapValue : 0f, +// m_SnapAxisConstraint); +// +// mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); +// mesh.Refresh(RefreshMask.Normals); +// mesh.mesh.RecalculateBounds(); +// } +// +// UpdateMeshHandles(); +// } + } +} diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs.meta b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs.meta new file mode 100644 index 000000000..fd3dd9ffe --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c8e151d527dfd9f42b7ecd605b9d42cc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index 7565dc9bb..a87edaab9 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -98,20 +98,22 @@ internal SelectionModifierBehavior selectionModifierBehavior } } - internal HandleOrientation handleOrientation + internal static HandleOrientation handleOrientation { - get { return m_HandleOrientation.value; } + get { return s_HandleOrientation.value; } set { - if (value == m_HandleOrientation.value) + if (value == s_HandleOrientation.value) return; if (selectMode.ContainsFlag(SelectMode.TextureFace)) value = HandleOrientation.Normal; - m_HandleOrientation.SetValue(value, true); - m_HandleRotation = GetHandleRotation(); + s_HandleOrientation.SetValue(value, true); + + if(instance != null) + instance.m_HandleRotation = MeshSelection.GetHandleRotation(s_HandleOrientation); } } @@ -255,10 +257,10 @@ public static SelectMode selectMode Tools.current = s_Instance.m_CurrentTool; if (value == SelectMode.TextureFace) - s_Instance.m_PreviousHandleOrientation = s_Instance.m_HandleOrientation; + s_Instance.m_PreviousHandleOrientation = s_HandleOrientation; if (previous == SelectMode.TextureFace) - s_Instance.handleOrientation = s_Instance.m_PreviousHandleOrientation; + handleOrientation = s_Instance.m_PreviousHandleOrientation; if (selectModeChanged != null) selectModeChanged(value); @@ -616,7 +618,7 @@ void OnSceneGUI(SceneView sceneView) if ((m_IsMovingElements || m_IsMovingTextures) && GUIUtility.hotControl < 1) { OnFinishVertexModification(); - m_HandleRotation = GetHandleRotation(); + m_HandleRotation = MeshSelection.GetHandleRotation(s_HandleOrientation); UpdateTextureHandles(); } @@ -797,8 +799,17 @@ void DoubleClick(Event e) } } + static VertexManipulationTool s_MoveTool; + void VertexMoveTool() { + if(s_MoveTool == null) + s_MoveTool = new MoveTool(); + + s_MoveTool.OnSceneGUI(Event.current); + + return; + if (!m_IsMovingElements) m_ElementHandlePosition = m_HandlePosition; @@ -809,11 +820,8 @@ void VertexMoveTool() if (m_CurrentEvent.alt) return; - bool previouslyMoving = m_IsMovingElements; - if (m_ElementHandlePosition != m_ElementHandleCachedPosition) { - // profiler.BeginSample("VertexMoveTool()"); Vector3 diff = m_ElementHandlePosition - m_ElementHandleCachedPosition; Vector3 mask = diff.ToMask(Math.handleEpsilon); @@ -861,16 +869,10 @@ void VertexMoveTool() } } } - // else if(snapToEdge && nearestEdge.IsValid()) - // { - // // FINDME - - // } - - m_IsMovingElements = true; - if (previouslyMoving == false) + if (!m_IsMovingElements) { + m_IsMovingElements = true; m_TranslateOrigin = m_ElementHandleCachedPosition; m_RotateOrigin = m_HandleRotation.eulerAngles; m_ScaleOrigin = m_HandleScale; @@ -942,7 +944,7 @@ void VertexScaleTool() Vector3 ver; // resulting vertex from modification Vector3 over; // vertex point to modify. different for world, local, and plane - bool gotoWorld = Selection.transforms.Length > 1 && m_HandleOrientation == HandleOrientation.Normal; + bool gotoWorld = Selection.transforms.Length > 1 && s_HandleOrientation == HandleOrientation.Normal; bool gotoLocal = MeshSelection.selectedFaceCount < 1; // if(pref_snapEnabled) @@ -960,7 +962,7 @@ void VertexScaleTool() for (int n = 0; n < mesh.selectedIndexesInternal.Length; n++) { - switch (m_HandleOrientation.value) + switch (s_HandleOrientation.value) { case HandleOrientation.Normal: { @@ -1068,7 +1070,7 @@ void VertexRotateTool() for (int nn = 0; nn < triangles.Length; nn++) m_VertexPositions[i][nn] = selection[i].transform.TransformPoint(vertices[triangles[nn]]); - if (m_HandleOrientation == HandleOrientation.World) + if (s_HandleOrientation == HandleOrientation.World) m_VertexOffset[i] = m_ElementHandlePosition; else m_VertexOffset[i] = Math.GetBounds(m_VertexPositions[i]).center; @@ -1508,7 +1510,7 @@ bool GeoLevelShortcuts(Shortcut shortcut) return false; ToggleHandleAlignment(); - EditorUtility.ShowNotification("Handle Alignment: " + m_HandleOrientation.value.ToString()); + EditorUtility.ShowNotification("Handle Alignment: " + s_HandleOrientation.value.ToString()); return true; case "Set Pivot": @@ -1562,7 +1564,7 @@ void SetTool_Internal(Tool newTool) internal void ToggleHandleAlignment() { - int newHa = (int) m_HandleOrientation.value + 1; + int newHa = (int) s_HandleOrientation.value + 1; if (newHa >= Enum.GetValues(typeof(HandleOrientation)).Length) newHa = 0; handleOrientation = ((HandleOrientation) newHa); @@ -1585,8 +1587,8 @@ void UpdateSelection(bool selectionChanged = true) { selection = MeshSelection.topInternal; - m_HandlePosition = GetHandlePosition(); - m_HandleRotation = GetHandleRotation(); + m_HandlePosition = MeshSelection.GetHandlePosition(); + m_HandleRotation = MeshSelection.GetHandleRotation(s_HandleOrientation); UpdateTextureHandles(); UpdateMeshHandles(selectionChanged); @@ -1601,19 +1603,22 @@ void UpdateSelection(bool selectionChanged = true) selectionUpdated(selection); } - void UpdateMeshHandles(bool selectionOrVertexCountChanged) + static void UpdateMeshHandles(bool selectionOrVertexCountChanged) { - if (m_EditorMeshHandles == null) + if (!s_Instance) + return; + + if (s_Instance.m_EditorMeshHandles == null) return; try { - m_EditorMeshHandles.RebuildSelectedHandles(MeshSelection.topInternal, selectMode, selectionOrVertexCountChanged); + s_Instance.m_EditorMeshHandles.RebuildSelectedHandles(MeshSelection.topInternal, selectMode, selectionOrVertexCountChanged); } catch { // happens on undo when c++ object is gone but c# isn't in the know - m_EditorMeshHandles.ClearHandles(); + s_Instance.m_EditorMeshHandles.ClearHandles(); } } @@ -1671,49 +1676,6 @@ void UpdateTextureHandles() } } - internal Vector3 GetHandlePosition() - { - MeshSelection.RecalculateSelectionBounds(); - return MeshSelection.bounds.center; - } - - internal Quaternion GetHandleRotation() - { - Quaternion localRotation = Selection.activeTransform == null ? Quaternion.identity : Selection.activeTransform.rotation; - - switch (m_HandleOrientation.value) - { - case HandleOrientation.Normal: - - if (Selection.transforms.Length > 1) - goto default; - - ProBuilderMesh pb; - Face face; - - if (!GetFirstSelectedFace(out pb, out face)) - goto case HandleOrientation.Local; - - // use average normal, tangent, and bi-tangent to calculate rotation relative to local space - var tup = Math.NormalTangentBitangent(pb, face); - Vector3 nrm = tup.normal, bitan = tup.bitangent; - - if (nrm == Vector3.zero || bitan == Vector3.zero) - { - nrm = Vector3.up; - bitan = Vector3.right; - } - - return localRotation * Quaternion.LookRotation(nrm, bitan); - - case HandleOrientation.Local: - return localRotation; - - default: - return Quaternion.identity; - } - } - /// /// Find the nearest vertex among all visible objects. /// @@ -1849,7 +1811,7 @@ internal void OnBeginTextureModification() /// When beginning a vertex modification, nuke the UV2 and rebuild the mesh using PB data so that triangles /// match vertices (and no inserted vertices from the Unwrapping.GenerateSecondaryUVSet() remain). /// - void OnBeginVertexMovement() + internal void OnBeginVertexMovement() { switch (m_CurrentTool) { @@ -1887,12 +1849,12 @@ void OnBeginVertexMovement() beforeMeshModification(selection); } - void OnFinishVertexModification() + internal void OnFinishVertexModification() { Lightmapping.PopGIWorkflowMode(); m_HandleScale = Vector3.one; - m_HandleRotation = GetHandleRotation(); + m_HandleRotation = MeshSelection.GetHandleRotation(s_HandleOrientation); if (m_IsMovingTextures) { diff --git a/com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleAlignment.cs b/com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleAlignment.cs index 83420202d..fa9c02105 100644 --- a/com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleAlignment.cs +++ b/com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleAlignment.cs @@ -13,8 +13,8 @@ sealed class ToggleHandleAlignment : MenuAction HandleOrientation handleOrientation { - get { return ProBuilderEditor.instance == null ? HandleOrientation.World : ProBuilderEditor.instance.handleOrientation; } - set { ProBuilderEditor.instance.handleOrientation = value; } + get { return ProBuilderEditor.instance == null ? HandleOrientation.World : ProBuilderEditor.handleOrientation; } + set { ProBuilderEditor.handleOrientation = value; } } public override ToolbarGroup group diff --git a/com.unity.probuilder/Runtime/Core/HandleOrientation.cs b/com.unity.probuilder/Runtime/Core/HandleOrientation.cs new file mode 100644 index 000000000..a3f2f6d40 --- /dev/null +++ b/com.unity.probuilder/Runtime/Core/HandleOrientation.cs @@ -0,0 +1,25 @@ +namespace UnityEngine.ProBuilder +{ + /// + /// How the handle gizmo is oriented with regards to the current element selection. + /// + /// + /// This overrides the Unity Pivot / Global setting when editing vertices, faces, or edges. + /// + /// Editor only. + public enum HandleOrientation + { + /// + /// The gizmo is aligned in world space. + /// + World = 0, + /// + /// The gizmo is aligned relative to the mesh transform. Also called coordinate or model space. + /// + Local = 1, + /// + /// The gizmo is aligned relative to the currently selected face. When editing vertices or edges, this falls back to alignment. + /// + Normal = 2 + } +} diff --git a/com.unity.probuilder/Runtime/Core/HandleOrientation.cs.meta b/com.unity.probuilder/Runtime/Core/HandleOrientation.cs.meta new file mode 100644 index 000000000..d1b2d7155 --- /dev/null +++ b/com.unity.probuilder/Runtime/Core/HandleOrientation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2e52c205e35f30d4c81ff62d3f94e234 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.probuilder/Runtime/Core/PivotPoint.cs b/com.unity.probuilder/Runtime/Core/PivotPoint.cs new file mode 100644 index 000000000..bbecb0f1b --- /dev/null +++ b/com.unity.probuilder/Runtime/Core/PivotPoint.cs @@ -0,0 +1,27 @@ +namespace UnityEngine.ProBuilder +{ + public enum PivotPoint + { + /// + /// Transforms are applied from the center point of the selection bounding box. + /// Corresponds with . + /// + WorldBoundingBoxCenter = 1 << 0, + + /// + /// Transforms are applied in model space from the average point of selected elements. + /// Corresponds with . + /// + ModelBoundingBoxCenter = 1 << 1, + + /// + /// Transforms are applied from the origin of each selection group. + /// + IndividualOrigins = 1 << 2, + + /// + /// Transforms are applied from a user-defined pivot point. + /// + Custom = 1 << 3 + } +} diff --git a/com.unity.probuilder/Runtime/Core/PivotPoint.cs.meta b/com.unity.probuilder/Runtime/Core/PivotPoint.cs.meta new file mode 100644 index 000000000..1ba99919a --- /dev/null +++ b/com.unity.probuilder/Runtime/Core/PivotPoint.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3abdb0569285bbf4389d38655d5a90a3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From f850c3f21f8480b49985c2449b4364420dbacdbb Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Thu, 18 Oct 2018 16:14:42 -0400 Subject: [PATCH 02/27] support translate in world and model space --- .../Debug/Editor/TempMenuItems.cs | 7 -- .../Editor/EditorCore/MeshSelection.cs | 20 +-- .../Editor/EditorCore/MoveTool.cs | 115 ++++++++++-------- .../Editor/EditorCore/ProBuilderEditor.cs | 7 +- com.unity.probuilder/Runtime/Core/Math.cs | 39 ++++-- 5 files changed, 108 insertions(+), 80 deletions(-) diff --git a/com.unity.probuilder/Debug/Editor/TempMenuItems.cs b/com.unity.probuilder/Debug/Editor/TempMenuItems.cs index 12a7f8339..a0784fb23 100644 --- a/com.unity.probuilder/Debug/Editor/TempMenuItems.cs +++ b/com.unity.probuilder/Debug/Editor/TempMenuItems.cs @@ -10,13 +10,6 @@ class TempMenuItems : EditorWindow [MenuItem("Tools/Temp Menu Item &d", false, 1000)] static void MenuInit() { - string[] search = new[] - { - "Assets/Temp.cs", - "Assets/*.cs", - "*.cs" - }; - } diff --git a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs index bf3f48d1e..47b76aa58 100644 --- a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs +++ b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs @@ -69,6 +69,14 @@ static MeshSelection() OnObjectSelectionChanged(); } + /// + /// Returns the active selected mesh. + /// + public static ProBuilderMesh activeMesh + { + get { return selectedObjectCount > 0 ? s_TopSelection[selectedObjectCount - 1] : null; } + } + /// /// Receive notifications when the object selection changes. /// @@ -329,13 +337,11 @@ internal static Vector3 GetHandlePosition() { case PivotMode.Pivot: { - ProBuilderMesh mesh; - Face face; - - if (!GetFirstSelectedFace(out mesh, out face)) - goto default; - - return mesh.transform.TransformPoint(Math.Average(mesh.positionsInternal, face.distinctIndexesInternal)); + var mesh = activeMesh; + if (mesh == null) + return Vector3.zero; + var center = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); + return mesh.transform.TransformPoint(center.center); } default: diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs index 1b3f7b9ee..084bef5f8 100644 --- a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs @@ -10,6 +10,7 @@ struct MeshAndElementSelection ProBuilderMesh m_Mesh; Vector3[] m_Positions; List m_Selection; + bool m_ApplyDeltaInWorldSpace; public ProBuilderMesh mesh { @@ -26,11 +27,20 @@ public List selection get { return m_Selection; } } - public MeshAndElementSelection(ProBuilderMesh mesh, List groups) + public bool applyDeltaInWorldSpace + { + get { return m_ApplyDeltaInWorldSpace; } + } + + public MeshAndElementSelection(ProBuilderMesh mesh, PivotPoint pivot) { m_Mesh = mesh; m_Positions = mesh.positions.ToArray(); + m_ApplyDeltaInWorldSpace = pivot == PivotPoint.WorldBoundingBoxCenter; + var groups = new List(); + ElementGroup.GetElementGroups(mesh, pivot, groups); m_Selection = groups; + } } @@ -38,44 +48,43 @@ struct ElementGroup { List m_Indices; Matrix4x4 m_Matrix; - bool m_ApplyDeltaInWorldSpace; public List indices { get { return m_Indices; } } + /// + /// The coordinate space in which vertices are transformed. + /// public Matrix4x4 matrix { get { return m_Matrix; } } - public bool applyDeltaInWorldSpace + public Matrix4x4 inverseMatrix { - get { return m_ApplyDeltaInWorldSpace; } + get { return m_Matrix.inverse; } } public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List groups) { Matrix4x4 matrix = Matrix4x4.identity; - bool applyDeltaInWorldSpace; switch (pivot) { case PivotPoint.ModelBoundingBoxCenter: - matrix = Matrix4x4.identity; - applyDeltaInWorldSpace = false; + var bounds = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); + matrix = Matrix4x4.TRS(-bounds.center, Quaternion.identity, Vector3.one); break; case PivotPoint.IndividualOrigins: - applyDeltaInWorldSpace = false; break; // case PivotPoint.WorldBoundingBoxCenter: // case PivotPoint.Custom: default: matrix = mesh.transform.localToWorldMatrix; - applyDeltaInWorldSpace = true; break; } @@ -83,7 +92,6 @@ public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List< { m_Indices = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal), m_Matrix = matrix, - m_ApplyDeltaInWorldSpace = applyDeltaInWorldSpace }); } } @@ -95,7 +103,6 @@ abstract class VertexManipulationTool Vector3 m_HandlePositionOrigin; Quaternion m_HandleRotationOrigin; - Matrix4x4 m_HandleMatrixInverse; protected Vector3 handlePositionOrigin { @@ -111,6 +118,25 @@ protected Quaternion handleRotationOrigin protected bool m_IsEditing; + public void OnSceneGUI(Event evt) + { + if (evt.type == EventType.MouseUp || evt.type == EventType.Ignore) + FinishEdit(); + + if (evt.alt) + return; + + if (!m_IsEditing) + { + m_HandlePosition = MeshSelection.GetHandlePosition(); + m_HandleRotation = MeshSelection.GetHandleRotation(ProBuilderEditor.handleOrientation); + } + + DoTool(m_HandlePosition, m_HandleRotation); + } + + protected abstract void DoTool(Vector3 handlePosition, Quaternion handleRotation); + protected void BeginEdit() { if (m_IsEditing) @@ -120,7 +146,6 @@ protected void BeginEdit() m_HandlePositionOrigin = m_HandlePosition; m_HandleRotationOrigin = m_HandleRotation; - m_HandleMatrixInverse = Matrix4x4.TRS(m_HandlePosition, m_HandleRotation, Vector3.one).inverse; ProBuilderEditor.instance.OnBeginVertexMovement(); @@ -128,24 +153,36 @@ protected void BeginEdit() foreach (var mesh in MeshSelection.topInternal) { - var groups = new List(); - var pivotMode = Tools.pivotMode.ProBuilderPivot(); - var orientation = ProBuilderEditor.handleOrientation; - ElementGroup.GetElementGroups(mesh, pivotMode, groups); - m_Selection.Add(new MeshAndElementSelection(mesh, groups)); + var pivot = Tools.pivotMode == PivotMode.Center + ? PivotPoint.WorldBoundingBoxCenter + : PivotPoint.ModelBoundingBoxCenter; + + m_Selection.Add(new MeshAndElementSelection(mesh, pivot)); } } + protected void FinishEdit() + { + if (!m_IsEditing) + return; + + ProBuilderEditor.instance.OnFinishVertexModification(); + + m_IsEditing = false; + } + /// /// /// /// The translation to apply in handle coordinates (usually this corresponds to world space). protected void ApplyTranslation(Vector3 translation) { - var t = Quaternion.Inverse(m_HandleRotationOrigin) * translation; - foreach (var selectionGroup in m_Selection) { + var delta = selectionGroup.applyDeltaInWorldSpace + ? translation + : Quaternion.Inverse(m_HandleRotationOrigin) * translation; + var mesh = selectionGroup.mesh; var origins = selectionGroup.positions; var positions = mesh.positionsInternal; @@ -154,46 +191,18 @@ protected void ApplyTranslation(Vector3 translation) { foreach (var index in group.indices) { - positions[index] = origins[index] + t; + // todo Move matrix * origin to selection group c'tor + positions[index] = group.inverseMatrix.MultiplyPoint3x4(group.matrix.MultiplyPoint3x4(origins[index]) + delta); } } mesh.mesh.vertices = positions; - -// mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); -// mesh.Refresh(RefreshMask.Normals); -// mesh.mesh.RecalculateBounds(); + mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); + mesh.Refresh(RefreshMask.Normals); } - ProBuilderEditor.UpdateMeshHandles(); - } - - protected void FinishEdit() - { - if (!m_IsEditing) - return; - - ProBuilderEditor.instance.OnFinishVertexModification(); - - m_IsEditing = false; - } - - public void OnSceneGUI(Event evt) - { - if (evt.alt) - return; - - m_HandlePosition = MeshSelection.GetHandlePosition(); - m_HandleRotation = MeshSelection.GetHandleRotation(ProBuilderEditor.handleOrientation); - - DoTool(m_HandlePosition, m_HandleRotation); - - if (evt.type == EventType.MouseUp || evt.type == EventType.Ignore) - FinishEdit(); - + ProBuilderEditor.UpdateMeshHandles(false); } - - protected abstract void DoTool(Vector3 handlePosition, Quaternion handleRotation); } class MoveTool : VertexManipulationTool @@ -224,7 +233,7 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation GUILayout.Label(delta.ToString()); Handles.EndGUI(); -// + // if (!m_IsMovingElements) // m_ElementHandlePosition = m_HandlePosition; // diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index a87edaab9..1708f443d 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -70,9 +70,10 @@ public sealed class ProBuilderEditor : EditorWindow, IHasCustomMenu internal Pref m_ExtrudeMethod = new Pref("editor.extrudeMethod", ExtrudeMethod.FaceNormal); internal Pref m_SelectModifierBehavior = new Pref("editor.rectSelectModifier", SelectionModifierBehavior.Difference); internal Pref m_ExtrudeEdgesAsGroup = new Pref("editor.extrudeEdgesAsGroup", true); - internal Pref m_HandleOrientation = new Pref("editor.handleAlignment", HandleOrientation.World); Pref m_SelectMode = new Pref("editor.selectMode", SelectMode.Object); + internal static Pref s_HandleOrientation = new Pref("editor.handleAlignment", HandleOrientation.World); + internal RectSelectMode rectSelectMode { get { return m_DragSelectRectMode.value; } @@ -265,7 +266,7 @@ public static SelectMode selectMode if (selectModeChanged != null) selectModeChanged(value); - s_Instance.UpdateMeshHandles(true); + UpdateMeshHandles(true); s_Instance.Repaint(); } } @@ -1603,7 +1604,7 @@ void UpdateSelection(bool selectionChanged = true) selectionUpdated(selection); } - static void UpdateMeshHandles(bool selectionOrVertexCountChanged) + internal static void UpdateMeshHandles(bool selectionOrVertexCountChanged = true) { if (!s_Instance) return; diff --git a/com.unity.probuilder/Runtime/Core/Math.cs b/com.unity.probuilder/Runtime/Core/Math.cs index 717a5a2d0..bb8d4cab7 100644 --- a/com.unity.probuilder/Runtime/Core/Math.cs +++ b/com.unity.probuilder/Runtime/Core/Math.cs @@ -937,24 +937,43 @@ internal static Vector2 LargestVector2(Vector2[] v, int[] indexes) /// /// /// - internal static Bounds GetBounds(Vector3[] positions) + internal static Bounds GetBounds(Vector3[] positions, int[] indices = null) { - if (positions.Length < 1) + bool hasIndices = indices != null; + + if ((hasIndices && indices.Length < 1) || positions.Length < 1) return default(Bounds); - Vector3 min = positions[0]; + Vector3 min = positions[hasIndices ? indices[0] : 0]; Vector3 max = min; - for(int i = 1, c = positions.Length; i < c; i++) + if (hasIndices) + { + for(int i = 1, c = indices.Length; i < c; i++) + { + min.x = Mathf.Min(positions[indices[i]].x, min.x); + max.x = Mathf.Max(positions[indices[i]].x, max.x); + + min.y = Mathf.Min(positions[indices[i]].y, min.y); + max.y = Mathf.Max(positions[indices[i]].y, max.y); + + min.z = Mathf.Min(positions[indices[i]].z, min.z); + max.z = Mathf.Max(positions[indices[i]].z, max.z); + } + } + else { - min.x = Mathf.Min(positions[i].x, min.x); - max.x = Mathf.Max(positions[i].x, max.x); + for(int i = 1, c = positions.Length; i < c; i++) + { + min.x = Mathf.Min(positions[i].x, min.x); + max.x = Mathf.Max(positions[i].x, max.x); - min.y = Mathf.Min(positions[i].y, min.y); - max.y = Mathf.Max(positions[i].y, max.y); + min.y = Mathf.Min(positions[i].y, min.y); + max.y = Mathf.Max(positions[i].y, max.y); - min.z = Mathf.Min(positions[i].z, min.z); - max.z = Mathf.Max(positions[i].z, max.z); + min.z = Mathf.Min(positions[i].z, min.z); + max.z = Mathf.Max(positions[i].z, max.z); + } } return new Bounds((min+max) * .5f, max - min); From b70ff8be7c1a6a7ff8cd3c57da56dcaab6950ecc Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Thu, 18 Oct 2018 17:22:04 -0400 Subject: [PATCH 03/27] wip - use new tool classes for rotate and scale --- .../Editor/EditorCore/MoveTool.cs | 585 ++++++++++-------- .../Editor/EditorCore/ProBuilderEditor.cs | 13 + 2 files changed, 330 insertions(+), 268 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs index 084bef5f8..315a682c1 100644 --- a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs @@ -5,325 +5,374 @@ using UnityEngine; using UnityEngine.ProBuilder; -struct MeshAndElementSelection +namespace UnityEditor.ProBuilder { - ProBuilderMesh m_Mesh; - Vector3[] m_Positions; - List m_Selection; - bool m_ApplyDeltaInWorldSpace; - - public ProBuilderMesh mesh - { - get { return m_Mesh; } - } - - public Vector3[] positions - { - get { return m_Positions; } - } - - public List selection + struct MeshAndElementSelection { - get { return m_Selection; } - } + ProBuilderMesh m_Mesh; + Vector3[] m_Positions; + List m_Selection; + bool m_ApplyDeltaInWorldSpace; - public bool applyDeltaInWorldSpace - { - get { return m_ApplyDeltaInWorldSpace; } - } + public ProBuilderMesh mesh + { + get { return m_Mesh; } + } - public MeshAndElementSelection(ProBuilderMesh mesh, PivotPoint pivot) - { - m_Mesh = mesh; - m_Positions = mesh.positions.ToArray(); - m_ApplyDeltaInWorldSpace = pivot == PivotPoint.WorldBoundingBoxCenter; - var groups = new List(); - ElementGroup.GetElementGroups(mesh, pivot, groups); - m_Selection = groups; + public Vector3[] positions + { + get { return m_Positions; } + } - } -} + public List selection + { + get { return m_Selection; } + } -struct ElementGroup -{ - List m_Indices; - Matrix4x4 m_Matrix; + public bool applyDeltaInWorldSpace + { + get { return m_ApplyDeltaInWorldSpace; } + } - public List indices - { - get { return m_Indices; } - } + public MeshAndElementSelection(ProBuilderMesh mesh, PivotPoint pivot) + { + m_Mesh = mesh; + m_Positions = mesh.positions.ToArray(); + m_ApplyDeltaInWorldSpace = pivot == PivotPoint.WorldBoundingBoxCenter; + var groups = new List(); + ElementGroup.GetElementGroups(mesh, pivot, groups); + m_Selection = groups; - /// - /// The coordinate space in which vertices are transformed. - /// - public Matrix4x4 matrix - { - get { return m_Matrix; } + } } - public Matrix4x4 inverseMatrix + struct ElementGroup { - get { return m_Matrix.inverse; } - } + List m_Indices; + Matrix4x4 m_Matrix; - public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List groups) - { - Matrix4x4 matrix = Matrix4x4.identity; + public List indices + { + get { return m_Indices; } + } - switch (pivot) + /// + /// The coordinate space in which vertices are transformed. + /// + public Matrix4x4 matrix { - case PivotPoint.ModelBoundingBoxCenter: - var bounds = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); - matrix = Matrix4x4.TRS(-bounds.center, Quaternion.identity, Vector3.one); - break; - - case PivotPoint.IndividualOrigins: - break; - -// case PivotPoint.WorldBoundingBoxCenter: -// case PivotPoint.Custom: - default: - matrix = mesh.transform.localToWorldMatrix; - break; + get { return m_Matrix; } } - groups.Add(new ElementGroup() + public Matrix4x4 inverseMatrix { - m_Indices = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal), - m_Matrix = matrix, - }); - } -} + get { return m_Matrix.inverse; } + } -abstract class VertexManipulationTool -{ - Vector3 m_HandlePosition; - Quaternion m_HandleRotation; + public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List groups) + { + Matrix4x4 matrix = Matrix4x4.identity; - Vector3 m_HandlePositionOrigin; - Quaternion m_HandleRotationOrigin; + switch (pivot) + { + case PivotPoint.ModelBoundingBoxCenter: + // Vertices will be transformed in local space + var bounds = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); + matrix = Matrix4x4.TRS(-bounds.center, Quaternion.identity, Vector3.one); + break; + + case PivotPoint.IndividualOrigins: + break; + + // case PivotPoint.WorldBoundingBoxCenter: + // case PivotPoint.Custom: + default: + matrix = Matrix4x4.identity; + break; + } - protected Vector3 handlePositionOrigin - { - get { return m_HandlePositionOrigin; } + groups.Add(new ElementGroup() + { + m_Indices = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal), + m_Matrix = matrix, + }); + } } - protected Quaternion handleRotationOrigin + abstract class VertexManipulationTool { - get { return m_HandleRotationOrigin; } - } + Vector3 m_HandlePosition; + Quaternion m_HandleRotation; - protected List m_Selection = new List(); + Vector3 m_HandlePositionOrigin; + Quaternion m_HandleRotationOrigin; + protected Quaternion handleRotationOriginInverse { get; private set; } - protected bool m_IsEditing; + protected Vector3 handlePositionOrigin + { + get { return m_HandlePositionOrigin; } + } - public void OnSceneGUI(Event evt) - { - if (evt.type == EventType.MouseUp || evt.type == EventType.Ignore) - FinishEdit(); + protected Quaternion handleRotationOrigin + { + get { return m_HandleRotationOrigin; } + } - if (evt.alt) - return; + protected List m_Selection = new List(); - if (!m_IsEditing) + protected bool m_IsEditing; + + public void OnSceneGUI(Event evt) { - m_HandlePosition = MeshSelection.GetHandlePosition(); - m_HandleRotation = MeshSelection.GetHandleRotation(ProBuilderEditor.handleOrientation); + if (evt.type == EventType.MouseUp || evt.type == EventType.Ignore) + FinishEdit(); + + if (evt.alt) + return; + + if (!m_IsEditing) + { + m_HandlePosition = MeshSelection.GetHandlePosition(); + m_HandleRotation = MeshSelection.GetHandleRotation(ProBuilderEditor.handleOrientation); + } + + DoTool(m_HandlePosition, m_HandleRotation); } - DoTool(m_HandlePosition, m_HandleRotation); - } + protected abstract void DoTool(Vector3 handlePosition, Quaternion handleRotation); - protected abstract void DoTool(Vector3 handlePosition, Quaternion handleRotation); + protected void BeginEdit() + { + if (m_IsEditing) + return; - protected void BeginEdit() - { - if (m_IsEditing) - return; + m_IsEditing = true; - m_IsEditing = true; + m_HandlePositionOrigin = m_HandlePosition; + m_HandleRotationOrigin = m_HandleRotation; + handleRotationOriginInverse = Quaternion.Inverse(m_HandleRotation); - m_HandlePositionOrigin = m_HandlePosition; - m_HandleRotationOrigin = m_HandleRotation; + ProBuilderEditor.instance.OnBeginVertexMovement(); - ProBuilderEditor.instance.OnBeginVertexMovement(); + m_Selection.Clear(); - m_Selection.Clear(); + foreach (var mesh in MeshSelection.topInternal) + { + var pivot = Tools.pivotMode == PivotMode.Center + ? PivotPoint.WorldBoundingBoxCenter + : PivotPoint.ModelBoundingBoxCenter; - foreach (var mesh in MeshSelection.topInternal) - { - var pivot = Tools.pivotMode == PivotMode.Center - ? PivotPoint.WorldBoundingBoxCenter - : PivotPoint.ModelBoundingBoxCenter; + m_Selection.Add(new MeshAndElementSelection(mesh, pivot)); + } + } - m_Selection.Add(new MeshAndElementSelection(mesh, pivot)); - } - } + protected void FinishEdit() + { + if (!m_IsEditing) + return; - protected void FinishEdit() - { - if (!m_IsEditing) - return; + ProBuilderEditor.instance.OnFinishVertexModification(); - ProBuilderEditor.instance.OnFinishVertexModification(); + m_IsEditing = false; + } - m_IsEditing = false; - } + /// + /// + /// + protected void Apply(Matrix4x4 delta) + { + foreach (var selectionGroup in m_Selection) + { + var mesh = selectionGroup.mesh; + var origins = selectionGroup.positions; + var positions = mesh.positionsInternal; + + foreach (var group in selectionGroup.selection) + { + foreach (var index in group.indices) + { + // todo Move matrix * origin to selection group c'tor + if (selectionGroup.applyDeltaInWorldSpace) + { + positions[index] = group.inverseMatrix.MultiplyPoint3x4(delta.MultiplyPoint3x4(group.matrix.MultiplyPoint3x4(origins[index]))); + } + else + { + var p = group.matrix.MultiplyPoint3x4(origins[index]); + p = m_HandleRotationOrigin * p; + p = delta.MultiplyPoint3x4(p); + p = Quaternion.Inverse(m_HandleRotationOrigin) * p; + positions[index] = group.inverseMatrix.MultiplyPoint3x4(p); + } + } + } + + mesh.mesh.vertices = positions; + mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); + mesh.Refresh(RefreshMask.Normals); + } - /// - /// - /// - /// The translation to apply in handle coordinates (usually this corresponds to world space). - protected void ApplyTranslation(Vector3 translation) + ProBuilderEditor.UpdateMeshHandles(false); + } + } + + class MoveTool : VertexManipulationTool { - foreach (var selectionGroup in m_Selection) + Vector3 m_HandlePosition; + Vector3 delta = Vector3.zero; + + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { - var delta = selectionGroup.applyDeltaInWorldSpace - ? translation - : Quaternion.Inverse(m_HandleRotationOrigin) * translation; + if (!m_IsEditing) + m_HandlePosition = handlePosition; + + EditorGUI.BeginChangeCheck(); - var mesh = selectionGroup.mesh; - var origins = selectionGroup.positions; - var positions = mesh.positionsInternal; + m_HandlePosition = Handles.PositionHandle(m_HandlePosition, handleRotation); - foreach (var group in selectionGroup.selection) + if (EditorGUI.EndChangeCheck()) { - foreach (var index in group.indices) - { - // todo Move matrix * origin to selection group c'tor - positions[index] = group.inverseMatrix.MultiplyPoint3x4(group.matrix.MultiplyPoint3x4(origins[index]) + delta); - } + if (!m_IsEditing) + BeginEdit(); + + delta = m_HandlePosition - handlePositionOrigin; + + Apply(Matrix4x4.TRS(delta, Quaternion.identity, Vector3.one)); } - mesh.mesh.vertices = positions; - mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); - mesh.Refresh(RefreshMask.Normals); + // if (!m_IsMovingElements) + // m_ElementHandlePosition = m_HandlePosition; + // + // m_ElementHandleCachedPosition = m_ElementHandlePosition; + // + // m_ElementHandlePosition = Handles.PositionHandle(m_ElementHandlePosition, m_HandleRotation); + // + // if (m_CurrentEvent.alt) + // return; + // + // if (m_ElementHandlePosition != m_ElementHandleCachedPosition) + // { + // Vector3 diff = m_ElementHandlePosition - m_ElementHandleCachedPosition; + // + // Vector3 mask = diff.ToMask(Math.handleEpsilon); + // + // if (m_DoSnapToVertex) + // { + // Vector3 v; + // + // if (FindNearestVertex(m_CurrentEvent.mousePosition, out v)) + // diff = Vector3.Scale(v - m_ElementHandleCachedPosition, mask); + // } + // else if (m_DoSnapToFace) + // { + // ProBuilderMesh obj = null; + // RaycastHit hit; + // Dictionary> ignore = new Dictionary>(); + // foreach (ProBuilderMesh pb in selection) + // ignore.Add(pb, new HashSet(pb.selectedFacesInternal)); + // + // if (EditorHandleUtility.FaceRaycast(m_CurrentEvent.mousePosition, out obj, out hit, ignore)) + // { + // if (mask.IntSum() == 1) + // { + // Ray r = new Ray(m_ElementHandleCachedPosition, -mask); + // Plane plane = new Plane(obj.transform.TransformDirection(hit.normal).normalized, + // obj.transform.TransformPoint(hit.point)); + // + // float forward, backward; + // plane.Raycast(r, out forward); + // plane.Raycast(r, out backward); + // float planeHit = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; + // r.direction = -r.direction; + // plane.Raycast(r, out forward); + // plane.Raycast(r, out backward); + // float rev = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; + // if (Mathf.Abs(rev) > Mathf.Abs(planeHit)) + // planeHit = rev; + // + // if (Mathf.Abs(planeHit) > Mathf.Epsilon) + // diff = mask * -planeHit; + // } + // else + // { + // diff = Vector3.Scale(obj.transform.TransformPoint(hit.point) - m_ElementHandleCachedPosition, mask.Abs()); + // } + // } + // } + // + // if (!m_IsMovingElements) + // { + // m_IsMovingElements = true; + // m_TranslateOrigin = m_ElementHandleCachedPosition; + // m_RotateOrigin = m_HandleRotation.eulerAngles; + // m_ScaleOrigin = m_HandleScale; + // + // OnBeginVertexMovement(); + // + // if (Event.current.modifiers == EventModifiers.Shift) + // ShiftExtrude(); + // + // ProGridsInterface.OnHandleMove(mask); + // } + // + // for (int i = 0; i < selection.Length; i++) + // { + // var mesh = selection[i]; + // + // mesh.TranslateVerticesInWorldSpace(mesh.selectedIndexesInternal, + // diff, + // m_SnapEnabled ? m_SnapValue : 0f, + // m_SnapAxisConstraint); + // + // mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); + // mesh.Refresh(RefreshMask.Normals); + // mesh.mesh.RecalculateBounds(); + // } + // + // UpdateMeshHandles(); + // } } - ProBuilderEditor.UpdateMeshHandles(false); } -} -class MoveTool : VertexManipulationTool -{ - Vector3 m_HandlePosition; - Vector3 delta = Vector3.zero; - - protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) - { - if (!m_IsEditing) - m_HandlePosition = handlePosition; - - EditorGUI.BeginChangeCheck(); - - m_HandlePosition = Handles.PositionHandle(m_HandlePosition, handleRotation); - - if (EditorGUI.EndChangeCheck()) - { - if(!m_IsEditing) - BeginEdit(); - - delta = m_HandlePosition - handlePositionOrigin; - - ApplyTranslation(delta); - } - - Handles.BeginGUI(); - GUILayout.Label(delta.ToString()); - Handles.EndGUI(); - - -// if (!m_IsMovingElements) -// m_ElementHandlePosition = m_HandlePosition; -// -// m_ElementHandleCachedPosition = m_ElementHandlePosition; -// -// m_ElementHandlePosition = Handles.PositionHandle(m_ElementHandlePosition, m_HandleRotation); -// -// if (m_CurrentEvent.alt) -// return; -// -// if (m_ElementHandlePosition != m_ElementHandleCachedPosition) -// { -// Vector3 diff = m_ElementHandlePosition - m_ElementHandleCachedPosition; -// -// Vector3 mask = diff.ToMask(Math.handleEpsilon); -// -// if (m_DoSnapToVertex) -// { -// Vector3 v; -// -// if (FindNearestVertex(m_CurrentEvent.mousePosition, out v)) -// diff = Vector3.Scale(v - m_ElementHandleCachedPosition, mask); -// } -// else if (m_DoSnapToFace) -// { -// ProBuilderMesh obj = null; -// RaycastHit hit; -// Dictionary> ignore = new Dictionary>(); -// foreach (ProBuilderMesh pb in selection) -// ignore.Add(pb, new HashSet(pb.selectedFacesInternal)); -// -// if (EditorHandleUtility.FaceRaycast(m_CurrentEvent.mousePosition, out obj, out hit, ignore)) -// { -// if (mask.IntSum() == 1) -// { -// Ray r = new Ray(m_ElementHandleCachedPosition, -mask); -// Plane plane = new Plane(obj.transform.TransformDirection(hit.normal).normalized, -// obj.transform.TransformPoint(hit.point)); -// -// float forward, backward; -// plane.Raycast(r, out forward); -// plane.Raycast(r, out backward); -// float planeHit = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; -// r.direction = -r.direction; -// plane.Raycast(r, out forward); -// plane.Raycast(r, out backward); -// float rev = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; -// if (Mathf.Abs(rev) > Mathf.Abs(planeHit)) -// planeHit = rev; -// -// if (Mathf.Abs(planeHit) > Mathf.Epsilon) -// diff = mask * -planeHit; -// } -// else -// { -// diff = Vector3.Scale(obj.transform.TransformPoint(hit.point) - m_ElementHandleCachedPosition, mask.Abs()); -// } -// } -// } -// -// if (!m_IsMovingElements) -// { -// m_IsMovingElements = true; -// m_TranslateOrigin = m_ElementHandleCachedPosition; -// m_RotateOrigin = m_HandleRotation.eulerAngles; -// m_ScaleOrigin = m_HandleScale; -// -// OnBeginVertexMovement(); -// -// if (Event.current.modifiers == EventModifiers.Shift) -// ShiftExtrude(); -// -// ProGridsInterface.OnHandleMove(mask); -// } -// -// for (int i = 0; i < selection.Length; i++) -// { -// var mesh = selection[i]; -// -// mesh.TranslateVerticesInWorldSpace(mesh.selectedIndexesInternal, -// diff, -// m_SnapEnabled ? m_SnapValue : 0f, -// m_SnapAxisConstraint); -// -// mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); -// mesh.Refresh(RefreshMask.Normals); -// mesh.mesh.RecalculateBounds(); -// } -// -// UpdateMeshHandles(); -// } - } -} + class RotateTool : VertexManipulationTool + { + Quaternion m_Rotation; + + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) + { + if (!m_IsEditing) + m_Rotation = handleRotation; + + EditorGUI.BeginChangeCheck(); + m_Rotation = Handles.RotationHandle(m_Rotation, handlePosition); + if (EditorGUI.EndChangeCheck()) + { + if (!m_IsEditing) + BeginEdit(); + + Apply(Matrix4x4.Rotate(m_Rotation * handleRotationOriginInverse)); + } + } + } + + class ScaleTool : VertexManipulationTool + { + Vector3 m_Scale; + + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) + { + if (!m_IsEditing) + m_Scale = Vector3.one; + + EditorGUI.BeginChangeCheck(); + m_Scale = Handles.ScaleHandle(m_Scale, handlePosition, handleRotation, UnityEditor.HandleUtility.GetHandleSize(handlePosition)); + if (EditorGUI.EndChangeCheck()) + { + if (!m_IsEditing) + BeginEdit(); + Apply(Matrix4x4.Scale(m_Scale)); + } + } + } +} \ No newline at end of file diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index 1708f443d..32705902e 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -801,6 +801,8 @@ void DoubleClick(Event e) } static VertexManipulationTool s_MoveTool; + static VertexManipulationTool s_RotateTool; + static VertexManipulationTool m_ScaleTool; void VertexMoveTool() { @@ -906,6 +908,10 @@ void VertexMoveTool() void VertexScaleTool() { + if (m_ScaleTool == null) + m_ScaleTool = new ScaleTool(); + m_ScaleTool.OnSceneGUI(Event.current); + m_ElementHandlePosition = m_HandlePosition; m_HandleScalePrevious = m_HandleScale; @@ -1029,6 +1035,13 @@ void VertexScaleTool() void VertexRotateTool() { + if(s_RotateTool == null) + s_RotateTool = new RotateTool(); + + s_RotateTool.OnSceneGUI(Event.current); + + return; + if (!m_IsMovingElements) m_ElementHandlePosition = m_HandlePosition; From 19d0585b6a97f53c666660a0066976ac9c815c03 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Fri, 19 Oct 2018 13:48:31 -0400 Subject: [PATCH 04/27] move action implementations to their menu class instead of a monolith commands class --- .../EditorCore/EditorSceneViewPicker.cs | 9 ++- .../Editor/EditorCore/MenuCommands.cs | 60 +++++----------- .../Editor/EditorCore/ProBuilderEditor.cs | 3 +- .../Editor/EditorCore/UndoUtility.cs | 24 ++++++- .../Editor/MenuActions/Export/ExportAsset.cs | 2 +- .../Editor/MenuActions/Geometry/BevelEdges.cs | 6 +- .../MenuActions/Geometry/BridgeEdges.cs | 33 ++++++++- .../MenuActions/Geometry/CollapseVertices.cs | 8 +-- .../Geometry/ConformFaceNormals.cs | 28 +++++++- .../MenuActions/Geometry/ConnectEdges.cs | 28 ++++++-- .../MenuActions/Geometry/ConnectVertices.cs | 30 ++++++-- .../MenuActions/Geometry/DeleteFaces.cs | 32 ++++++++- .../MenuActions/Geometry/DetachFaces.cs | 26 +++---- .../MenuActions/Geometry/ExtrudeEdges.cs | 14 ++-- .../MenuActions/Geometry/ExtrudeFaces.cs | 14 ++-- .../Editor/MenuActions/Geometry/FillHole.cs | 9 +-- .../MenuActions/Geometry/FlipFaceEdge.cs | 31 +++++++- .../MenuActions/Geometry/FlipFaceNormals.cs | 36 +++++++++- .../MenuActions/Geometry/InsertEdgeLoop.cs | 28 +++++++- .../Editor/MenuActions/Geometry/MergeFaces.cs | 31 +++++++- .../Geometry/SetPivotToSelection.cs | 26 ++++++- .../MenuActions/Geometry/SmartConnect.cs | 4 +- .../MenuActions/Geometry/SplitVertices.cs | 71 +++++++++++++++++-- .../MenuActions/Geometry/SubdivideEdges.cs | 9 +-- .../MenuActions/Geometry/SubdivideFaces.cs | 39 ++++++++-- .../MenuActions/Geometry/TriangulateFaces.cs | 14 ++-- .../MenuActions/Geometry/WeldVertices.cs | 8 +-- .../Editor/MenuActions/Object/CenterPivot.cs | 26 ++++++- .../Object/ConformObjectNormals.cs | 17 ++++- .../MenuActions/Object/FlipObjectNormals.cs | 16 ++++- .../MenuActions/Object/FreezeTransform.cs | 36 +++++++++- .../Editor/MenuActions/Object/MergeObjects.cs | 31 +++++++- .../MenuActions/Object/SubdivideObject.cs | 28 ++++++-- .../MenuActions/Object/TriangulateObject.cs | 23 ++++-- .../MenuActions/Selection/GrowSelection.cs | 7 +- .../MenuActions/Selection/InvertSelection.cs | 23 +++--- .../MenuActions/Selection/SelectEdgeLoop.cs | 8 +-- .../MenuActions/Selection/SelectEdgeRing.cs | 14 ++-- .../MenuActions/Selection/SelectFaceLoop.cs | 2 +- .../MenuActions/Selection/SelectFaceRing.cs | 2 +- .../MenuActions/Selection/SelectHole.cs | 2 +- .../MenuActions/Selection/SelectMaterial.cs | 11 ++- .../Selection/SelectSmoothingGroup.cs | 2 +- .../Selection/SelectVertexColor.cs | 10 ++- .../MenuActions/Selection/ShrinkSelection.cs | 5 +- .../Runtime/MeshOperations/MeshTransform.cs | 4 +- 46 files changed, 681 insertions(+), 209 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/EditorSceneViewPicker.cs b/com.unity.probuilder/Editor/EditorCore/EditorSceneViewPicker.cs index ff64bb9ab..7d5649c26 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorSceneViewPicker.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorSceneViewPicker.cs @@ -246,8 +246,7 @@ public static void DoMouseDrag(Rect mouseDragRect, SelectMode selectionMode, Sce rectSelectMode = scenePickerPreferences.rectSelectMode }; - var selection = MeshSelection.topInternal; - UndoUtility.RecordSelection(selection, "Drag Select"); + UndoUtility.RecordSelection("Drag Select"); bool isAppendModifier = EditorHandleUtility.IsAppendModifier(Event.current.modifiers); if (!isAppendModifier) @@ -262,7 +261,7 @@ public static void DoMouseDrag(Rect mouseDragRect, SelectMode selectionMode, Sce Dictionary> selected = Picking.PickVerticesInRect( SceneView.lastActiveSceneView.camera, mouseDragRect, - selection, + MeshSelection.topInternal, pickingOptions, EditorGUIUtility.pixelsPerPoint); @@ -301,7 +300,7 @@ public static void DoMouseDrag(Rect mouseDragRect, SelectMode selectionMode, Sce Dictionary> selected = Picking.PickFacesInRect( SceneView.lastActiveSceneView.camera, mouseDragRect, - selection, + MeshSelection.topInternal, pickingOptions, EditorGUIUtility.pixelsPerPoint); @@ -337,7 +336,7 @@ public static void DoMouseDrag(Rect mouseDragRect, SelectMode selectionMode, Sce var selected = Picking.PickEdgesInRect( SceneView.lastActiveSceneView.camera, mouseDragRect, - selection, + MeshSelection.topInternal, pickingOptions, EditorGUIUtility.pixelsPerPoint); diff --git a/com.unity.probuilder/Editor/EditorCore/MenuCommands.cs b/com.unity.probuilder/Editor/EditorCore/MenuCommands.cs index a2529b436..e01471db1 100644 --- a/com.unity.probuilder/Editor/EditorCore/MenuCommands.cs +++ b/com.unity.probuilder/Editor/EditorCore/MenuCommands.cs @@ -21,6 +21,7 @@ sealed class MenuCommands : UnityEditor.Editor #region Object Level + [Obsolete] public static ActionResult MenuMergeObjects(ProBuilderMesh[] selected) { if(selected.Length < 2) @@ -55,11 +56,13 @@ public static ActionResult MenuMergeObjects(ProBuilderMesh[] selected) * Set the pivot to the center of the current element selection. * ProBuilder only. */ + [Obsolete] public static ActionResult MenuCenterPivot(ProBuilderMesh[] selection) { return SetPivotInternal(selection, null); } + [Obsolete] public static ActionResult MenuSetPivot(ProBuilderMesh[] selection) { int[][] tri = new int[selection.Length][]; @@ -104,6 +107,7 @@ static ActionResult SetPivotInternal(ProBuilderMesh[] selection, int[][] triangl return new ActionResult(ActionResult.Status.Success, "Set Pivot"); } + [Obsolete] public static ActionResult MenuFreezeTransforms(ProBuilderMesh[] selection) { if(selection == null || selection.Length < 1) @@ -274,6 +278,7 @@ public static ActionResult MenuIntersect(ProBuilderMesh lhs, ProBuilderMesh rhs) /** * Reverse the direction of all faces on each object. */ + [Obsolete] public static ActionResult MenuFlipObjectNormals(ProBuilderMesh[] selected) { if(selected == null || selected.Length < 1) @@ -296,6 +301,7 @@ public static ActionResult MenuFlipObjectNormals(ProBuilderMesh[] selected) /** * Flips all face normals if editLevel == EditLevel.Top, else flips only pb_Object->SelectedFaces */ + [Obsolete] public static ActionResult MenuFlipNormals(ProBuilderMesh[] selected) { if(selected == null || selected.Length < 1) @@ -334,51 +340,11 @@ public static ActionResult MenuFlipNormals(ProBuilderMesh[] selected) return new ActionResult(ActionResult.Status.Canceled, "Flip Normals\nNo Faces Selected"); } - - /** - * Attempt to make face normals uniform. - */ - public static ActionResult MenuConformObjectNormals(ProBuilderMesh[] selection) - { - return DoConformNormals(selection, false); - } - - public static ActionResult MenuConformNormals(ProBuilderMesh[] selection) - { - return DoConformNormals(selection, true); - } - - public static ActionResult DoConformNormals(ProBuilderMesh[] selection, bool perFace = true) - { - if(!editor || selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - UndoUtility.RecordSelection(selection, "Conform " + (MeshSelection.selectedFaceCount > 0 ? "Face" : "Object") + " Normals."); - - ActionResult res = ActionResult.NoSelection; - - foreach(ProBuilderMesh pb in selection) - { - Face[] faces = perFace ? pb.GetSelectedFaces() : pb.facesInternal; - - if(faces == null) - continue; - - res = UnityEngine.ProBuilder.MeshOperations.SurfaceTopology.ConformNormals(pb, faces); - - pb.ToMesh(); - pb.Refresh(); - pb.Optimize(); - } - - ProBuilderEditor.Refresh(); - - return res; - } #endregion #region Extrude / Bridge + [Obsolete] public static ActionResult MenuBridgeEdges(ProBuilderMesh[] selection) { if(selection == null || selection.Length < 1) @@ -427,6 +393,7 @@ public static ActionResult MenuBridgeEdges(ProBuilderMesh[] selection) * Delete selected faces. * ProBuilder only. */ + [Obsolete] public static ActionResult MenuDeleteFace(ProBuilderMesh[] selection) { if(selection == null || selection.Length < 1) @@ -472,6 +439,7 @@ public static ActionResult MenuDeleteFace(ProBuilderMesh[] selection) /** * Treat selected faces as a single face. */ + [Obsolete] public static ActionResult MenuMergeFaces(ProBuilderMesh[] selection) { if(selection == null || selection.Length < 1) @@ -509,6 +477,7 @@ public static ActionResult MenuMergeFaces(ProBuilderMesh[] selection) /** * Turn / flip / swap a quad connecting edge. */ + [Obsolete] public static ActionResult MenuFlipEdges(ProBuilderMesh[] selection) { if(selection == null || selection.Length < 1) @@ -538,8 +507,7 @@ public static ActionResult MenuFlipEdges(ProBuilderMesh[] selection) if(success > 0) return new ActionResult(ActionResult.Status.Success, "Flipped " + success + " Edges"); - else - return new ActionResult(ActionResult.Status.Failure, string.Format("Flip Edges\n{0}", attempts > 0 ? "Faces Must Be Quads" : "No Faces Selected")); + return new ActionResult(ActionResult.Status.Failure, string.Format("Flip Edges\n{0}", attempts > 0 ? "Faces Must Be Quads" : "No Faces Selected")); } #endregion @@ -547,6 +515,7 @@ public static ActionResult MenuFlipEdges(ProBuilderMesh[] selection) #if !PROTOTYPE + [Obsolete] public static ActionResult MenuSplitVertices(ProBuilderMesh[] selection) { if(selection == null || selection.Length < 1) @@ -628,6 +597,7 @@ public static ActionResult MenuSplitVertices(ProBuilderMesh[] selection) * center of the edge. Otherwise from Vertex. * ProBuilder only. */ + [Obsolete] public static ActionResult MenuSubdivide(ProBuilderMesh[] selection) { if(!editor || selection == null || selection.Length < 1) @@ -659,6 +629,7 @@ public static ActionResult MenuSubdivide(ProBuilderMesh[] selection) * Subdivides all currently selected faces. * ProBuilder only. */ + [Obsolete] public static ActionResult MenuSubdivideFace(ProBuilderMesh[] selection) { if(!editor || selection == null || selection.Length < 1) @@ -696,6 +667,7 @@ public static ActionResult MenuSubdivideFace(ProBuilderMesh[] selection) } } + [Obsolete] public static ActionResult MenuConnectEdges(ProBuilderMesh[] selection) { ActionResult res = ActionResult.NoSelection; @@ -725,6 +697,7 @@ public static ActionResult MenuConnectEdges(ProBuilderMesh[] selection) * Connects all currently selected vertices. * ProBuilder only. */ + [Obsolete] public static ActionResult MenuConnectVertices(ProBuilderMesh[] selection) { ActionResult res = ActionResult.NoSelection; @@ -757,6 +730,7 @@ public static ActionResult MenuConnectVertices(ProBuilderMesh[] selection) * Inserts an edge loop along currently selected Edges. * ProBuilder only. */ + [Obsolete] public static ActionResult MenuInsertEdgeLoop(ProBuilderMesh[] selection) { if(!editor || selection == null || selection.Length < 1) diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index 7565dc9bb..01f53f34c 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -1583,7 +1583,8 @@ internal void ToggleSelectionMode() void UpdateSelection(bool selectionChanged = true) { - selection = MeshSelection.topInternal; + // todo remove selection property + selection = MeshSelection.topInternal.ToArray(); m_HandlePosition = GetHandlePosition(); m_HandleRotation = GetHandleRotation(); diff --git a/com.unity.probuilder/Editor/EditorCore/UndoUtility.cs b/com.unity.probuilder/Editor/EditorCore/UndoUtility.cs index cb502059f..6228b7b2f 100644 --- a/com.unity.probuilder/Editor/EditorCore/UndoUtility.cs +++ b/com.unity.probuilder/Editor/EditorCore/UndoUtility.cs @@ -19,7 +19,7 @@ static void UndoRedoPerformed() if (SceneDragAndDropListener.isDragging) return; - foreach(var mesh in InternalUtility.GetComponents(Selection.transforms)) + foreach (var mesh in InternalUtility.GetComponents(Selection.transforms)) { mesh.InvalidateCaches(); mesh.ToMesh(); @@ -37,12 +37,32 @@ static void UndoRedoPerformed() */ public static void RecordSelection(ProBuilderMesh pb, string msg) { - if( pb.vertexCount > 256 ) + if (pb.vertexCount > 256) RegisterCompleteObjectUndo(pb, msg); else Undo.RecordObject(pb, msg); } + internal static void RecordSelection(string message) + { + RecordSelection(MeshSelection.topInternal.ToArray(), message); + } + + internal static void RecordMeshAndTransformSelection(string message) + { + var count = MeshSelection.selectedObjectCount; + var res = new Object [count]; + var selection = MeshSelection.topInternal; + + for (int i = 0, c = count; i < c; i++) + { + res[i] = selection[i]; + res[i+c] = selection[i].transform; + } + + Undo.RegisterCompleteObjectUndo(res, message); + } + /** * Tests if any pb_Object in the selection has more than 512 vertices, and if so records the entire object * instead of diffing the serialized object (which is very slow for large arrays). diff --git a/com.unity.probuilder/Editor/MenuActions/Export/ExportAsset.cs b/com.unity.probuilder/Editor/MenuActions/Export/ExportAsset.cs index 9d22e5c6a..8fa2e7373 100644 --- a/com.unity.probuilder/Editor/MenuActions/Export/ExportAsset.cs +++ b/com.unity.probuilder/Editor/MenuActions/Export/ExportAsset.cs @@ -25,7 +25,7 @@ sealed class ExportAsset : MenuAction public override bool enabled { - get { return MeshSelection.count > 0; } + get { return MeshSelection.selectedObjectCount > 0; } } public override bool hidden diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/BevelEdges.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/BevelEdges.cs index f3336b6a9..a675292bf 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/BevelEdges.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/BevelEdges.cs @@ -59,13 +59,11 @@ protected override void OnSettingsGUI() public override ActionResult DoAction() { - var selection = MeshSelection.topInternal; - ActionResult res = ActionResult.NoSelection; - UndoUtility.RecordSelection(selection, "Bevel Edges"); + UndoUtility.RecordSelection("Bevel Edges"); - foreach(ProBuilderMesh pb in selection) + foreach(ProBuilderMesh pb in MeshSelection.topInternal) { pb.ToMesh(); diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/BridgeEdges.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/BridgeEdges.cs index 565ac71a0..9b9dc1917 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/BridgeEdges.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/BridgeEdges.cs @@ -1,6 +1,7 @@ using UnityEngine; using System.Linq; using UnityEngine.ProBuilder; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder.Actions { @@ -40,7 +41,37 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuBridgeEdges(MeshSelection.topInternal); + if(MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + UndoUtility.RecordSelection("Bridge Edges"); + + bool success = false; + + foreach(var mesh in MeshSelection.topInternal) + { + if(mesh.selectedEdgeCount == 2) + { + if(mesh.Bridge(mesh.selectedEdges[0], mesh.selectedEdges[1], ProBuilderEditor.s_AllowNonManifoldActions) != null) + { + success = true; + mesh.ToMesh(); + mesh.Refresh(); + mesh.Optimize(); + } + } + } + + if(success) + { + ProBuilderEditor.Refresh(); + return new ActionResult(ActionResult.Status.Success, "Bridge Edges"); + } + else + { + Debug.LogWarning("Failed Bridge Edges. Bridge Edges requires that only 2 edges be selected, and they must both only have one connecting face (non-manifold)."); + return new ActionResult(ActionResult.Status.Failure, "Bridge Edges requires that only 2 edges be selected, and they must both only have one connecting face (non-manifold)."); + } } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/CollapseVertices.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/CollapseVertices.cs index 0dbb7ff51..1adc05b3e 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/CollapseVertices.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/CollapseVertices.cs @@ -72,18 +72,16 @@ protected override void OnSettingsGUI() public override ActionResult DoAction() { - var selection = MeshSelection.topInternal; - - if (selection == null || selection.Length < 1) + if (MeshSelection.selectedObjectCount < 1) return ActionResult.NoSelection; bool success = false; bool collapseToFirst = m_CollapseToFirst; - UndoUtility.RegisterCompleteObjectUndo(selection, "Collapse Vertices"); + UndoUtility.RecordSelection("Collapse Vertices"); - foreach (ProBuilderMesh mesh in selection) + foreach (var mesh in MeshSelection.topInternal) { if (mesh.selectedIndexesInternal.Length > 1) { diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/ConformFaceNormals.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/ConformFaceNormals.cs index 204aea4c8..e3207771b 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/ConformFaceNormals.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/ConformFaceNormals.cs @@ -11,10 +11,10 @@ sealed class ConformFaceNormals : MenuAction { public override ToolbarGroup group { get { return ToolbarGroup.Geometry; } } public override Texture2D icon { get { return IconUtility.GetIcon("Toolbar/Face_ConformNormals", IconSkin.Pro); } } - public override TooltipContent tooltip { get { return _tooltip; } } + public override TooltipContent tooltip { get { return s_TooltipContent; } } public override string menuTitle { get { return "Conform Normals"; } } - static readonly TooltipContent _tooltip = new TooltipContent + static readonly TooltipContent s_TooltipContent = new TooltipContent ( "Conform Face Normals", @"Orients all selected faces to face the same direction." @@ -32,7 +32,29 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuConformNormals(MeshSelection.topInternal); + var selection = MeshSelection.topInternal; + + UndoUtility.RecordSelection("Conform " + (MeshSelection.selectedFaceCount > 0 ? "Face" : "Object") + " Normals."); + + ActionResult res = ActionResult.NoSelection; + + foreach(ProBuilderMesh pb in selection) + { + var faces = pb.GetSelectedFaces(); + + if(faces == null) + continue; + + res = UnityEngine.ProBuilder.MeshOperations.SurfaceTopology.ConformNormals(pb, faces); + + pb.ToMesh(); + pb.Refresh(); + pb.Optimize(); + } + + ProBuilderEditor.Refresh(); + + return res; } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/ConnectEdges.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/ConnectEdges.cs index f61f688c5..48f4e53fe 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/ConnectEdges.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/ConnectEdges.cs @@ -1,9 +1,6 @@ using UnityEngine; -using UnityEditor; -using UnityEditor.ProBuilder.UI; -using System.Linq; using UnityEngine.ProBuilder; -using UnityEditor.ProBuilder; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder.Actions { @@ -33,7 +30,28 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuConnectEdges(MeshSelection.topInternal); + ActionResult res = ActionResult.NoSelection; + + UndoUtility.RecordSelection("Connect Edges"); + + foreach(var mesh in MeshSelection.topInternal) + { + Edge[] connections; + Face[] faces; + + res = ConnectElements.Connect(mesh, mesh.selectedEdges, out faces, out connections, true, true); + + if (connections != null) + { + mesh.SetSelectedEdges(connections); + mesh.Refresh(); + mesh.Optimize(); + } + } + + ProBuilderEditor.Refresh(); + return res; + } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/ConnectVertices.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/ConnectVertices.cs index 6c769cb36..889037e2f 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/ConnectVertices.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/ConnectVertices.cs @@ -1,9 +1,6 @@ using UnityEngine; -using UnityEditor; -using UnityEditor.ProBuilder.UI; -using System.Linq; using UnityEngine.ProBuilder; -using UnityEditor.ProBuilder; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder.Actions { @@ -33,7 +30,30 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuConnectVertices(MeshSelection.topInternal); + ActionResult res = ActionResult.NoSelection; + + UndoUtility.RecordSelection("Connect Vertices"); + + foreach(var mesh in MeshSelection.topInternal) + { + mesh.ToMesh(); + int[] splits = mesh.Connect(mesh.selectedIndexesInternal); + + if(splits != null) + { + mesh.Refresh(); + mesh.Optimize(); + mesh.SetSelectedVertices(splits); + res = new ActionResult(ActionResult.Status.Success, "Connect Edges"); + } + else + { + res = new ActionResult(ActionResult.Status.Failure, "Failed Connecting Edges"); + } + } + ProBuilderEditor.Refresh(); + + return res; } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/DeleteFaces.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/DeleteFaces.cs index 6cd41b4ca..f054dad68 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/DeleteFaces.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/DeleteFaces.cs @@ -1,5 +1,6 @@ using UnityEngine; using UnityEngine.ProBuilder; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder.Actions { @@ -39,7 +40,36 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuDeleteFace(MeshSelection.topInternal); + if(MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + UndoUtility.RecordSelection("Delete Face"); + + int count = 0; + + foreach(ProBuilderMesh pb in MeshSelection.topInternal) + { + if(pb.selectedFaceCount == pb.facesInternal.Length) + { + Debug.LogWarning("Attempting to delete all faces on this mesh... I'm afraid I can't let you do that."); + continue; + } + + pb.DeleteFaces(pb.selectedFacesInternal); + count += pb.selectedFaceCount; + + pb.ToMesh(); + pb.Refresh(); + pb.Optimize(); + } + + MeshSelection.ClearElementSelection(); + ProBuilderEditor.Refresh(); + + if(count > 0) + return new ActionResult(ActionResult.Status.Success, "Delete " + count + " Faces"); + + return new ActionResult(ActionResult.Status.Failure, "No Faces Selected"); } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/DetachFaces.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/DetachFaces.cs index f3ef9a39a..dbe5ad92c 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/DetachFaces.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/DetachFaces.cs @@ -62,22 +62,23 @@ protected override void OnSettingsGUI() public override ActionResult DoAction() { + if(MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + UndoUtility.RecordSelection("Detach Face(s)"); + if (m_DetachSetting == DetachSetting.GameObject) - return DetachFacesToObject(MeshSelection.topInternal); + return DetachFacesToObject(); - return DetachFacesToSubmesh(MeshSelection.topInternal); + return DetachFacesToSubmesh(); } - static ActionResult DetachFacesToSubmesh(ProBuilderMesh[] selection) + static ActionResult DetachFacesToSubmesh() { - if(selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - UndoUtility.RegisterCompleteObjectUndo(selection, "Detach Face(s)"); int count = 0; - foreach(ProBuilderMesh pb in selection) + foreach(ProBuilderMesh pb in MeshSelection.topInternal) { pb.ToMesh(); List res = pb.DetachFaces(pb.selectedFacesInternal); @@ -97,17 +98,12 @@ static ActionResult DetachFacesToSubmesh(ProBuilderMesh[] selection) return new ActionResult(ActionResult.Status.Success, "Detach Faces"); } - static ActionResult DetachFacesToObject(ProBuilderMesh[] selection) + static ActionResult DetachFacesToObject() { - if(selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - UndoUtility.RegisterCompleteObjectUndo(selection, "Detach Selection to GameObject"); - int detachedFaceCount = 0; List detached = new List(); - foreach(ProBuilderMesh mesh in selection) + foreach(ProBuilderMesh mesh in MeshSelection.topInternal) { if(mesh.selectedFaceCount < 1 || mesh.selectedFaceCount == mesh.facesInternal.Length) continue; diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeEdges.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeEdges.cs index 355f1535d..7c8e78c84 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeEdges.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeEdges.cs @@ -61,18 +61,15 @@ protected override void OnSettingsGUI() public override ActionResult DoAction() { - var editor = ProBuilderEditor.instance; - var selection = MeshSelection.topInternal; - - if(selection == null || selection.Length < 1) + if(MeshSelection.selectedObjectCount < 1) return ActionResult.NoSelection; - UndoUtility.RegisterCompleteObjectUndo(selection, "Extrude"); + UndoUtility.RecordSelection("Extrude"); int extrudedFaceCount = 0; bool success = false; - foreach(ProBuilderMesh pb in selection) + foreach(ProBuilderMesh pb in MeshSelection.topInternal) { pb.ToMesh(); pb.Refresh(RefreshMask.Normals); @@ -97,10 +94,7 @@ public override ActionResult DoAction() pb.Rebuild(); } - if(editor != null) - ProBuilderEditor.Refresh(); - - SceneView.RepaintAll(); + ProBuilderEditor.Refresh(); if( extrudedFaceCount > 0 ) return new ActionResult(ActionResult.Status.Success, "Extrude"); diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeFaces.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeFaces.cs index 258d1a831..df5a6cddc 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeFaces.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeFaces.cs @@ -107,17 +107,14 @@ protected override void OnSettingsGUI() public override ActionResult DoAction() { - var editor = ProBuilderEditor.instance; - var selection = MeshSelection.topInternal; - - if (selection == null || selection.Length < 1) + if(MeshSelection.selectedObjectCount < 1) return ActionResult.NoSelection; - UndoUtility.RegisterCompleteObjectUndo(selection, "Extrude"); + UndoUtility.RecordSelection("Extrude"); int extrudedFaceCount = 0; - foreach (ProBuilderMesh mesh in selection) + foreach (ProBuilderMesh mesh in MeshSelection.topInternal) { mesh.ToMesh(); mesh.Refresh(RefreshMask.Normals); @@ -138,10 +135,7 @@ public override ActionResult DoAction() mesh.Optimize(); } - if (editor != null) - ProBuilderEditor.Refresh(); - - SceneView.RepaintAll(); + ProBuilderEditor.Refresh(); if (extrudedFaceCount > 0) return new ActionResult(ActionResult.Status.Success, "Extrude"); diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/FillHole.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/FillHole.cs index 5af5b8a60..3d292f102 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/FillHole.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/FillHole.cs @@ -73,19 +73,16 @@ protected override void OnSettingsGUI() public override ActionResult DoAction() { - var editor = ProBuilderEditor.instance; - var selection = MeshSelection.topInternal; - - if(editor == null) + if (MeshSelection.selectedObjectCount < 1) return ActionResult.NoSelection; - UndoUtility.RecordSelection(selection, "Fill Hole"); + UndoUtility.RecordSelection("Fill Hole"); ActionResult res = new ActionResult(ActionResult.Status.NoChange, "No Holes Found"); int filled = 0; bool wholePath = m_SelectEntirePath; - foreach(ProBuilderMesh mesh in selection) + foreach(ProBuilderMesh mesh in MeshSelection.topInternal) { bool selectAll = mesh.selectedIndexesInternal == null || mesh.selectedIndexesInternal.Length < 1; IEnumerable indexes = selectAll ? mesh.facesInternal.SelectMany(x => x.indexes) : mesh.selectedIndexesInternal; diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/FlipFaceEdge.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/FlipFaceEdge.cs index 5d1e53572..c53be6331 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/FlipFaceEdge.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/FlipFaceEdge.cs @@ -1,5 +1,6 @@ using UnityEngine; using UnityEngine.ProBuilder; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder.Actions { @@ -38,7 +39,35 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuFlipEdges(MeshSelection.topInternal); + if(MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + UndoUtility.RecordSelection("Flip Face Edges"); + int success = 0; + int attempts = 0; + + foreach(ProBuilderMesh pb in MeshSelection.topInternal) + { + foreach(Face face in pb.selectedFacesInternal) + { + if( pb.FlipEdge(face) ) + success++; + } + + attempts++; + + pb.ToMesh(); + pb.Refresh(); + pb.Optimize(); + } + + ProBuilderEditor.Refresh(); + + if(success > 0) + return new ActionResult(ActionResult.Status.Success, "Flipped " + success + " Edges"); + + return new ActionResult(ActionResult.Status.Failure, string.Format("Flip Edges\n{0}", attempts > 0 ? "Faces Must Be Quads" : "No Faces Selected")); + } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/FlipFaceNormals.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/FlipFaceNormals.cs index 556a7bb60..ee0501a20 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/FlipFaceNormals.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/FlipFaceNormals.cs @@ -43,7 +43,41 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuFlipNormals(MeshSelection.topInternal); + if(MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + UndoUtility.RecordSelection("Flip Face Normals"); + + int c = 0; + int faceCount = MeshSelection.selectedFaceCount; + + foreach(ProBuilderMesh pb in MeshSelection.topInternal) + { + if( pb.selectedFaceCount < 1 && faceCount < 1 ) + { + foreach(var face in pb.facesInternal) + face.Reverse(); + + c += pb.facesInternal.Length; + } + else + { + foreach(var face in pb.GetSelectedFaces()) + face.Reverse(); + + c += pb.selectedFaceCount; + } + + + pb.ToMesh(); + pb.Refresh(); + pb.Optimize(); + } + + if(c > 0) + return new ActionResult(ActionResult.Status.Success, "Flip " + c + (c > 1 ? " Face Normals" : " Face Normal")); + + return new ActionResult(ActionResult.Status.Canceled, "Flip Normals\nNo Faces Selected"); } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/InsertEdgeLoop.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/InsertEdgeLoop.cs index a2a280704..038a2e96f 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/InsertEdgeLoop.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/InsertEdgeLoop.cs @@ -4,6 +4,7 @@ using System.Linq; using UnityEngine.ProBuilder; using UnityEditor.ProBuilder; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder.Actions { @@ -43,7 +44,32 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuInsertEdgeLoop(MeshSelection.topInternal); + if(MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + int success = 0; + UndoUtility.RecordSelection("Insert Edge Loop"); + + foreach(ProBuilderMesh pb in MeshSelection.topInternal) + { + Edge[] edges = pb.Connect(ElementSelection.GetEdgeRing(pb, pb.selectedEdges)).item2; + + if(edges != null) + { + pb.SetSelectedEdges(edges); + pb.ToMesh(); + pb.Refresh(); + pb.Optimize(); + success++; + } + } + + ProBuilderEditor.Refresh(); + + if(success > 0) + return new ActionResult(ActionResult.Status.Success, "Insert Edge Loop"); + + return new ActionResult(ActionResult.Status.Success, "Insert Edge Loop"); } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/MergeFaces.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/MergeFaces.cs index 0ef5ba042..1a607ff1f 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/MergeFaces.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/MergeFaces.cs @@ -1,6 +1,7 @@ using UnityEngine; using System.Linq; using UnityEngine.ProBuilder; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder.Actions { @@ -39,7 +40,35 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuMergeFaces(MeshSelection.topInternal); + if(MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + UndoUtility.RecordSelection("Merge Faces"); + + int success = 0; + + foreach(ProBuilderMesh pb in MeshSelection.topInternal) + { + if(pb.selectedFaceCount > 1) + { + success += pb.selectedFaceCount; + + Face face = MergeElements.Merge(pb, pb.selectedFacesInternal); + + pb.ToMesh(); + pb.Refresh(); + pb.Optimize(); + + pb.SetSelectedFaces( new Face[] { face } ); + } + } + + ProBuilderEditor.Refresh(); + + if(success > 0) + return new ActionResult(ActionResult.Status.Success, "Merged " + success + " Faces"); + + return new ActionResult(ActionResult.Status.Failure, "Merge Faces\nNo Faces Selected"); } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/SetPivotToSelection.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/SetPivotToSelection.cs index 21ca59775..b1eff99d4 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/SetPivotToSelection.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/SetPivotToSelection.cs @@ -4,6 +4,7 @@ using System.Linq; using UnityEngine.ProBuilder; using UnityEditor.ProBuilder; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder.Actions { @@ -38,7 +39,30 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuSetPivot(MeshSelection.topInternal); + if (MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + Object[] objects = new Object[MeshSelection.selectedObjectCount * 2]; + + for (int i = 0, c = MeshSelection.selectedObjectCount; i < c; i++) + { + objects[i] = MeshSelection.topInternal[i]; + objects[i + c] = MeshSelection.topInternal[i].transform; + } + + UndoUtility.RegisterCompleteObjectUndo(objects, "Set Pivot"); + + foreach(var mesh in MeshSelection.topInternal) + { + TransformUtility.UnparentChildren(mesh.transform); + mesh.CenterPivot(mesh.selectedIndexesInternal); + mesh.Optimize(); + TransformUtility.ReparentChildren(mesh.transform); + } + + ProBuilderEditor.Refresh(); + + return new ActionResult(ActionResult.Status.Success, "Set Pivot"); } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/SmartConnect.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/SmartConnect.cs index 5a62ba97e..5e939791a 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/SmartConnect.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/SmartConnect.cs @@ -45,10 +45,10 @@ public override ActionResult DoAction() switch (ProBuilderEditor.selectMode) { case SelectMode.Vertex: - return MenuCommands.MenuConnectVertices(MeshSelection.topInternal); + return EditorToolbarLoader.GetInstance().DoAction(); default: - return MenuCommands.MenuConnectEdges(MeshSelection.topInternal); + return EditorToolbarLoader.GetInstance().DoAction(); } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/SplitVertices.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/SplitVertices.cs index 68e0ceb16..47e18e067 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/SplitVertices.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/SplitVertices.cs @@ -1,9 +1,8 @@ +using System.Collections.Generic; using UnityEngine; -using UnityEditor; -using UnityEditor.ProBuilder.UI; using System.Linq; using UnityEngine.ProBuilder; -using UnityEditor.ProBuilder; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder.Actions { @@ -43,7 +42,71 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuSplitVertices(MeshSelection.topInternal); + if (MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + int splitCount = 0; + UndoUtility.RecordSelection("Split Vertices"); + + foreach(ProBuilderMesh mesh in MeshSelection.topInternal) + { + // loose verts to split + List tris = new List(mesh.selectedIndexesInternal); + + if (mesh.selectedFacesInternal.Length > 0) + { + int[] sharedVertexHandles = new int[mesh.selectedIndexesInternal.Length]; + + // Get shared index index for each vert in selection + for (int i = 0; i < mesh.selectedIndexesInternal.Length; i++) + sharedVertexHandles[i] = mesh.GetSharedVertexHandle(mesh.selectedIndexesInternal[i]); + + // cycle through selected faces and remove the tris that compose full faces. + foreach (Face face in mesh.selectedFacesInternal) + { + List faceSharedIndexes = new List(); + + for (int j = 0; j < face.distinctIndexesInternal.Length; j++) + faceSharedIndexes.Add(mesh.GetSharedVertexHandle(face.distinctIndexesInternal[j])); + + List usedTris = new List(); + for (int i = 0; i < sharedVertexHandles.Length; i++) + if (faceSharedIndexes.Contains(sharedVertexHandles[i])) + usedTris.Add(mesh.selectedIndexesInternal[i]); + + // This face *is* composed of selected tris. Remove these tris from the loose index list + foreach (int i in usedTris) + if (tris.Contains(i)) + tris.Remove(i); + } + } + + // Now split the faces, and any loose vertices + mesh.DetachFaces(mesh.selectedFacesInternal); + + splitCount += mesh.selectedIndexesInternal.Length; + mesh.SplitVertices(mesh.selectedIndexesInternal); + + // Reattach detached face vertices (if any are to be had) + if(mesh.selectedFacesInternal.Length > 0) + mesh.WeldVertices(mesh.selectedFacesInternal.SelectMany(x => x.indexes), Mathf.Epsilon); + + // And set the selected triangles to the newly split + List newTriSelection = new List(mesh.selectedFacesInternal.SelectMany(x => x.indexes)); + newTriSelection.AddRange(tris); + mesh.SetSelectedVertices(newTriSelection.ToArray()); + + mesh.ToMesh(); + mesh.Refresh(); + mesh.Optimize(); + } + + ProBuilderEditor.Refresh(); + + if(splitCount > 0) + return new ActionResult(ActionResult.Status.Success, "Split " + splitCount + (splitCount > 1 ? " Vertices" : " Vertex")); + else + return new ActionResult(ActionResult.Status.Failure, "Split Vertices\nInsuffient Vertices Selected"); } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/SubdivideEdges.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/SubdivideEdges.cs index ab2f2f42b..eecd08e93 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/SubdivideEdges.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/SubdivideEdges.cs @@ -72,19 +72,16 @@ protected override void OnSettingsGUI() public override ActionResult DoAction() { - var editor = ProBuilderEditor.instance; - var selection = MeshSelection.topInternal; - - if (!editor || selection == null || selection.Length < 1) + if (MeshSelection.selectedObjectCount < 1) return ActionResult.NoSelection; int subdivisions = m_SubdivisionCount; - UndoUtility.RegisterCompleteObjectUndo(selection, "Subdivide Edges"); + UndoUtility.RecordSelection("Subdivide Edges"); ActionResult result = ActionResult.NoSelection; - foreach (ProBuilderMesh pb in selection) + foreach (ProBuilderMesh pb in MeshSelection.topInternal) { List newEdgeSelection = AppendElements.AppendVerticesToEdge(pb, pb.selectedEdges, subdivisions); diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/SubdivideFaces.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/SubdivideFaces.cs index bbc45eea6..2e56ba0eb 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/SubdivideFaces.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/SubdivideFaces.cs @@ -1,9 +1,6 @@ using UnityEngine; -using UnityEditor; -using UnityEditor.ProBuilder.UI; -using System.Linq; using UnityEngine.ProBuilder; -using UnityEditor.ProBuilder; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder.Actions { @@ -48,7 +45,39 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuSubdivideFace(MeshSelection.topInternal); + if (MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + int success = 0; + UndoUtility.RecordSelection("Subdivide Faces"); + + foreach(ProBuilderMesh pb in MeshSelection.topInternal) + { + Face[] faces = pb.Subdivide(pb.selectedFacesInternal); + + pb.ToMesh(); + + if(faces != null) + { + success += pb.selectedFacesInternal.Length; + pb.SetSelectedFaces(faces); + + pb.Refresh(); + pb.Optimize(); + } + } + + if(success > 0) + { + ProBuilderEditor.Refresh(); + + return new ActionResult(ActionResult.Status.Success, "Subdivide " + success + ((success > 1) ? " faces" : " face")); + } + else + { + Debug.LogWarning("Subdivide faces failed - did you not have any faces selected?"); + return new ActionResult(ActionResult.Status.Failure, "Subdivide Faces\nNo faces selected"); + } } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/TriangulateFaces.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/TriangulateFaces.cs index 2489ff3ce..025cd3cab 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/TriangulateFaces.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/TriangulateFaces.cs @@ -42,15 +42,15 @@ public override ActionResult DoAction() { ActionResult res = ActionResult.NoSelection; - UndoUtility.RecordSelection(MeshSelection.topInternal, "Triangulate Faces"); + UndoUtility.RecordSelection("Triangulate Faces"); - foreach (ProBuilderMesh pb in MeshSelection.topInternal) + foreach (ProBuilderMesh mesh in MeshSelection.topInternal) { - pb.ToMesh(); - Face[] triangulatedFaces = pb.ToTriangles(pb.selectedFacesInternal); - pb.Refresh(); - pb.Optimize(); - pb.SetSelectedFaces(triangulatedFaces); + mesh.ToMesh(); + Face[] triangulatedFaces = mesh.ToTriangles(mesh.selectedFacesInternal); + mesh.Refresh(); + mesh.Optimize(); + mesh.SetSelectedFaces(triangulatedFaces); res = new ActionResult(ActionResult.Status.Success, string.Format("Triangulated {0} {1}", triangulatedFaces.Length, triangulatedFaces.Length < 2 ? "Face" : "Faces")); } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/WeldVertices.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/WeldVertices.cs index bcb00f01b..06be8d418 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/WeldVertices.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/WeldVertices.cs @@ -71,18 +71,16 @@ protected override void OnSettingsGUI() public override ActionResult DoAction() { - var selection = MeshSelection.topInternal; - - if(selection == null || selection.Length < 1) + if (MeshSelection.selectedObjectCount < 1) return ActionResult.NoSelection; ActionResult res = ActionResult.NoSelection; - UndoUtility.RegisterCompleteObjectUndo(selection, "Weld Vertices"); + UndoUtility.RecordSelection("Weld Vertices"); int weldCount = 0; - foreach(ProBuilderMesh mesh in selection) + foreach(ProBuilderMesh mesh in MeshSelection.topInternal) { weldCount += mesh.sharedVerticesInternal.Length; diff --git a/com.unity.probuilder/Editor/MenuActions/Object/CenterPivot.cs b/com.unity.probuilder/Editor/MenuActions/Object/CenterPivot.cs index cd873a2e0..c5d93c070 100644 --- a/com.unity.probuilder/Editor/MenuActions/Object/CenterPivot.cs +++ b/com.unity.probuilder/Editor/MenuActions/Object/CenterPivot.cs @@ -1,5 +1,6 @@ using UnityEngine.ProBuilder; using UnityEngine; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder.Actions { @@ -33,7 +34,30 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuCenterPivot(MeshSelection.topInternal); + if (MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + Object[] objects = new Object[MeshSelection.selectedObjectCount * 2]; + + for (int i = 0, c = MeshSelection.selectedObjectCount; i < c; i++) + { + objects[i] = MeshSelection.topInternal[i]; + objects[i + c] = MeshSelection.topInternal[i].transform; + } + + UndoUtility.RegisterCompleteObjectUndo(objects, "Center Pivot"); + + foreach(var mesh in MeshSelection.topInternal) + { + TransformUtility.UnparentChildren(mesh.transform); + mesh.CenterPivot(null); + mesh.Optimize(); + TransformUtility.ReparentChildren(mesh.transform); + } + + ProBuilderEditor.Refresh(); + + return new ActionResult(ActionResult.Status.Success, "Center Pivot"); } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Object/ConformObjectNormals.cs b/com.unity.probuilder/Editor/MenuActions/Object/ConformObjectNormals.cs index 67a521f04..3a3f47444 100644 --- a/com.unity.probuilder/Editor/MenuActions/Object/ConformObjectNormals.cs +++ b/com.unity.probuilder/Editor/MenuActions/Object/ConformObjectNormals.cs @@ -38,7 +38,22 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuConformObjectNormals(MeshSelection.topInternal); + UndoUtility.RecordSelection("Conform Object Normals"); + + ActionResult res = ActionResult.NoSelection; + + foreach(ProBuilderMesh pb in MeshSelection.topInternal) + { + res = UnityEngine.ProBuilder.MeshOperations.SurfaceTopology.ConformNormals(pb, pb.faces); + + pb.ToMesh(); + pb.Refresh(); + pb.Optimize(); + } + + ProBuilderEditor.Refresh(); + + return res; } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Object/FlipObjectNormals.cs b/com.unity.probuilder/Editor/MenuActions/Object/FlipObjectNormals.cs index d910d8b7e..168bdfedc 100644 --- a/com.unity.probuilder/Editor/MenuActions/Object/FlipObjectNormals.cs +++ b/com.unity.probuilder/Editor/MenuActions/Object/FlipObjectNormals.cs @@ -41,7 +41,21 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuFlipObjectNormals(MeshSelection.topInternal); + if (MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + UndoUtility.RecordSelection("Flip Object Normals"); + + foreach(ProBuilderMesh pb in MeshSelection.topInternal) + { + foreach(var face in pb.facesInternal) + face.Reverse(); + pb.ToMesh(); + pb.Refresh(); + pb.Optimize(); + } + + return new ActionResult(ActionResult.Status.Success, "Flip Object Normals"); } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Object/FreezeTransform.cs b/com.unity.probuilder/Editor/MenuActions/Object/FreezeTransform.cs index 2902defb0..0d1e97230 100644 --- a/com.unity.probuilder/Editor/MenuActions/Object/FreezeTransform.cs +++ b/com.unity.probuilder/Editor/MenuActions/Object/FreezeTransform.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using UnityEngine.ProBuilder; using UnityEditor.ProBuilder; using UnityEngine; @@ -36,7 +37,40 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuFreezeTransforms(MeshSelection.topInternal); + if (MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + UndoUtility.RecordMeshAndTransformSelection("Freeze Transforms"); + + var selection = MeshSelection.topInternal; + Vector3[][] positions = new Vector3[selection.Count][]; + + for(int i = 0, c = selection.Count; i < c; i++) + positions[i] = selection[i].VerticesInWorldSpace(); + + for(int i = 0, c = selection.Count; i < c; i++) + { + ProBuilderMesh pb = selection[i]; + + pb.transform.position = Vector3.zero; + pb.transform.rotation = Quaternion.identity; + pb.transform.localScale = Vector3.one; + + foreach(Face face in pb.facesInternal) + face.manualUV = true; + + pb.positions = positions[i]; + + pb.ToMesh(); + pb.Refresh(); + pb.Optimize(); + } + + ProBuilderEditor.Refresh(); + + SceneView.RepaintAll(); + + return new ActionResult(ActionResult.Status.Success, "Freeze Transforms"); } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Object/MergeObjects.cs b/com.unity.probuilder/Editor/MenuActions/Object/MergeObjects.cs index 874bc8072..434da166d 100644 --- a/com.unity.probuilder/Editor/MenuActions/Object/MergeObjects.cs +++ b/com.unity.probuilder/Editor/MenuActions/Object/MergeObjects.cs @@ -1,8 +1,11 @@ +using System.Collections.Generic; +using System.Linq; using UnityEngine.ProBuilder; using UnityEditor.ProBuilder; using UnityEngine; using UnityEditor; using UnityEditor.ProBuilder.UI; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder.Actions { @@ -36,7 +39,33 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuMergeObjects(MeshSelection.topInternal); + if(MeshSelection.selectedObjectCount < 2) + return new ActionResult(ActionResult.Status.Canceled, "Must Select 2+ Objects"); + + var selected = MeshSelection.top.ToArray(); + List res = InternalMeshUtility.CombineObjects(MeshSelection.topInternal); + + if (res != null) + { + foreach (var mesh in res) + { + mesh.Optimize(); + mesh.gameObject.name = "pb-MergedObject" + mesh.id; + UndoUtility.RegisterCreatedObjectUndo(mesh.gameObject, "Merge Objects"); + Selection.objects = res.Select(x => x.gameObject).ToArray(); + } + + // Delete donor objects + for(int i = 0; i < selected.Length; i++) + { + if(selected[i] != null) + UndoUtility.DestroyImmediate(selected[i].gameObject); + } + } + + ProBuilderEditor.Refresh(); + + return new ActionResult(ActionResult.Status.Success, "Merged Objects"); } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Object/SubdivideObject.cs b/com.unity.probuilder/Editor/MenuActions/Object/SubdivideObject.cs index 8f78d1b98..5e2adfb6c 100644 --- a/com.unity.probuilder/Editor/MenuActions/Object/SubdivideObject.cs +++ b/com.unity.probuilder/Editor/MenuActions/Object/SubdivideObject.cs @@ -1,8 +1,6 @@ using UnityEngine.ProBuilder; -using UnityEditor.ProBuilder; +using UnityEngine.ProBuilder.MeshOperations; using UnityEngine; -using UnityEditor; -using UnityEditor.ProBuilder.UI; namespace UnityEditor.ProBuilder.Actions { @@ -36,7 +34,29 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuSubdivide(MeshSelection.topInternal); + if(MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + UndoUtility.RecordSelection("Subdivide Selection"); + + int success = 0; + + foreach(ProBuilderMesh pb in MeshSelection.topInternal) + { + pb.ToMesh(); + + if( pb.Subdivide() ) + success++; + + pb.Refresh(); + pb.Optimize(); + + pb.SetSelectedVertices(new int[0]); + } + + ProBuilderEditor.Refresh(); + + return new ActionResult(ActionResult.Status.Success, "Subdivide " + success + " Objects"); } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Object/TriangulateObject.cs b/com.unity.probuilder/Editor/MenuActions/Object/TriangulateObject.cs index cadf8c1a7..0997644d6 100644 --- a/com.unity.probuilder/Editor/MenuActions/Object/TriangulateObject.cs +++ b/com.unity.probuilder/Editor/MenuActions/Object/TriangulateObject.cs @@ -1,8 +1,6 @@ using UnityEngine.ProBuilder; -using UnityEditor.ProBuilder; using UnityEngine; -using UnityEditor; -using UnityEditor.ProBuilder.UI; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder.Actions { @@ -26,7 +24,24 @@ public override bool enabled public override ActionResult DoAction() { - return MenuCommands.MenuTriangulateObject(MeshSelection.topInternal); + if(MeshSelection.selectedObjectCount < 1) + return ActionResult.NoSelection; + + UndoUtility.RecordSelection("Triangulate Objects"); + + foreach(var mesh in MeshSelection.topInternal) + { + mesh.ToMesh(); + mesh.ToTriangles(mesh.facesInternal); + mesh.Refresh(); + mesh.Optimize(); + mesh.ClearSelection(); + } + + ProBuilderEditor.Refresh(); + + var c = MeshSelection.selectedObjectCount; + return new ActionResult(ActionResult.Status.Success, "Triangulate " + c + (c > 1 ? " Objects" : " Object")); } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Selection/GrowSelection.cs b/com.unity.probuilder/Editor/MenuActions/Selection/GrowSelection.cs index 65e9f66a7..2b33c72d3 100644 --- a/com.unity.probuilder/Editor/MenuActions/Selection/GrowSelection.cs +++ b/com.unity.probuilder/Editor/MenuActions/Selection/GrowSelection.cs @@ -88,13 +88,10 @@ protected override void OnSettingsGUI() public override ActionResult DoAction() { - var selection = MeshSelection.topInternal; - var editor = ProBuilderEditor.instance; - - if(!ProBuilderEditor.instance || selection == null || selection.Length < 1) + if (MeshSelection.selectedObjectCount < 1) return ActionResult.NoSelection; - UndoUtility.RecordSelection(selection, "Grow Selection"); + UndoUtility.RecordSelection("Grow Selection"); int grown = 0; bool angleGrow = m_GrowSelectionWithAngle; diff --git a/com.unity.probuilder/Editor/MenuActions/Selection/InvertSelection.cs b/com.unity.probuilder/Editor/MenuActions/Selection/InvertSelection.cs index d75a33033..b1486885b 100644 --- a/com.unity.probuilder/Editor/MenuActions/Selection/InvertSelection.cs +++ b/com.unity.probuilder/Editor/MenuActions/Selection/InvertSelection.cs @@ -44,18 +44,15 @@ public override bool enabled public override ActionResult DoAction() { - var selection = MeshSelection.topInternal; - var editor = ProBuilderEditor.instance; - - if(selection == null || selection.Length < 1) + if(MeshSelection.selectedObjectCount < 1) return ActionResult.NoSelection; - UndoUtility.RecordSelection(selection, "Invert Selection"); + UndoUtility.RecordSelection("Invert Selection"); switch(ProBuilderEditor.selectMode) { case SelectMode.Vertex: - foreach(var mesh in selection) + foreach(var mesh in MeshSelection.topInternal) { SharedVertex[] sharedIndexes = mesh.sharedVerticesInternal; List selectedSharedIndexes = new List(); @@ -77,7 +74,7 @@ public override ActionResult DoAction() case SelectMode.Face: case SelectMode.TextureFace: - foreach(var mesh in selection) + foreach(var mesh in MeshSelection.topInternal) { IEnumerable inverse = mesh.facesInternal.Where( x => !mesh.selectedFacesInternal.Contains(x) ); mesh.SetSelectedFaces(inverse.ToArray()); @@ -86,19 +83,17 @@ public override ActionResult DoAction() case SelectMode.Edge: - if(!editor) break; - - for(int i = 0; i < selection.Length; i++) + foreach(var mesh in MeshSelection.topInternal) { - var universalEdges = selection[i].GetSharedVertexHandleEdges(selection[i].facesInternal.SelectMany(x => x.edges)).ToArray(); - var universal_selected_edges = EdgeExtension.GetSharedVertexHandleEdges(selection[i], selection[i].selectedEdges).Distinct(); + var universalEdges = mesh.GetSharedVertexHandleEdges(mesh.facesInternal.SelectMany(x => x.edges)).ToArray(); + var universal_selected_edges = EdgeExtension.GetSharedVertexHandleEdges(mesh, mesh.selectedEdges).Distinct(); Edge[] inverse_universal = System.Array.FindAll(universalEdges, x => !universal_selected_edges.Contains(x)); Edge[] inverse = new Edge[inverse_universal.Length]; for(int n = 0; n < inverse_universal.Length; n++) - inverse[n] = new Edge( selection[i].sharedVerticesInternal[inverse_universal[n].a][0], selection[i].sharedVerticesInternal[inverse_universal[n].b][0] ); + inverse[n] = new Edge( mesh.sharedVerticesInternal[inverse_universal[n].a][0], mesh.sharedVerticesInternal[inverse_universal[n].b][0] ); - selection[i].SetSelectedEdges(inverse); + mesh.SetSelectedEdges(inverse); } break; } diff --git a/com.unity.probuilder/Editor/MenuActions/Selection/SelectEdgeLoop.cs b/com.unity.probuilder/Editor/MenuActions/Selection/SelectEdgeLoop.cs index d6109face..9d89ea275 100644 --- a/com.unity.probuilder/Editor/MenuActions/Selection/SelectEdgeLoop.cs +++ b/com.unity.probuilder/Editor/MenuActions/Selection/SelectEdgeLoop.cs @@ -54,16 +54,14 @@ public override bool enabled public override ActionResult DoAction() { - var selection = MeshSelection.topInternal; - - if(selection == null || selection.Length < 1) + if(MeshSelection.selectedObjectCount < 1) return ActionResult.NoSelection; - UndoUtility.RecordSelection(selection, "Select Edge Loop"); + UndoUtility.RecordSelection("Select Edge Loop"); bool foundLoop = false; - foreach(ProBuilderMesh pb in selection) + foreach(ProBuilderMesh pb in MeshSelection.topInternal) { Edge[] loop; bool success = ElementSelection.GetEdgeLoop(pb, pb.selectedEdges, out loop); diff --git a/com.unity.probuilder/Editor/MenuActions/Selection/SelectEdgeRing.cs b/com.unity.probuilder/Editor/MenuActions/Selection/SelectEdgeRing.cs index 839a8727a..efcffc7ec 100644 --- a/com.unity.probuilder/Editor/MenuActions/Selection/SelectEdgeRing.cs +++ b/com.unity.probuilder/Editor/MenuActions/Selection/SelectEdgeRing.cs @@ -54,23 +54,21 @@ public override bool enabled public override ActionResult DoAction() { - var selection = MeshSelection.topInternal; - - if(selection == null || selection.Length < 1) + if(MeshSelection.selectedObjectCount < 1) return ActionResult.NoSelection; - UndoUtility.RecordSelection(selection, "Select Edge Ring"); + UndoUtility.RecordSelection("Select Edge Ring"); bool success = false; - foreach(ProBuilderMesh pb in InternalUtility.GetComponents(Selection.transforms)) + foreach(var mesh in MeshSelection.topInternal) { - Edge[] edges = ElementSelection.GetEdgeRing(pb, pb.selectedEdges).ToArray(); + Edge[] edges = ElementSelection.GetEdgeRing(mesh, mesh.selectedEdges).ToArray(); - if(edges.Length > pb.selectedEdgeCount) + if(edges.Length > mesh.selectedEdgeCount) success = true; - pb.SetSelectedEdges( edges ); + mesh.SetSelectedEdges( edges ); } ProBuilderEditor.Refresh(); diff --git a/com.unity.probuilder/Editor/MenuActions/Selection/SelectFaceLoop.cs b/com.unity.probuilder/Editor/MenuActions/Selection/SelectFaceLoop.cs index 4cf18e19f..42001b351 100644 --- a/com.unity.probuilder/Editor/MenuActions/Selection/SelectFaceLoop.cs +++ b/com.unity.probuilder/Editor/MenuActions/Selection/SelectFaceLoop.cs @@ -54,7 +54,7 @@ public override ActionResult DoAction() { var selection = MeshSelection.topInternal; - UndoUtility.RecordSelection(selection, "Select Face Loop"); + UndoUtility.RecordSelection("Select Face Loop"); foreach (ProBuilderMesh pb in selection) { diff --git a/com.unity.probuilder/Editor/MenuActions/Selection/SelectFaceRing.cs b/com.unity.probuilder/Editor/MenuActions/Selection/SelectFaceRing.cs index 538daea21..5464e2dec 100644 --- a/com.unity.probuilder/Editor/MenuActions/Selection/SelectFaceRing.cs +++ b/com.unity.probuilder/Editor/MenuActions/Selection/SelectFaceRing.cs @@ -52,7 +52,7 @@ public override ActionResult DoAction() { var selection = MeshSelection.topInternal; - UndoUtility.RecordSelection(selection, "Select Face Ring"); + UndoUtility.RecordSelection("Select Face Ring"); foreach (ProBuilderMesh pb in selection) { diff --git a/com.unity.probuilder/Editor/MenuActions/Selection/SelectHole.cs b/com.unity.probuilder/Editor/MenuActions/Selection/SelectHole.cs index befa68c32..afa1a99f4 100644 --- a/com.unity.probuilder/Editor/MenuActions/Selection/SelectHole.cs +++ b/com.unity.probuilder/Editor/MenuActions/Selection/SelectHole.cs @@ -44,7 +44,7 @@ public override bool enabled public override ActionResult DoAction() { - UndoUtility.RecordSelection(MeshSelection.topInternal, "Select Hole"); + UndoUtility.RecordSelection("Select Hole"); ActionResult res = ActionResult.NoSelection; diff --git a/com.unity.probuilder/Editor/MenuActions/Selection/SelectMaterial.cs b/com.unity.probuilder/Editor/MenuActions/Selection/SelectMaterial.cs index aef9bd82e..f025950f7 100644 --- a/com.unity.probuilder/Editor/MenuActions/Selection/SelectMaterial.cs +++ b/com.unity.probuilder/Editor/MenuActions/Selection/SelectMaterial.cs @@ -69,9 +69,14 @@ protected override void OnSettingsGUI() public override ActionResult DoAction() { - UndoUtility.RecordSelection(MeshSelection.topInternal, "Select Faces with Material"); + IEnumerable selection; - bool restrictToSelection = m_RestrictToSelectedObjects; + if (m_RestrictToSelectedObjects) + selection = MeshSelection.topInternal; + else + selection = Object.FindObjectsOfType(); + + UndoUtility.RecordSelection("Select Faces with Material"); HashSet sel = new HashSet( MeshSelection.topInternal @@ -79,7 +84,7 @@ public override ActionResult DoAction() List newSelection = new List(); - foreach (ProBuilderMesh pb in restrictToSelection ? MeshSelection.topInternal : Object.FindObjectsOfType()) + foreach (var pb in selection) { IEnumerable matches = pb.facesInternal.Where(x => sel.Contains(x.submeshIndex)); diff --git a/com.unity.probuilder/Editor/MenuActions/Selection/SelectSmoothingGroup.cs b/com.unity.probuilder/Editor/MenuActions/Selection/SelectSmoothingGroup.cs index 9f43ac478..c5fab8431 100644 --- a/com.unity.probuilder/Editor/MenuActions/Selection/SelectSmoothingGroup.cs +++ b/com.unity.probuilder/Editor/MenuActions/Selection/SelectSmoothingGroup.cs @@ -59,7 +59,7 @@ protected override MenuActionState optionsMenuState public override ActionResult DoAction() { - UndoUtility.RecordSelection(MeshSelection.topInternal, "Select Faces with Smoothing Group"); + UndoUtility.RecordSelection("Select Faces with Smoothing Group"); HashSet selectedSmoothGroups = new HashSet(MeshSelection.topInternal.SelectMany(x => x.selectedFacesInternal.Select(y => y.smoothingGroup))); diff --git a/com.unity.probuilder/Editor/MenuActions/Selection/SelectVertexColor.cs b/com.unity.probuilder/Editor/MenuActions/Selection/SelectVertexColor.cs index b5253f202..251993e1c 100644 --- a/com.unity.probuilder/Editor/MenuActions/Selection/SelectVertexColor.cs +++ b/com.unity.probuilder/Editor/MenuActions/Selection/SelectVertexColor.cs @@ -77,7 +77,7 @@ protected override void OnSettingsGUI() public override ActionResult DoAction() { - UndoUtility.RecordSelection(MeshSelection.topInternal, "Select Faces with Vertex Colors"); + UndoUtility.RecordSelection("Select Faces with Vertex Colors"); HashSet colors = new HashSet(); @@ -94,7 +94,13 @@ public override ActionResult DoAction() List newSelection = new List(); bool selectionOnly = m_SearchSelectedObjectsOnly; - ProBuilderMesh[] pool = selectionOnly ? MeshSelection.topInternal : Object.FindObjectsOfType(); + + IEnumerable pool; + + if (selectionOnly) + pool = MeshSelection.topInternal; + else + pool = Object.FindObjectsOfType(); foreach (ProBuilderMesh pb in pool) { diff --git a/com.unity.probuilder/Editor/MenuActions/Selection/ShrinkSelection.cs b/com.unity.probuilder/Editor/MenuActions/Selection/ShrinkSelection.cs index e06bbd37e..44eb4aa79 100644 --- a/com.unity.probuilder/Editor/MenuActions/Selection/ShrinkSelection.cs +++ b/com.unity.probuilder/Editor/MenuActions/Selection/ShrinkSelection.cs @@ -42,12 +42,13 @@ public override bool enabled public override ActionResult DoAction() { var selection = MeshSelection.topInternal; + var selectionCount = MeshSelection.selectedObjectCount; - UndoUtility.RecordSelection(selection, "Shrink Selection"); + UndoUtility.RecordSelection("Shrink Selection"); // find perimeter edges int rc = 0; - for(int i = 0; i < selection.Length; i++) + for(int i = 0; i < selectionCount; i++) { ProBuilderMesh mesh = selection[i]; diff --git a/com.unity.probuilder/Runtime/MeshOperations/MeshTransform.cs b/com.unity.probuilder/Runtime/MeshOperations/MeshTransform.cs index 0cbb9d5c9..ffc56aba0 100644 --- a/com.unity.probuilder/Runtime/MeshOperations/MeshTransform.cs +++ b/com.unity.probuilder/Runtime/MeshOperations/MeshTransform.cs @@ -47,8 +47,8 @@ public static void CenterPivot(this ProBuilderMesh mesh, int[] indexes) /// Set the pivot point of a mesh in world space. The Transform component position property is set to worldPosition, while the mesh geometry does not move. /// /// The target mesh. - /// The new transform position. - public static void CenterPivot(this ProBuilderMesh mesh, Vector3 worldPosition) + /// The new pivot position in world space. + public static void SetPivot(this ProBuilderMesh mesh, Vector3 worldPosition) { if (mesh == null) throw new System.ArgumentNullException("mesh"); From f5bfcb5dff3960ce807cf095fd84fd6dc791544a Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Fri, 19 Oct 2018 13:52:21 -0400 Subject: [PATCH 05/27] remove MenuCommands class --- .../Editor/EditorCore/BooleanEditor.cs | 80 +- .../Editor/EditorCore/MenuCommands.cs | 767 ------------------ .../Editor/EditorCore/MenuCommands.cs.meta | 11 - .../Editor/EditorCore/ProBuilderEditor.cs | 2 +- .../Editors/OpenVertexColorEditor.cs | 7 +- 5 files changed, 79 insertions(+), 788 deletions(-) delete mode 100644 com.unity.probuilder/Editor/EditorCore/MenuCommands.cs delete mode 100644 com.unity.probuilder/Editor/EditorCore/MenuCommands.cs.meta diff --git a/com.unity.probuilder/Editor/EditorCore/BooleanEditor.cs b/com.unity.probuilder/Editor/EditorCore/BooleanEditor.cs index 9e5c28bb9..dec6afaa9 100644 --- a/com.unity.probuilder/Editor/EditorCore/BooleanEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/BooleanEditor.cs @@ -1,5 +1,7 @@ using UnityEngine; using UnityEngine.ProBuilder; +using UnityEngine.ProBuilder.Experimental.CSG; +using UnityEngine.ProBuilder.MeshOperations; namespace UnityEditor.ProBuilder { @@ -155,15 +157,15 @@ void OnGUI() switch(operation) { case BooleanOp.Union: - MenuCommands.MenuUnion(m_LeftGameObject.GetComponent(), m_RightGameObject.GetComponent()); + MenuUnion(m_LeftGameObject.GetComponent(), m_RightGameObject.GetComponent()); break; case BooleanOp.Intersection: - MenuCommands.MenuIntersect(m_LeftGameObject.GetComponent(), m_RightGameObject.GetComponent()); + MenuIntersect(m_LeftGameObject.GetComponent(), m_RightGameObject.GetComponent()); break; case BooleanOp.Subtraction: - MenuCommands.MenuSubtract(m_LeftGameObject.GetComponent(), m_RightGameObject.GetComponent()); + MenuSubtract(m_LeftGameObject.GetComponent(), m_RightGameObject.GetComponent()); break; } } @@ -291,5 +293,77 @@ bool ListenForDragAndDrop() } return false; } + + enum BooleanOperation + { + Union, + Subtract, + Intersect + } + + static ActionResult MenuBooleanOperation(BooleanOperation operation, ProBuilderMesh lhs, ProBuilderMesh rhs) + { + if(lhs == null || rhs == null) + return new ActionResult(ActionResult.Status.Failure, "Must Select 2 Objects"); + + string op_string = operation == BooleanOperation.Union ? "Union" : (operation == BooleanOperation.Subtract ? "Subtract" : "Intersect"); + + ProBuilderMesh[] sel = new ProBuilderMesh[] { lhs, rhs }; + + UndoUtility.RecordSelection(sel, op_string); + + Mesh c; + + switch(operation) + { + case BooleanOperation.Union: + c = CSG.Union(lhs.gameObject, rhs.gameObject); + break; + + case BooleanOperation.Subtract: + c = CSG.Subtract(lhs.gameObject, rhs.gameObject); + break; + + default: + c = CSG.Intersect(lhs.gameObject, rhs.gameObject); + break; + } + + GameObject go = new GameObject(); + + go.AddComponent().sharedMaterial = EditorUtility.GetUserMaterial(); + go.AddComponent().sharedMesh = c; + + ProBuilderMesh pb = InternalMeshUtility.CreateMeshWithTransform(go.transform, false); + DestroyImmediate(go); + + Selection.objects = new Object[] { pb.gameObject }; + + return new ActionResult(ActionResult.Status.Success, op_string); + } + + /** + * Union operation between two ProBuilder objects. + */ + public static ActionResult MenuUnion(ProBuilderMesh lhs, ProBuilderMesh rhs) + { + return MenuBooleanOperation(BooleanOperation.Union, lhs, rhs); + } + + /** + * Subtract boolean operation between two pb_Objects. + */ + public static ActionResult MenuSubtract(ProBuilderMesh lhs, ProBuilderMesh rhs) + { + return MenuBooleanOperation(BooleanOperation.Subtract, lhs, rhs); + } + + /** + * Intersect boolean operation between two pb_Objects. + */ + public static ActionResult MenuIntersect(ProBuilderMesh lhs, ProBuilderMesh rhs) + { + return MenuBooleanOperation(BooleanOperation.Intersect, lhs, rhs); + } } } diff --git a/com.unity.probuilder/Editor/EditorCore/MenuCommands.cs b/com.unity.probuilder/Editor/EditorCore/MenuCommands.cs deleted file mode 100644 index e01471db1..000000000 --- a/com.unity.probuilder/Editor/EditorCore/MenuCommands.cs +++ /dev/null @@ -1,767 +0,0 @@ -using System; -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using System.Linq; -using UnityEngine.ProBuilder; -using UnityEngine.ProBuilder.MeshOperations; -using MeshOps = UnityEngine.ProBuilder.MeshOperations; -using Object = UnityEngine.Object; -using UnityEngine.ProBuilder.Experimental.CSG; - -namespace UnityEditor.ProBuilder -{ - /// - /// - /// Contains Menu commands for most ProBuilder operations. Will also attempt to Update the pb_Editor. - /// - sealed class MenuCommands : UnityEditor.Editor - { - static ProBuilderEditor editor { get { return ProBuilderEditor.instance; } } - -#region Object Level - - [Obsolete] - public static ActionResult MenuMergeObjects(ProBuilderMesh[] selected) - { - if(selected.Length < 2) - return new ActionResult(ActionResult.Status.Canceled, "Must Select 2+ Objects"); - - List res = InternalMeshUtility.CombineObjects(selected); - - if (res != null) - { - foreach (var mesh in res) - { - mesh.Optimize(); - mesh.gameObject.name = "pb-MergedObject" + mesh.id; - UndoUtility.RegisterCreatedObjectUndo(mesh.gameObject, "Merge Objects"); - Selection.objects = res.Select(x => x.gameObject).ToArray(); - } - - // Delete donor objects - for(int i = 0; i < selected.Length; i++) - { - if(selected[i] != null) - UndoUtility.DestroyImmediate(selected[i].gameObject); - } - } - - ProBuilderEditor.Refresh(); - - return new ActionResult(ActionResult.Status.Success, "Merged Objects"); - } - - /** - * Set the pivot to the center of the current element selection. - * ProBuilder only. - */ - [Obsolete] - public static ActionResult MenuCenterPivot(ProBuilderMesh[] selection) - { - return SetPivotInternal(selection, null); - } - - [Obsolete] - public static ActionResult MenuSetPivot(ProBuilderMesh[] selection) - { - int[][] tri = new int[selection.Length][]; - - for(int i = 0; i < tri.Length; i++) - tri[i] = selection[i].selectedVertices.ToArray(); - - return SetPivotInternal(selection, tri); - } - - static ActionResult SetPivotInternal(ProBuilderMesh[] selection, int[][] triangles = null) - { - if(selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - Object[] objects = new Object[selection.Length * 2]; - System.Array.Copy(selection, 0, objects, 0, selection.Length); - for(int i = selection.Length; i < objects.Length; i++) - objects[i] = selection[i-selection.Length].transform; - - UndoUtility.RegisterCompleteObjectUndo(objects, "Set Pivot"); - - for(int i = 0; i < selection.Length; i++) - { - TransformUtility.UnparentChildren(selection[i].transform); - - if(triangles != null) - selection[i].CenterPivot(triangles[i]); - else - selection[i].CenterPivot(null); - - selection[i].Optimize(); - - TransformUtility.ReparentChildren(selection[i].transform); - } - - SceneView.RepaintAll(); - - if(editor != null) - ProBuilderEditor.Refresh(); - - return new ActionResult(ActionResult.Status.Success, "Set Pivot"); - } - - [Obsolete] - public static ActionResult MenuFreezeTransforms(ProBuilderMesh[] selection) - { - if(selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - List undoables = new List( selection.Select(x => (Object) x.transform) ); - undoables.AddRange(selection); - UndoUtility.RecordObjects(undoables.ToArray(), "Freeze Transforms"); - - Vector3[][] positions = new Vector3[selection.Length][]; - - for(int i = 0; i < selection.Length; i++) - positions[i] = selection[i].VerticesInWorldSpace(); - - for(int i = 0; i < selection.Length; i++) - { - ProBuilderMesh pb = selection[i]; - - pb.transform.position = Vector3.zero; - pb.transform.rotation = Quaternion.identity; - pb.transform.localScale = Vector3.one; - - foreach(Face face in pb.facesInternal) - face.manualUV = true; - - pb.positions = positions[i]; - - pb.ToMesh(); - pb.Refresh(); - pb.Optimize(); - } - - ProBuilderEditor.Refresh(); - - SceneView.RepaintAll(); - - return new ActionResult(ActionResult.Status.Success, "Freeze Transforms"); - } - - /// - /// Set the pb_Entity entityType on selection. - /// - /// - /// - /// - [Obsolete("pb_Entity is obsolete.")] - public static ActionResult MenuSetEntityType(ProBuilderMesh[] selection, EntityType entityType) - { - if(selection.Length < 1) - return ActionResult.NoSelection; - - Object[] undoObjects = selection.SelectMany(x => x.GetComponents()).ToArray(); - - UndoUtility.RecordObjects(undoObjects, "Set Entity Type"); - - foreach(ProBuilderMesh pb in selection) - { - EntityUtility.SetEntityType(entityType, pb.gameObject); - pb.ToMesh(); - pb.Refresh(); - pb.Optimize(); - } - - return new ActionResult(ActionResult.Status.Success, "Set " + entityType); - } - - public static void MenuOpenVertexColorsEditor() - { - VertexColorPalette.MenuOpenWindow(); - } - - public static ActionResult MenuTriangulateObject(ProBuilderMesh[] selection) - { - if(!editor || selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - UndoUtility.RegisterCompleteObjectUndo(selection, "Triangulate Objects"); - - for(int i = 0; i < selection.Length; i++) - { - selection[i].ToMesh(); - selection[i].ToTriangles(selection[i].facesInternal); - selection[i].Refresh(); - selection[i].Optimize(); - selection[i].ClearSelection(); - } - - ProBuilderEditor.Refresh(); - - return new ActionResult(ActionResult.Status.Success, "Triangulate " + selection.Length + (selection.Length > 1 ? " Objects" : " Object")); - } - - enum BooleanOperation - { - Union, - Subtract, - Intersect - } - - static ActionResult MenuBooleanOperation(BooleanOperation operation, ProBuilderMesh lhs, ProBuilderMesh rhs) - { - if(lhs == null || rhs == null) - return new ActionResult(ActionResult.Status.Failure, "Must Select 2 Objects"); - - string op_string = operation == BooleanOperation.Union ? "Union" : (operation == BooleanOperation.Subtract ? "Subtract" : "Intersect"); - - ProBuilderMesh[] sel = new ProBuilderMesh[] { lhs, rhs }; - - UndoUtility.RecordSelection(sel, op_string); - - Mesh c; - - switch(operation) - { - case BooleanOperation.Union: - c = CSG.Union(lhs.gameObject, rhs.gameObject); - break; - - case BooleanOperation.Subtract: - c = CSG.Subtract(lhs.gameObject, rhs.gameObject); - break; - - default: - c = CSG.Intersect(lhs.gameObject, rhs.gameObject); - break; - } - - GameObject go = new GameObject(); - - go.AddComponent().sharedMaterial = EditorUtility.GetUserMaterial(); - go.AddComponent().sharedMesh = c; - - ProBuilderMesh pb = InternalMeshUtility.CreateMeshWithTransform(go.transform, false); - DestroyImmediate(go); - - Selection.objects = new Object[] { pb.gameObject }; - - return new ActionResult(ActionResult.Status.Success, op_string); - } - - /** - * Union operation between two ProBuilder objects. - */ - public static ActionResult MenuUnion(ProBuilderMesh lhs, ProBuilderMesh rhs) - { - return MenuBooleanOperation(BooleanOperation.Union, lhs, rhs); - } - - /** - * Subtract boolean operation between two pb_Objects. - */ - public static ActionResult MenuSubtract(ProBuilderMesh lhs, ProBuilderMesh rhs) - { - return MenuBooleanOperation(BooleanOperation.Subtract, lhs, rhs); - } - - /** - * Intersect boolean operation between two pb_Objects. - */ - public static ActionResult MenuIntersect(ProBuilderMesh lhs, ProBuilderMesh rhs) - { - return MenuBooleanOperation(BooleanOperation.Intersect, lhs, rhs); - } -#endregion - -#region Normals - - /** - * Reverse the direction of all faces on each object. - */ - [Obsolete] - public static ActionResult MenuFlipObjectNormals(ProBuilderMesh[] selected) - { - if(selected == null || selected.Length < 1) - return ActionResult.NoSelection; - - UndoUtility.RecordSelection(InternalUtility.GetComponents(Selection.transforms), "Flip Object Normals"); - - foreach(ProBuilderMesh pb in selected) - { - foreach(var face in pb.facesInternal) - face.Reverse(); - pb.ToMesh(); - pb.Refresh(); - pb.Optimize(); - } - - return new ActionResult(ActionResult.Status.Success, "Flip Object Normals"); - } - - /** - * Flips all face normals if editLevel == EditLevel.Top, else flips only pb_Object->SelectedFaces - */ - [Obsolete] - public static ActionResult MenuFlipNormals(ProBuilderMesh[] selected) - { - if(selected == null || selected.Length < 1) - return ActionResult.NoSelection; - - UndoUtility.RecordSelection(InternalUtility.GetComponents(Selection.transforms), "Flip Face Normals"); - - int c = 0; - int faceCount = MeshSelection.selectedFaceCount; - - foreach(ProBuilderMesh pb in InternalUtility.GetComponents(Selection.transforms)) - { - if( pb.selectedFaceCount < 1 && faceCount < 1 ) - { - foreach(var face in pb.facesInternal) - face.Reverse(); - - c += pb.facesInternal.Length; - } - else - { - foreach(var face in pb.GetSelectedFaces()) - face.Reverse(); - - c += pb.selectedFaceCount; - } - - - pb.ToMesh(); - pb.Refresh(); - pb.Optimize(); - } - - if(c > 0) - return new ActionResult(ActionResult.Status.Success, "Flip " + c + (c > 1 ? " Face Normals" : " Face Normal")); - - return new ActionResult(ActionResult.Status.Canceled, "Flip Normals\nNo Faces Selected"); - } -#endregion - -#region Extrude / Bridge - - [Obsolete] - public static ActionResult MenuBridgeEdges(ProBuilderMesh[] selection) - { - if(selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - UndoUtility.RecordSelection(selection, "Bridge Edges"); - - bool success = false; - - foreach(ProBuilderMesh pb in selection) - { - if(pb.selectedEdgeCount == 2) - { - if(pb.Bridge(pb.selectedEdges[0], pb.selectedEdges[1], ProBuilderEditor.s_AllowNonManifoldActions) != null) - { - success = true; - pb.ToMesh(); - pb.Refresh(); - pb.Optimize(); - } - } - } - - if(success) - { - ProBuilderEditor.Refresh(); - return new ActionResult(ActionResult.Status.Success, "Bridge Edges"); - } - else - { - Debug.LogWarning("Failed Bridge Edges. Bridge Edges requires that only 2 edges be selected, and they must both only have one connecting face (non-manifold)."); - return new ActionResult(ActionResult.Status.Failure, "Bridge Edges requires that only 2 edges be selected, and they must both only have one connecting face (non-manifold)."); - } - } - -#endregion - -#region Selection - - -#endregion - -#region Delete / Detach - - /** - * Delete selected faces. - * ProBuilder only. - */ - [Obsolete] - public static ActionResult MenuDeleteFace(ProBuilderMesh[] selection) - { - if(selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - UndoUtility.RegisterCompleteObjectUndo(selection, "Delete Face"); - - int count = 0; - - foreach(ProBuilderMesh pb in selection) - { - if(pb.selectedFaceCount == pb.facesInternal.Length) - { - Debug.LogWarning("Attempting to delete all faces on this mesh... I'm afraid I can't let you do that."); - continue; - } - - pb.DeleteFaces(pb.selectedFacesInternal); - count += pb.selectedFaceCount; - - pb.ToMesh(); - pb.Refresh(); - pb.Optimize(); - } - - if(editor) - { - editor.ClearElementSelection(); - ProBuilderEditor.Refresh(); - } - - if(count > 0) - return new ActionResult(ActionResult.Status.Success, "Delete " + count + " Faces"); - else - return new ActionResult(ActionResult.Status.Failure, "No Faces Selected"); - } - - -#endregion - -#region Face / Triangles - - /** - * Treat selected faces as a single face. - */ - [Obsolete] - public static ActionResult MenuMergeFaces(ProBuilderMesh[] selection) - { - if(selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - UndoUtility.RecordObjects(selection, "Merge Faces"); - - int success = 0; - - foreach(ProBuilderMesh pb in selection) - { - if(pb.selectedFaceCount > 1) - { - success += pb.selectedFaceCount; - - Face face = MergeElements.Merge(pb, pb.selectedFacesInternal); - - pb.ToMesh(); - pb.Refresh(); - pb.Optimize(); - - pb.SetSelectedFaces( new Face[] { face } ); - } - } - - if(editor) - ProBuilderEditor.Refresh(); - - if(success > 0) - return new ActionResult(ActionResult.Status.Success, "Merged " + success + " Faces"); - else - return new ActionResult(ActionResult.Status.Failure, "Merge Faces\nNo Faces Selected"); - } - - /** - * Turn / flip / swap a quad connecting edge. - */ - [Obsolete] - public static ActionResult MenuFlipEdges(ProBuilderMesh[] selection) - { - if(selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - UndoUtility.RecordSelection(selection, "Flip Face Edges"); - int success = 0; - int attempts = 0; - - foreach(ProBuilderMesh pb in selection) - { - foreach(Face face in pb.selectedFacesInternal) - { - if( pb.FlipEdge(face) ) - success++; - } - - attempts++; - - pb.ToMesh(); - pb.Refresh(); - pb.Optimize(); - } - - if(editor) - ProBuilderEditor.Refresh(); - - if(success > 0) - return new ActionResult(ActionResult.Status.Success, "Flipped " + success + " Edges"); - return new ActionResult(ActionResult.Status.Failure, string.Format("Flip Edges\n{0}", attempts > 0 ? "Faces Must Be Quads" : "No Faces Selected")); - } -#endregion - -#region Vertex Operations - -#if !PROTOTYPE - - [Obsolete] - public static ActionResult MenuSplitVertices(ProBuilderMesh[] selection) - { - if(selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - int splitCount = 0; - UndoUtility.RecordSelection(selection, "Split Vertices"); - - foreach(ProBuilderMesh mesh in selection) - { - // loose verts to split - List tris = new List(mesh.selectedIndexesInternal); - - if (mesh.selectedFacesInternal.Length > 0) - { - int[] sharedVertexHandles = new int[mesh.selectedIndexesInternal.Length]; - - // Get shared index index for each vert in selection - for (int i = 0; i < mesh.selectedIndexesInternal.Length; i++) - sharedVertexHandles[i] = mesh.GetSharedVertexHandle(mesh.selectedIndexesInternal[i]); - - // cycle through selected faces and remove the tris that compose full faces. - foreach (Face face in mesh.selectedFacesInternal) - { - List faceSharedIndexes = new List(); - - for (int j = 0; j < face.distinctIndexesInternal.Length; j++) - faceSharedIndexes.Add(mesh.GetSharedVertexHandle(face.distinctIndexesInternal[j])); - - List usedTris = new List(); - for (int i = 0; i < sharedVertexHandles.Length; i++) - if (faceSharedIndexes.Contains(sharedVertexHandles[i])) - usedTris.Add(mesh.selectedIndexesInternal[i]); - - // This face *is* composed of selected tris. Remove these tris from the loose index list - foreach (int i in usedTris) - if (tris.Contains(i)) - tris.Remove(i); - } - } - - // Now split the faces, and any loose vertices - mesh.DetachFaces(mesh.selectedFacesInternal); - - splitCount += mesh.selectedIndexesInternal.Length; - mesh.SplitVertices(mesh.selectedIndexesInternal); - - // Reattach detached face vertices (if any are to be had) - if(mesh.selectedFacesInternal.Length > 0) - mesh.WeldVertices(mesh.selectedFacesInternal.SelectMany(x => x.indexes), Mathf.Epsilon); - - // And set the selected triangles to the newly split - List newTriSelection = new List(mesh.selectedFacesInternal.SelectMany(x => x.indexes)); - newTriSelection.AddRange(tris); - mesh.SetSelectedVertices(newTriSelection.ToArray()); - - mesh.ToMesh(); - mesh.Refresh(); - mesh.Optimize(); - } - - ProBuilderEditor.Refresh(); - - if(splitCount > 0) - return new ActionResult(ActionResult.Status.Success, "Split " + splitCount + (splitCount > 1 ? " Vertices" : " Vertex")); - else - return new ActionResult(ActionResult.Status.Failure, "Split Vertices\nInsuffient Vertices Selected"); - } - -#endif -#endregion - -#region Subdivide / Split - -#if !PROTOTYPE - - /** - * Attempts to subdivide the selected objects. If Edge or Face selection mode, splits at the - * center of the edge. Otherwise from Vertex. - * ProBuilder only. - */ - [Obsolete] - public static ActionResult MenuSubdivide(ProBuilderMesh[] selection) - { - if(!editor || selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - UndoUtility.RegisterCompleteObjectUndo(selection, "Subdivide Selection"); - - int success = 0; - - foreach(ProBuilderMesh pb in selection) - { - pb.ToMesh(); - - if( pb.Subdivide() ) - success++; - - pb.Refresh(); - pb.Optimize(); - - pb.SetSelectedVertices(new int[0]); - } - - ProBuilderEditor.Refresh(); - - return new ActionResult(ActionResult.Status.Success, "Subdivide " + selection.Length + " Objects"); - } - - /** - * Subdivides all currently selected faces. - * ProBuilder only. - */ - [Obsolete] - public static ActionResult MenuSubdivideFace(ProBuilderMesh[] selection) - { - if(!editor || selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - int success = 0; - - foreach(ProBuilderMesh pb in selection) - { - UndoUtility.RegisterCompleteObjectUndo(selection, "Subdivide Faces"); - - Face[] faces = pb.Subdivide(pb.selectedFacesInternal); - pb.ToMesh(); - - if(faces != null) - { - success += pb.selectedFacesInternal.Length; - pb.SetSelectedFaces(faces); - - pb.Refresh(); - pb.Optimize(); - } - } - - if(success > 0) - { - ProBuilderEditor.Refresh(); - - return new ActionResult(ActionResult.Status.Success, "Subdivide " + success + ((success > 1) ? " faces" : " face")); - } - else - { - Debug.LogWarning("Subdivide faces failed - did you not have any faces selected?"); - return new ActionResult(ActionResult.Status.Failure, "Subdivide Faces\nNo faces selected"); - } - } - - [Obsolete] - public static ActionResult MenuConnectEdges(ProBuilderMesh[] selection) - { - ActionResult res = ActionResult.NoSelection; - - UndoUtility.RegisterCompleteObjectUndo(selection, "Connect Edges"); - - foreach(ProBuilderMesh pb in selection) - { - Edge[] connections; - Face[] faces; - - res = ConnectElements.Connect(pb, pb.selectedEdges, out faces, out connections, true, true); - - if (connections != null) - { - pb.SetSelectedEdges(connections); - pb.Refresh(); - pb.Optimize(); - } - } - - ProBuilderEditor.Refresh(); - return res; - } - - /** - * Connects all currently selected vertices. - * ProBuilder only. - */ - [Obsolete] - public static ActionResult MenuConnectVertices(ProBuilderMesh[] selection) - { - ActionResult res = ActionResult.NoSelection; - - UndoUtility.RegisterCompleteObjectUndo(selection, "Connect Vertices"); - - foreach(ProBuilderMesh pb in selection) - { - pb.ToMesh(); - int[] splits = pb.Connect(pb.selectedIndexesInternal); - - if(splits != null) - { - pb.Refresh(); - pb.Optimize(); - pb.SetSelectedVertices(splits); - res = new ActionResult(ActionResult.Status.Success, "Connect Edges"); - } - else - { - res = new ActionResult(ActionResult.Status.Failure, "Failed Connecting Edges"); - } - } - ProBuilderEditor.Refresh(); - - return res; - } - - /** - * Inserts an edge loop along currently selected Edges. - * ProBuilder only. - */ - [Obsolete] - public static ActionResult MenuInsertEdgeLoop(ProBuilderMesh[] selection) - { - if(!editor || selection == null || selection.Length < 1) - return ActionResult.NoSelection; - - int success = 0; - UndoUtility.RegisterCompleteObjectUndo(selection, "Insert Edge Loop"); - - foreach(ProBuilderMesh pb in selection) - { - Edge[] edges = pb.Connect(ElementSelection.GetEdgeRing(pb, pb.selectedEdges)).item2; - - if(edges != null) - { - pb.SetSelectedEdges(edges); - pb.ToMesh(); - pb.Refresh(); - pb.Optimize(); - success++; - } - } - - ProBuilderEditor.Refresh(); - - if(success > 0) - return new ActionResult(ActionResult.Status.Success, "Insert Edge Loop"); - else - return new ActionResult(ActionResult.Status.Success, "Insert Edge Loop"); - } - -#endif -#endregion - } -} diff --git a/com.unity.probuilder/Editor/EditorCore/MenuCommands.cs.meta b/com.unity.probuilder/Editor/EditorCore/MenuCommands.cs.meta deleted file mode 100644 index 50995fd15..000000000 --- a/com.unity.probuilder/Editor/EditorCore/MenuCommands.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9d08e2d1f66b00d499490c18fffd5393 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index 01f53f34c..7a5885305 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -1499,7 +1499,7 @@ bool GeoLevelShortcuts(Shortcut shortcut) return true; case "Delete Face": - EditorUtility.ShowNotification(MenuCommands.MenuDeleteFace(selection).notification); + EditorUtility.ShowNotification(EditorToolbarLoader.GetInstance().DoAction().notification); return true; /* handle alignment */ diff --git a/com.unity.probuilder/Editor/MenuActions/Editors/OpenVertexColorEditor.cs b/com.unity.probuilder/Editor/MenuActions/Editors/OpenVertexColorEditor.cs index 16f7fa331..b163953aa 100644 --- a/com.unity.probuilder/Editor/MenuActions/Editors/OpenVertexColorEditor.cs +++ b/com.unity.probuilder/Editor/MenuActions/Editors/OpenVertexColorEditor.cs @@ -1,10 +1,5 @@ using UnityEngine.ProBuilder; -using UnityEditor.ProBuilder; using UnityEngine; -using UnityEditor; -using UnityEditor.ProBuilder.UI; -using EditorGUILayout = UnityEditor.EditorGUILayout; -using EditorStyles = UnityEditor.EditorStyles; namespace UnityEditor.ProBuilder.Actions { @@ -28,7 +23,7 @@ public override bool enabled public override ActionResult DoAction() { - MenuCommands.MenuOpenVertexColorsEditor(); + VertexColorPalette.MenuOpenWindow(); return new ActionResult(ActionResult.Status.Success, "Open Vertex Color Window"); } } From 59fd1fa7757fbb8faf5beba269cb15b47b548fe4 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Fri, 19 Oct 2018 14:08:46 -0400 Subject: [PATCH 06/27] include missing reference --- com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index 7a5885305..51dba4aa3 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Reflection; using System.Collections.Generic; +using UnityEditor.ProBuilder.Actions; using UnityEngine.ProBuilder; using PMesh = UnityEngine.ProBuilder.ProBuilderMesh; using UnityEngine.ProBuilder.MeshOperations; From 3b87eed18f90d4fb75c6aaca8beef038b1f289be Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Fri, 19 Oct 2018 14:12:02 -0400 Subject: [PATCH 07/27] change internal storage of mesh selection to list --- .../Editor/EditorCore/MeshSelection.cs | 62 +++++++++++++------ 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs index 06ef0ea03..db0d40853 100644 --- a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs +++ b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs @@ -14,7 +14,7 @@ namespace UnityEditor.ProBuilder [InitializeOnLoad] public static class MeshSelection { - static ProBuilderMesh[] s_TopSelection = new ProBuilderMesh[0]; + static List s_TopSelection = new List(); static bool s_ElementCountCacheIsDirty = true; @@ -32,7 +32,11 @@ public static Bounds bounds static int s_TotalVertexCountCompiled; static int s_TotalTriangleCountCompiled; - internal static int selectedObjectCount { get; private set; } + /// + /// How many ProBuilderMesh components are currently selected. Corresponds to the length of Top. + /// + public static int selectedObjectCount { get; private set; } + internal static int selectedVertexCount { get; private set; } internal static int selectedSharedVertexCount { get; private set; } internal static int selectedFaceCount { get; private set; } @@ -69,6 +73,14 @@ static MeshSelection() OnObjectSelectionChanged(); } + /// + /// Returns the active selected mesh. + /// + public static ProBuilderMesh activeMesh + { + get { return selectedObjectCount > 0 ? s_TopSelection[selectedObjectCount - 1] : null; } + } + /// /// Receive notifications when the object selection changes. /// @@ -78,9 +90,20 @@ internal static void OnObjectSelectionChanged() { // GameObjects returns both parent and child when both are selected, where transforms only returns the top-most // transform. - s_TopSelection = Selection.gameObjects.Select(x => x.GetComponent()).Where(x => x != null).ToArray(); + s_TopSelection.Clear(); + + var gameObjects = Selection.gameObjects; + + for (int i = 0, c = gameObjects.Length; i < c; i++) + { + var mesh = gameObjects[i].GetComponent(); + + if (mesh != null) + s_TopSelection.Add(mesh); + } + + selectedObjectCount = s_TopSelection.Count; - selectedObjectCount = s_TopSelection.Length; s_ElementCountCacheIsDirty = true; if (objectSelectionChanged != null) @@ -169,7 +192,7 @@ public static IEnumerable top get { return new ReadOnlyCollection(s_TopSelection); } } - internal static ProBuilderMesh[] topInternal + internal static List topInternal { get { return s_TopSelection; } } @@ -188,14 +211,6 @@ internal static bool Contains(ProBuilderMesh mesh) return s_TopSelection.Contains(mesh); } - /// - /// How many ProBuilderMesh components are currently selected. Corresponds to the length of Top. - /// - public static int count - { - get { return topInternal.Length; } - } - /// /// Get the number of all selected vertices across the selected ProBuilder meshes. /// @@ -252,10 +267,16 @@ internal static void AddToSelection(GameObject t) { if(t == null || Selection.objects.Contains(t)) return; - Object[] temp = new Object[Selection.objects.Length + 1]; - temp[0] = t; - for(int i = 1; i < temp.Length; i++) - temp[i] = Selection.objects[i-1]; + + int len = Selection.objects.Length; + + Object[] temp = new Object[len + 1]; + + for(int i = 0; i < len; i++) + temp[i] = Selection.objects[i]; + + temp[len] = t; + Selection.objects = temp; } @@ -284,8 +305,11 @@ internal static void SetSelection(IList newSelection) if(Tools.current == Tool.None) Tools.current = Tool.Move; - if(newSelection != null && newSelection.Count > 0) { - Selection.activeTransform = newSelection[0].transform; + var newCount = newSelection != null ? newSelection.Count : 0; + + if(newCount > 0) + { + Selection.activeTransform = newSelection[newCount - 1].transform; Selection.objects = newSelection.ToArray(); } else From 33f53bf59aa7100241d6394fdb7d29aec8c1b134 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Fri, 19 Oct 2018 16:22:50 -0400 Subject: [PATCH 08/27] show a gizmo with the object orientation when moving handles in pivot mode --- .../Content/Shader/LineBillboard.shader | 3 +- .../Editor/EditorCore/EditorMeshHandles.cs | 43 +++- .../Editor/EditorCore/MeshSelection.cs | 12 +- .../Editor/EditorCore/MoveTool.cs | 212 ++++++++---------- .../Editor/EditorCore/ProBuilderEditor.cs | 2 + 5 files changed, 151 insertions(+), 121 deletions(-) diff --git a/com.unity.probuilder/Content/Shader/LineBillboard.shader b/com.unity.probuilder/Content/Shader/LineBillboard.shader index 3c62e3bae..ca04b06ef 100644 --- a/com.unity.probuilder/Content/Shader/LineBillboard.shader +++ b/com.unity.probuilder/Content/Shader/LineBillboard.shader @@ -4,6 +4,7 @@ { _Color ("Color", Color) = (1,1,1,1) _Scale ("Scale", Range(0, 20)) = 7 + _HandleZTest ("_HandleZTest", Int) = 8 } SubShader @@ -19,7 +20,7 @@ } Lighting Off - ZTest LEqual + ZTest [_HandleZTest] ZWrite On Cull Off Blend Off diff --git a/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs b/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs index c182265d8..5d2bc5c3a 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs @@ -13,6 +13,7 @@ class EditorMeshHandles : IDisposable, IHasPreferences { const HideFlags k_MeshHideFlags = (HideFlags) (1 | 2 | 4 | 8); + static bool s_Initialized; bool m_IsDisposed; ObjectPool m_MeshPool; @@ -104,6 +105,8 @@ static void HandleColorPreferences(string searchContext) Material m_VertMaterial; Material m_WireMaterial; + static Material s_LineMaterial; + public static Color faceSelectedColor { get { return s_FaceSelectedColor; } @@ -159,6 +162,15 @@ public EditorMeshHandles() ReloadPreferences(); } + static void Init() + { + if (s_Initialized) + return; + s_Initialized = true; + var shader = BuiltinMaterials.geometryShadersSupported ? BuiltinMaterials.lineShader : BuiltinMaterials.wireShader; + s_LineMaterial = CreateMaterial(Shader.Find(shader), "ProBuilder::GeneralUseLineMaterial"); + } + public void Dispose() { if (m_IsDisposed) @@ -211,6 +223,10 @@ public void ReloadPreferences() m_VertMaterial.SetFloat("_Scale", s_VertexPointSize * EditorGUIUtility.pixelsPerPoint); + m_WireMaterial.SetInt("_HandleZTest", (int) CompareFunction.LessEqual); + m_EdgeMaterial.SetInt("_HandleZTest", (int) CompareFunction.LessEqual); + + if (BuiltinMaterials.geometryShadersSupported) { m_WireMaterial.SetFloat("_Scale", s_WireframeLineSize * EditorGUIUtility.pixelsPerPoint); @@ -249,13 +265,24 @@ void DestroyMesh(Mesh mesh) CompareFunction.Always }; - internal bool BeginDrawingLines(CompareFunction zTest) + internal static bool BeginDrawingLines(Color color, CompareFunction zTest = CompareFunction.LessEqual, float thickness = -1f) { if (Event.current.type != EventType.Repaint) return false; + Init(); + + if (thickness < Mathf.Epsilon) + thickness = s_EdgeLineSize; + + s_LineMaterial.SetColor("_Color", color); + s_LineMaterial.SetInt("_HandleZTest", (int) zTest); + + if(BuiltinMaterials.geometryShadersSupported) + s_LineMaterial.SetFloat("_Scale", thickness * EditorGUIUtility.pixelsPerPoint); + if (!BuiltinMaterials.geometryShadersSupported || - !m_EdgeMaterial.SetPass(0)) + !s_LineMaterial.SetPass(0)) { if (s_ApplyWireMaterial == null) { @@ -283,12 +310,18 @@ internal bool BeginDrawingLines(CompareFunction zTest) return true; } - internal void EndDrawingLines() + internal static void EndDrawingLines() { GL.End(); GL.PopMatrix(); } + internal static void DrawLine(Vector3 a, Vector3 b) + { + GL.Vertex(a); + GL.Vertex(b); + } + internal void DrawSceneSelection(SceneSelection selection) { var mesh = selection.mesh; @@ -325,9 +358,7 @@ internal void DrawSceneSelection(SceneSelection selection) } else if (selection.edge != Edge.Empty) { - m_EdgeMaterial.SetColor("_Color", preselectionColor); - - if (BeginDrawingLines(Handles.zTest)) + if (BeginDrawingLines(preselectionColor, Handles.zTest)) { GL.MultMatrix(mesh.transform.localToWorldMatrix); GL.Vertex(positions[selection.edge.a]); diff --git a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs index 17ba665d9..c6169a578 100644 --- a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs +++ b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs @@ -15,6 +15,7 @@ namespace UnityEditor.ProBuilder public static class MeshSelection { static List s_TopSelection = new List(); + static ProBuilderMesh s_ActiveMesh; static bool s_ElementCountCacheIsDirty = true; @@ -78,7 +79,7 @@ static MeshSelection() /// public static ProBuilderMesh activeMesh { - get { return selectedObjectCount > 0 ? s_TopSelection[selectedObjectCount - 1] : null; } + get { return s_ActiveMesh; } } /// @@ -91,6 +92,7 @@ internal static void OnObjectSelectionChanged() // GameObjects returns both parent and child when both are selected, where transforms only returns the top-most // transform. s_TopSelection.Clear(); + s_ActiveMesh = null; var gameObjects = Selection.gameObjects; @@ -99,7 +101,11 @@ internal static void OnObjectSelectionChanged() var mesh = gameObjects[i].GetComponent(); if (mesh != null) + { + if (gameObjects[i] == Selection.activeGameObject) + s_ActiveMesh = mesh; s_TopSelection.Add(mesh); + } } selectedObjectCount = s_TopSelection.Count; @@ -277,6 +283,7 @@ internal static void AddToSelection(GameObject t) temp[len] = t; + Selection.activeObject = t; Selection.objects = temp; } @@ -294,6 +301,9 @@ internal static void RemoveFromSelection(GameObject t) } Selection.objects = temp; + + if (Selection.activeGameObject == t) + Selection.activeObject = temp.FirstOrDefault(); } internal static void SetSelection(IList newSelection) diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs index 315a682c1..f0218edcd 100644 --- a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; using System.Linq; -using UnityEditor; -using UnityEditor.ProBuilder; using UnityEngine; using UnityEngine.ProBuilder; +using UnityEngine.Rendering; namespace UnityEditor.ProBuilder { @@ -38,11 +37,13 @@ public MeshAndElementSelection(ProBuilderMesh mesh, PivotPoint pivot) { m_Mesh = mesh; m_Positions = mesh.positions.ToArray(); + var l2w = m_Mesh.transform.localToWorldMatrix; + for (int i = 0, c = m_Positions.Length; i < c; i++) + m_Positions[i] = l2w.MultiplyPoint3x4(m_Positions[i]); m_ApplyDeltaInWorldSpace = pivot == PivotPoint.WorldBoundingBoxCenter; var groups = new List(); ElementGroup.GetElementGroups(mesh, pivot, groups); m_Selection = groups; - } } @@ -57,7 +58,7 @@ public List indices } /// - /// The coordinate space in which vertices are transformed. + /// An additional transform to be applied to world space vertices prior to handle apply. /// public Matrix4x4 matrix { @@ -72,13 +73,13 @@ public Matrix4x4 inverseMatrix public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List groups) { Matrix4x4 matrix = Matrix4x4.identity; + var trs = mesh.transform.localToWorldMatrix; switch (pivot) { case PivotPoint.ModelBoundingBoxCenter: - // Vertices will be transformed in local space var bounds = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); - matrix = Matrix4x4.TRS(-bounds.center, Quaternion.identity, Vector3.one); + matrix = Matrix4x4.Translate(trs.MultiplyPoint3x4(-bounds.center)); break; case PivotPoint.IndividualOrigins: @@ -87,7 +88,7 @@ public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List< // case PivotPoint.WorldBoundingBoxCenter: // case PivotPoint.Custom: default: - matrix = Matrix4x4.identity; + matrix = Matrix4x4.Translate(-MeshSelection.GetHandlePosition()); break; } @@ -135,6 +136,40 @@ public void OnSceneGUI(Event evt) m_HandlePosition = MeshSelection.GetHandlePosition(); m_HandleRotation = MeshSelection.GetHandleRotation(ProBuilderEditor.handleOrientation); } + else + { + if (evt.type == EventType.Repaint && Tools.pivotMode == PivotMode.Pivot) + { + foreach (var key in m_Selection) + { + var trs = key.mesh.transform; + + foreach (var group in key.selection) + { + var p = group.inverseMatrix.MultiplyPoint3x4(Vector3.zero); + var size = HandleUtility.GetHandleSize(p) * .5f; + + if (EditorMeshHandles.BeginDrawingLines(Color.green, CompareFunction.Always)) + { + EditorMeshHandles.DrawLine(p, p + group.inverseMatrix.MultiplyVector(Vector3.up) * size); + EditorMeshHandles.EndDrawingLines(); + } + + if (EditorMeshHandles.BeginDrawingLines(Color.red, CompareFunction.Always)) + { + EditorMeshHandles.DrawLine(p, p + group.inverseMatrix.MultiplyVector(Vector3.right) * size); + EditorMeshHandles.EndDrawingLines(); + } + + if (EditorMeshHandles.BeginDrawingLines(Color.blue, CompareFunction.Always)) + { + EditorMeshHandles.DrawLine(p, p + group.inverseMatrix.MultiplyVector(Vector3.forward) * size); + EditorMeshHandles.EndDrawingLines(); + } + } + } + } + } DoTool(m_HandlePosition, m_HandleRotation); } @@ -184,26 +219,36 @@ protected void Apply(Matrix4x4 delta) foreach (var selectionGroup in m_Selection) { var mesh = selectionGroup.mesh; + var worldToLocal = mesh.transform.worldToLocalMatrix; + var localToWorld = Matrix4x4.Rotate(mesh.transform.localRotation); var origins = selectionGroup.positions; var positions = mesh.positionsInternal; + var transformed = selectionGroup.applyDeltaInWorldSpace + ? delta + : localToWorld * (delta * Matrix4x4.Rotate(m_HandleRotationOrigin).inverse); + foreach (var group in selectionGroup.selection) { foreach (var index in group.indices) { // todo Move matrix * origin to selection group c'tor - if (selectionGroup.applyDeltaInWorldSpace) - { - positions[index] = group.inverseMatrix.MultiplyPoint3x4(delta.MultiplyPoint3x4(group.matrix.MultiplyPoint3x4(origins[index]))); - } - else - { - var p = group.matrix.MultiplyPoint3x4(origins[index]); - p = m_HandleRotationOrigin * p; - p = delta.MultiplyPoint3x4(p); - p = Quaternion.Inverse(m_HandleRotationOrigin) * p; - positions[index] = group.inverseMatrix.MultiplyPoint3x4(p); - } +// if (selectionGroup.applyDeltaInWorldSpace) +// { + // position = WorldToLocal * (InverseGroupMatrix * (delta * (GroupMatrix * WorldPosition))) + positions[index] = worldToLocal.MultiplyPoint3x4( + group.inverseMatrix.MultiplyPoint3x4( + transformed.MultiplyPoint3x4( + group.matrix.MultiplyPoint3x4(origins[index])))); +// } +// else +// { +// var p = group.matrix.MultiplyPoint3x4(origins[index]); +// p = m_HandleRotationOrigin * p; +// p = delta.MultiplyPoint3x4(p); +// p = Quaternion.Inverse(m_HandleRotationOrigin) * p; +// positions[index] = group.inverseMatrix.MultiplyPoint3x4(p); +// } } } @@ -221,6 +266,40 @@ class MoveTool : VertexManipulationTool Vector3 m_HandlePosition; Vector3 delta = Vector3.zero; + void DoTranslate(Vector3 deltaInWorldSpace) + { + foreach (var key in m_Selection) + { + var mesh = key.mesh; + var meshRotation = mesh.transform.rotation; + var worldToLocal = mesh.transform.worldToLocalMatrix; + var origins = key.positions; + var positions = mesh.positionsInternal; + + var delta = key.applyDeltaInWorldSpace + ? deltaInWorldSpace + : meshRotation * (handleRotationOriginInverse * deltaInWorldSpace); + + var mat = Matrix4x4.Translate(delta); + + foreach (var group in key.selection) + { + foreach (var index in group.indices) + { + positions[index] = worldToLocal.MultiplyPoint3x4( + group.inverseMatrix.MultiplyPoint3x4( + mat.MultiplyPoint3x4(group.matrix.MultiplyPoint3x4(origins[index])))); + } + } + + mesh.mesh.vertices = positions; + mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); + mesh.Refresh(RefreshMask.Normals); + } + + ProBuilderEditor.UpdateMeshHandles(false); + } + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { if (!m_IsEditing) @@ -237,102 +316,9 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation delta = m_HandlePosition - handlePositionOrigin; - Apply(Matrix4x4.TRS(delta, Quaternion.identity, Vector3.one)); + DoTranslate(delta); } - - // if (!m_IsMovingElements) - // m_ElementHandlePosition = m_HandlePosition; - // - // m_ElementHandleCachedPosition = m_ElementHandlePosition; - // - // m_ElementHandlePosition = Handles.PositionHandle(m_ElementHandlePosition, m_HandleRotation); - // - // if (m_CurrentEvent.alt) - // return; - // - // if (m_ElementHandlePosition != m_ElementHandleCachedPosition) - // { - // Vector3 diff = m_ElementHandlePosition - m_ElementHandleCachedPosition; - // - // Vector3 mask = diff.ToMask(Math.handleEpsilon); - // - // if (m_DoSnapToVertex) - // { - // Vector3 v; - // - // if (FindNearestVertex(m_CurrentEvent.mousePosition, out v)) - // diff = Vector3.Scale(v - m_ElementHandleCachedPosition, mask); - // } - // else if (m_DoSnapToFace) - // { - // ProBuilderMesh obj = null; - // RaycastHit hit; - // Dictionary> ignore = new Dictionary>(); - // foreach (ProBuilderMesh pb in selection) - // ignore.Add(pb, new HashSet(pb.selectedFacesInternal)); - // - // if (EditorHandleUtility.FaceRaycast(m_CurrentEvent.mousePosition, out obj, out hit, ignore)) - // { - // if (mask.IntSum() == 1) - // { - // Ray r = new Ray(m_ElementHandleCachedPosition, -mask); - // Plane plane = new Plane(obj.transform.TransformDirection(hit.normal).normalized, - // obj.transform.TransformPoint(hit.point)); - // - // float forward, backward; - // plane.Raycast(r, out forward); - // plane.Raycast(r, out backward); - // float planeHit = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; - // r.direction = -r.direction; - // plane.Raycast(r, out forward); - // plane.Raycast(r, out backward); - // float rev = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; - // if (Mathf.Abs(rev) > Mathf.Abs(planeHit)) - // planeHit = rev; - // - // if (Mathf.Abs(planeHit) > Mathf.Epsilon) - // diff = mask * -planeHit; - // } - // else - // { - // diff = Vector3.Scale(obj.transform.TransformPoint(hit.point) - m_ElementHandleCachedPosition, mask.Abs()); - // } - // } - // } - // - // if (!m_IsMovingElements) - // { - // m_IsMovingElements = true; - // m_TranslateOrigin = m_ElementHandleCachedPosition; - // m_RotateOrigin = m_HandleRotation.eulerAngles; - // m_ScaleOrigin = m_HandleScale; - // - // OnBeginVertexMovement(); - // - // if (Event.current.modifiers == EventModifiers.Shift) - // ShiftExtrude(); - // - // ProGridsInterface.OnHandleMove(mask); - // } - // - // for (int i = 0; i < selection.Length; i++) - // { - // var mesh = selection[i]; - // - // mesh.TranslateVerticesInWorldSpace(mesh.selectedIndexesInternal, - // diff, - // m_SnapEnabled ? m_SnapValue : 0f, - // m_SnapAxisConstraint); - // - // mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); - // mesh.Refresh(RefreshMask.Normals); - // mesh.mesh.RecalculateBounds(); - // } - // - // UpdateMeshHandles(); - // } } - } class RotateTool : VertexManipulationTool diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index 656f10eb2..91482280d 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -913,6 +913,8 @@ void VertexScaleTool() m_ScaleTool = new ScaleTool(); m_ScaleTool.OnSceneGUI(Event.current); + return; + m_ElementHandlePosition = m_HandlePosition; m_HandleScalePrevious = m_HandleScale; From d1ca33230aad85d9b55ee9e125e5559c52d653dc Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Fri, 19 Oct 2018 17:38:08 -0400 Subject: [PATCH 09/27] wip - applying handle transforms in correct coordinate space --- .../Content/Shader/FaceHighlight.shader | 3 +- .../Editor/EditorCore/EditorMeshHandles.cs | 85 +----------- .../Editor/EditorCore/MoveTool.cs | 45 +++++-- .../Editor/EditorCore/ProBuilderEditor.cs | 3 +- .../EditorCore/StaticEditorMeshHandles.cs | 123 ++++++++++++++++++ .../StaticEditorMeshHandles.cs.meta | 11 ++ 6 files changed, 178 insertions(+), 92 deletions(-) create mode 100644 com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs create mode 100644 com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs.meta diff --git a/com.unity.probuilder/Content/Shader/FaceHighlight.shader b/com.unity.probuilder/Content/Shader/FaceHighlight.shader index cf2c43aa9..332e4aac0 100644 --- a/com.unity.probuilder/Content/Shader/FaceHighlight.shader +++ b/com.unity.probuilder/Content/Shader/FaceHighlight.shader @@ -4,13 +4,14 @@ Shader "Hidden/ProBuilder/FaceHighlight" { _Color ("Color Tint", Color) = (1,1,1,1) _Dither ("Dithering", float) = 0 + _HandleZTest ("_HandleZTest", Int) = 8 } SubShader { Tags { "IgnoreProjector"="True" "RenderType"="Geometry" } Lighting Off - ZTest LEqual + ZTest [_HandleZTest] ZWrite On Cull Off Blend Off diff --git a/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs b/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs index 5d2bc5c3a..40e24ac84 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs @@ -9,11 +9,10 @@ namespace UnityEditor.ProBuilder { - class EditorMeshHandles : IDisposable, IHasPreferences + partial class EditorMeshHandles : IDisposable, IHasPreferences { const HideFlags k_MeshHideFlags = (HideFlags) (1 | 2 | 4 | 8); - static bool s_Initialized; bool m_IsDisposed; ObjectPool m_MeshPool; @@ -101,12 +100,9 @@ static void HandleColorPreferences(string searchContext) static Color s_VertexUnselectedColor; Material m_EdgeMaterial; - Material m_FaceMaterial; Material m_VertMaterial; Material m_WireMaterial; - static Material s_LineMaterial; - public static Color faceSelectedColor { get { return s_FaceSelectedColor; } @@ -144,6 +140,8 @@ public static Color vertexUnselectedColor public EditorMeshHandles() { + Init(); + m_MeshPool = new ObjectPool( 0, 8, CreateMesh, DestroyMesh); m_WireHandles = new Dictionary(); m_VertexHandles = new Dictionary(); @@ -157,20 +155,10 @@ public EditorMeshHandles() m_EdgeMaterial = CreateMaterial(Shader.Find(lineShader), "ProBuilder::LineMaterial"); m_WireMaterial = CreateMaterial(Shader.Find(lineShader), "ProBuilder::WireMaterial"); m_VertMaterial = CreateMaterial(Shader.Find(vertShader), "ProBuilder::VertexMaterial"); - m_FaceMaterial = CreateMaterial(Shader.Find(BuiltinMaterials.faceShader), "ProBuilder::FaceMaterial"); ReloadPreferences(); } - static void Init() - { - if (s_Initialized) - return; - s_Initialized = true; - var shader = BuiltinMaterials.geometryShadersSupported ? BuiltinMaterials.lineShader : BuiltinMaterials.wireShader; - s_LineMaterial = CreateMaterial(Shader.Find(shader), "ProBuilder::GeneralUseLineMaterial"); - } - public void Dispose() { if (m_IsDisposed) @@ -185,7 +173,6 @@ public void Dispose() UObject.DestroyImmediate(m_EdgeMaterial); UObject.DestroyImmediate(m_WireMaterial); UObject.DestroyImmediate(m_VertMaterial); - UObject.DestroyImmediate(m_FaceMaterial); } public void ReloadPreferences() @@ -219,14 +206,13 @@ public void ReloadPreferences() } m_WireMaterial.SetColor("_Color", s_WireframeColor); - m_FaceMaterial.SetFloat("_Dither", (s_UseUnityColors || s_DitherFaceHandle) ? 1f : 0f); + s_FaceMaterial.SetFloat("_Dither", (s_UseUnityColors || s_DitherFaceHandle) ? 1f : 0f); m_VertMaterial.SetFloat("_Scale", s_VertexPointSize * EditorGUIUtility.pixelsPerPoint); m_WireMaterial.SetInt("_HandleZTest", (int) CompareFunction.LessEqual); m_EdgeMaterial.SetInt("_HandleZTest", (int) CompareFunction.LessEqual); - if (BuiltinMaterials.geometryShadersSupported) { m_WireMaterial.SetFloat("_Scale", s_WireframeLineSize * EditorGUIUtility.pixelsPerPoint); @@ -265,63 +251,6 @@ void DestroyMesh(Mesh mesh) CompareFunction.Always }; - internal static bool BeginDrawingLines(Color color, CompareFunction zTest = CompareFunction.LessEqual, float thickness = -1f) - { - if (Event.current.type != EventType.Repaint) - return false; - - Init(); - - if (thickness < Mathf.Epsilon) - thickness = s_EdgeLineSize; - - s_LineMaterial.SetColor("_Color", color); - s_LineMaterial.SetInt("_HandleZTest", (int) zTest); - - if(BuiltinMaterials.geometryShadersSupported) - s_LineMaterial.SetFloat("_Scale", thickness * EditorGUIUtility.pixelsPerPoint); - - if (!BuiltinMaterials.geometryShadersSupported || - !s_LineMaterial.SetPass(0)) - { - if (s_ApplyWireMaterial == null) - { - s_ApplyWireMaterial = typeof(HandleUtility).GetMethod( - "ApplyWireMaterial", - BindingFlags.Static | BindingFlags.NonPublic, - null, - new System.Type[] { typeof(CompareFunction) }, - null); - - if (s_ApplyWireMaterial == null) - { - Log.Info("Failed to find wire material, stopping draw lines."); - return false; - } - } - - s_ApplyWireMaterialArgs[0] = zTest; - s_ApplyWireMaterial.Invoke(null, s_ApplyWireMaterialArgs); - } - - GL.PushMatrix(); - GL.Begin(GL.LINES); - - return true; - } - - internal static void EndDrawingLines() - { - GL.End(); - GL.PopMatrix(); - } - - internal static void DrawLine(Vector3 a, Vector3 b) - { - GL.Vertex(a); - GL.Vertex(b); - } - internal void DrawSceneSelection(SceneSelection selection) { var mesh = selection.mesh; @@ -334,9 +263,9 @@ internal void DrawSceneSelection(SceneSelection selection) // Draw nearest edge if (selection.face != null) { - m_FaceMaterial.SetColor("_Color", preselectionColor); + s_FaceMaterial.SetColor("_Color", preselectionColor); - if (!m_FaceMaterial.SetPass(0)) + if (!s_FaceMaterial.SetPass(0)) return; GL.PushMatrix(); @@ -395,7 +324,7 @@ public void DrawSceneHandles(SelectMode mode) case SelectMode.Face: { RenderWithColor(m_WireHandles, m_WireMaterial, s_WireframeColor); - RenderWithColor(m_SelectedFaceHandles, m_FaceMaterial, s_FaceSelectedColor); + RenderWithColor(m_SelectedFaceHandles, s_FaceMaterial, s_FaceSelectedColor); break; } case SelectMode.Vertex: diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs index f0218edcd..77eb2fb8e 100644 --- a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs @@ -51,6 +51,7 @@ struct ElementGroup { List m_Indices; Matrix4x4 m_Matrix; + Matrix4x4 m_InverseMatrix; public List indices { @@ -67,19 +68,19 @@ public Matrix4x4 matrix public Matrix4x4 inverseMatrix { - get { return m_Matrix.inverse; } + get { return m_InverseMatrix; } } public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List groups) { - Matrix4x4 matrix = Matrix4x4.identity; + Matrix4x4 inverse = Matrix4x4.identity; var trs = mesh.transform.localToWorldMatrix; switch (pivot) { case PivotPoint.ModelBoundingBoxCenter: var bounds = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); - matrix = Matrix4x4.Translate(trs.MultiplyPoint3x4(-bounds.center)); + inverse = Matrix4x4.TRS(trs.MultiplyPoint3x4(bounds.center), mesh.transform.rotation, Vector3.one); break; case PivotPoint.IndividualOrigins: @@ -88,14 +89,15 @@ public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List< // case PivotPoint.WorldBoundingBoxCenter: // case PivotPoint.Custom: default: - matrix = Matrix4x4.Translate(-MeshSelection.GetHandlePosition()); + inverse = Matrix4x4.Translate(MeshSelection.GetHandlePosition()); break; } groups.Add(new ElementGroup() { m_Indices = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal), - m_Matrix = matrix, + m_InverseMatrix = inverse, + m_Matrix = inverse.inverse, }); } } @@ -142,28 +144,47 @@ public void OnSceneGUI(Event evt) { foreach (var key in m_Selection) { - var trs = key.mesh.transform; - +#if DEBUG foreach (var group in key.selection) { - var p = group.inverseMatrix.MultiplyPoint3x4(Vector3.zero); + using (var faceDrawer = new EditorMeshHandles.FaceDrawingScope(Color.cyan, CompareFunction.Always)) + { + foreach (var face in key.mesh.GetSelectedFaces()) + { + var indices = face.indexesInternal; + + for (int i = 0, c = indices.Length; i < c; i += 3) + { + faceDrawer.Draw( + group.matrix.MultiplyPoint3x4(key.positions[indices[i]]), + group.matrix.MultiplyPoint3x4(key.positions[indices[i + 1]]), + group.matrix.MultiplyPoint3x4(key.positions[indices[i + 2]]) + ); + } + } + } +#endif + + var m = group.matrix.inverse; + var p = m.MultiplyPoint3x4(Vector3.zero); + var size = HandleUtility.GetHandleSize(p) * .5f; if (EditorMeshHandles.BeginDrawingLines(Color.green, CompareFunction.Always)) { - EditorMeshHandles.DrawLine(p, p + group.inverseMatrix.MultiplyVector(Vector3.up) * size); + EditorMeshHandles.DrawLine(p, p + m.MultiplyVector(Vector3.up) * size); EditorMeshHandles.EndDrawingLines(); } if (EditorMeshHandles.BeginDrawingLines(Color.red, CompareFunction.Always)) { - EditorMeshHandles.DrawLine(p, p + group.inverseMatrix.MultiplyVector(Vector3.right) * size); + EditorMeshHandles.DrawLine(p, p + m.MultiplyVector(Vector3.right) * size); EditorMeshHandles.EndDrawingLines(); } if (EditorMeshHandles.BeginDrawingLines(Color.blue, CompareFunction.Always)) { - EditorMeshHandles.DrawLine(p, p + group.inverseMatrix.MultiplyVector(Vector3.forward) * size); + EditorMeshHandles.DrawLine(p, p + m.MultiplyVector(Vector3.forward) * size); EditorMeshHandles.EndDrawingLines(); } } @@ -278,7 +299,7 @@ void DoTranslate(Vector3 deltaInWorldSpace) var delta = key.applyDeltaInWorldSpace ? deltaInWorldSpace - : meshRotation * (handleRotationOriginInverse * deltaInWorldSpace); + : (handleRotationOriginInverse * deltaInWorldSpace); var mat = Matrix4x4.Translate(delta); diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index 91482280d..07f54a8b2 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -804,7 +804,7 @@ void DoubleClick(Event e) static VertexManipulationTool s_MoveTool; static VertexManipulationTool s_RotateTool; static VertexManipulationTool m_ScaleTool; - +#pragma warning disable 612 void VertexMoveTool() { if(s_MoveTool == null) @@ -1134,6 +1134,7 @@ void VertexRotateTool() UpdateMeshHandles(false); } } +#pragma warning restore 612 /// /// Extrude the current selection with no translation. diff --git a/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs new file mode 100644 index 000000000..62babd602 --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UObject = UnityEngine.Object; +using UnityEngine.ProBuilder; +using System.Reflection; +using UnityEngine.Rendering; + +namespace UnityEditor.ProBuilder +{ + partial class EditorMeshHandles + { + static bool s_Initialized; + + static Material s_LineMaterial; + static Material s_FaceMaterial; + + static Mesh s_FaceMesh; + + static void Init() + { + if (s_Initialized) + return; + s_Initialized = true; + + var shader = BuiltinMaterials.geometryShadersSupported ? BuiltinMaterials.lineShader : BuiltinMaterials.wireShader; + s_LineMaterial = CreateMaterial(Shader.Find(shader), "ProBuilder::GeneralUseLineMaterial"); + + s_FaceMesh = new Mesh(); + s_FaceMesh.hideFlags = HideFlags.HideAndDontSave; + + s_FaceMaterial = CreateMaterial(Shader.Find(BuiltinMaterials.faceShader), "ProBuilder::FaceMaterial"); + s_FaceMaterial.SetFloat("_Dither", (s_UseUnityColors || s_DitherFaceHandle) ? 1f : 0f); + } + + internal static bool BeginDrawingLines(Color color, CompareFunction zTest = CompareFunction.LessEqual, float thickness = -1f) + { + if (Event.current.type != EventType.Repaint) + return false; + + Init(); + + if (thickness < Mathf.Epsilon) + thickness = s_EdgeLineSize; + + s_LineMaterial.SetColor("_Color", color); + s_LineMaterial.SetInt("_HandleZTest", (int) zTest); + + if(BuiltinMaterials.geometryShadersSupported) + s_LineMaterial.SetFloat("_Scale", thickness * EditorGUIUtility.pixelsPerPoint); + + if (!BuiltinMaterials.geometryShadersSupported || + !s_LineMaterial.SetPass(0)) + { + if (s_ApplyWireMaterial == null) + { + s_ApplyWireMaterial = typeof(HandleUtility).GetMethod( + "ApplyWireMaterial", + BindingFlags.Static | BindingFlags.NonPublic, + null, + new System.Type[] { typeof(CompareFunction) }, + null); + + if (s_ApplyWireMaterial == null) + { + Log.Info("Failed to find wire material, stopping draw lines."); + return false; + } + } + + s_ApplyWireMaterialArgs[0] = zTest; + s_ApplyWireMaterial.Invoke(null, s_ApplyWireMaterialArgs); + } + + GL.PushMatrix(); + GL.Begin(GL.LINES); + + return true; + } + + internal static void EndDrawingLines() + { + GL.End(); + GL.PopMatrix(); + } + + internal static void DrawLine(Vector3 a, Vector3 b) + { + GL.Vertex(a); + GL.Vertex(b); + } + + internal class FaceDrawingScope : IDisposable + { + Vector3[] m_Positions; + + public FaceDrawingScope(Color color, CompareFunction zTest = CompareFunction.LessEqual) + { + s_FaceMaterial.SetColor("_Color", color); + s_FaceMaterial.SetInt("_HandleZTest", (int) zTest); + + if (!s_FaceMaterial.SetPass(0)) + throw new Exception("Failed initializing face material."); + + GL.PushMatrix(); + GL.Begin(GL.TRIANGLES); + } + + public void Dispose() + { + GL.End(); + GL.PopMatrix(); + } + + public void Draw(Vector3 a, Vector3 b, Vector3 c) + { + GL.Vertex(a); + GL.Vertex(b); + GL.Vertex(c); + } + } + } +} diff --git a/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs.meta b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs.meta new file mode 100644 index 000000000..a37c44ec4 --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 36feefd7c908ad14fbe6f426fe0d702e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From ccbc8301cba9f1826d687b50d802f877f1c276a9 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Wed, 24 Oct 2018 13:04:40 -0400 Subject: [PATCH 10/27] Get rotate tool working with world/pivot and handle orientation --- .../Editor/EditorCore/EditorMeshHandles.cs | 3 +- .../Editor/EditorCore/MeshSelection.cs | 15 +- .../Editor/EditorCore/MoveTool.cs | 196 +++++++---------- .../EditorCore/StaticEditorMeshHandles.cs | 200 ++++++++++++++---- .../Runtime/Core/ProBuilderMeshSelection.cs | 5 + 5 files changed, 252 insertions(+), 167 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs b/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs index 40e24ac84..62d5f52b4 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs @@ -287,12 +287,11 @@ internal void DrawSceneSelection(SceneSelection selection) } else if (selection.edge != Edge.Empty) { - if (BeginDrawingLines(preselectionColor, Handles.zTest)) + using (new EditorMeshHandles.LineDrawingScope(preselectionColor, -1f, Handles.zTest)) { GL.MultMatrix(mesh.transform.localToWorldMatrix); GL.Vertex(positions[selection.edge.a]); GL.Vertex(positions[selection.edge.b]); - EndDrawingLines(); } } else if (selection.vertex > -1) diff --git a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs index c6169a578..04f84a9ba 100644 --- a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs +++ b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs @@ -387,7 +387,7 @@ internal static Quaternion GetHandleRotation(HandleOrientation orientation) ProBuilderMesh mesh; Face face; - if(!GetFirstSelectedFace(out mesh, out face)) + if(!GetActiveFace(out mesh, out face)) goto default; // use average normal, tangent, and bi-tangent to calculate rotation relative to local space @@ -410,16 +410,13 @@ internal static Quaternion GetHandleRotation(HandleOrientation orientation) } } - static bool GetFirstSelectedFace(out ProBuilderMesh mesh, out Face face) + static bool GetActiveFace(out ProBuilderMesh mesh, out Face face) { - foreach (var m in topInternal) + if (activeMesh != null && activeMesh.selectedFaceCount > 0) { - if (m.selectedFaceCount > 0) - { - mesh = m; - face = mesh.selectedFacesInternal[0]; - return true; - } + mesh = activeMesh; + face = mesh.faces[activeMesh.selectedFaceIndicesInternal[0]]; + return true; } mesh = null; diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs index 77eb2fb8e..2aa3e19f6 100644 --- a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs @@ -11,7 +11,6 @@ struct MeshAndElementSelection ProBuilderMesh m_Mesh; Vector3[] m_Positions; List m_Selection; - bool m_ApplyDeltaInWorldSpace; public ProBuilderMesh mesh { @@ -28,11 +27,6 @@ public List selection get { return m_Selection; } } - public bool applyDeltaInWorldSpace - { - get { return m_ApplyDeltaInWorldSpace; } - } - public MeshAndElementSelection(ProBuilderMesh mesh, PivotPoint pivot) { m_Mesh = mesh; @@ -40,7 +34,6 @@ public MeshAndElementSelection(ProBuilderMesh mesh, PivotPoint pivot) var l2w = m_Mesh.transform.localToWorldMatrix; for (int i = 0, c = m_Positions.Length; i < c; i++) m_Positions[i] = l2w.MultiplyPoint3x4(m_Positions[i]); - m_ApplyDeltaInWorldSpace = pivot == PivotPoint.WorldBoundingBoxCenter; var groups = new List(); ElementGroup.GetElementGroups(mesh, pivot, groups); m_Selection = groups; @@ -50,8 +43,8 @@ public MeshAndElementSelection(ProBuilderMesh mesh, PivotPoint pivot) struct ElementGroup { List m_Indices; - Matrix4x4 m_Matrix; - Matrix4x4 m_InverseMatrix; + Matrix4x4 m_PreApplyPositionsMatrix; + Matrix4x4 m_PostApplyPositionsMatrix; public List indices { @@ -63,41 +56,49 @@ public List indices /// public Matrix4x4 matrix { - get { return m_Matrix; } + get { return m_PreApplyPositionsMatrix; } } public Matrix4x4 inverseMatrix { - get { return m_InverseMatrix; } + get { return m_PostApplyPositionsMatrix; } } public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List groups) { - Matrix4x4 inverse = Matrix4x4.identity; + Matrix4x4 postApplyPositionsMatrix, handleMatrix; var trs = mesh.transform.localToWorldMatrix; switch (pivot) { case PivotPoint.ModelBoundingBoxCenter: + { var bounds = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); - inverse = Matrix4x4.TRS(trs.MultiplyPoint3x4(bounds.center), mesh.transform.rotation, Vector3.one); + postApplyPositionsMatrix = Matrix4x4.TRS(trs.MultiplyPoint3x4(bounds.center), mesh.transform.rotation, Vector3.one); break; + } case PivotPoint.IndividualOrigins: + { + var bounds = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); + var ntb = Math.NormalTangentBitangent(mesh, mesh.selectedFacesInternal[0]); + var rot = mesh.transform.rotation * Quaternion.LookRotation(ntb.normal, ntb.bitangent); + postApplyPositionsMatrix = Matrix4x4.TRS(trs.MultiplyPoint3x4(bounds.center), rot, Vector3.one); break; + } - // case PivotPoint.WorldBoundingBoxCenter: - // case PivotPoint.Custom: default: - inverse = Matrix4x4.Translate(MeshSelection.GetHandlePosition()); + { + postApplyPositionsMatrix = Matrix4x4.Translate(MeshSelection.GetHandlePosition()); break; + } } groups.Add(new ElementGroup() { m_Indices = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal), - m_InverseMatrix = inverse, - m_Matrix = inverse.inverse, + m_PostApplyPositionsMatrix = postApplyPositionsMatrix, + m_PreApplyPositionsMatrix = postApplyPositionsMatrix.inverse }); } } @@ -111,6 +112,8 @@ abstract class VertexManipulationTool Quaternion m_HandleRotationOrigin; protected Quaternion handleRotationOriginInverse { get; private set; } + protected PivotPoint pivotPoint { get; private set; } + protected Vector3 handlePositionOrigin { get { return m_HandlePositionOrigin; } @@ -133,6 +136,13 @@ public void OnSceneGUI(Event evt) if (evt.alt) return; + if (Tools.pivotMode == PivotMode.Center) + pivotPoint = PivotPoint.WorldBoundingBoxCenter; + else if(ProBuilderEditor.handleOrientation == HandleOrientation.Normal) + pivotPoint = PivotPoint.IndividualOrigins; + else + pivotPoint = PivotPoint.ModelBoundingBoxCenter; + if (!m_IsEditing) { m_HandlePosition = MeshSelection.GetHandlePosition(); @@ -140,14 +150,18 @@ public void OnSceneGUI(Event evt) } else { - if (evt.type == EventType.Repaint && Tools.pivotMode == PivotMode.Pivot) +#if DEBUG + if (evt.type == EventType.Repaint) +#else + if (evt.type == EventType.Repaint && pivotPoint != PivotPoint.WorldBoundingBoxCenter) +#endif { foreach (var key in m_Selection) { #if DEBUG foreach (var group in key.selection) { - using (var faceDrawer = new EditorMeshHandles.FaceDrawingScope(Color.cyan, CompareFunction.Always)) + using (var faceDrawer = new EditorMeshHandles.TriangleDrawingScope(Color.cyan, CompareFunction.Always)) { foreach (var face in key.mesh.GetSelectedFaces()) { @@ -164,34 +178,18 @@ public void OnSceneGUI(Event evt) } } #endif - - var m = group.matrix.inverse; - var p = m.MultiplyPoint3x4(Vector3.zero); - - var size = HandleUtility.GetHandleSize(p) * .5f; - - if (EditorMeshHandles.BeginDrawingLines(Color.green, CompareFunction.Always)) - { - EditorMeshHandles.DrawLine(p, p + m.MultiplyVector(Vector3.up) * size); - EditorMeshHandles.EndDrawingLines(); - } - - if (EditorMeshHandles.BeginDrawingLines(Color.red, CompareFunction.Always)) - { - EditorMeshHandles.DrawLine(p, p + m.MultiplyVector(Vector3.right) * size); - EditorMeshHandles.EndDrawingLines(); - } - - if (EditorMeshHandles.BeginDrawingLines(Color.blue, CompareFunction.Always)) - { - EditorMeshHandles.DrawLine(p, p + m.MultiplyVector(Vector3.forward) * size); - EditorMeshHandles.EndDrawingLines(); - } + EditorMeshHandles.DrawGizmo(Vector3.zero, group.matrix.inverse); } } } } + Handles.BeginGUI(); + GUILayout.Label("pivot: " + pivotPoint); + GUILayout.Label("position: " + m_HandlePosition); + GUILayout.Label("rotation: " + m_HandleRotation.eulerAngles); + Handles.EndGUI(); + DoTool(m_HandlePosition, m_HandleRotation); } @@ -214,11 +212,7 @@ protected void BeginEdit() foreach (var mesh in MeshSelection.topInternal) { - var pivot = Tools.pivotMode == PivotMode.Center - ? PivotPoint.WorldBoundingBoxCenter - : PivotPoint.ModelBoundingBoxCenter; - - m_Selection.Add(new MeshAndElementSelection(mesh, pivot)); + m_Selection.Add(new MeshAndElementSelection(mesh, pivotPoint)); } } @@ -232,84 +226,22 @@ protected void FinishEdit() m_IsEditing = false; } - /// - /// - /// protected void Apply(Matrix4x4 delta) - { - foreach (var selectionGroup in m_Selection) - { - var mesh = selectionGroup.mesh; - var worldToLocal = mesh.transform.worldToLocalMatrix; - var localToWorld = Matrix4x4.Rotate(mesh.transform.localRotation); - var origins = selectionGroup.positions; - var positions = mesh.positionsInternal; - - var transformed = selectionGroup.applyDeltaInWorldSpace - ? delta - : localToWorld * (delta * Matrix4x4.Rotate(m_HandleRotationOrigin).inverse); - - foreach (var group in selectionGroup.selection) - { - foreach (var index in group.indices) - { - // todo Move matrix * origin to selection group c'tor -// if (selectionGroup.applyDeltaInWorldSpace) -// { - // position = WorldToLocal * (InverseGroupMatrix * (delta * (GroupMatrix * WorldPosition))) - positions[index] = worldToLocal.MultiplyPoint3x4( - group.inverseMatrix.MultiplyPoint3x4( - transformed.MultiplyPoint3x4( - group.matrix.MultiplyPoint3x4(origins[index])))); -// } -// else -// { -// var p = group.matrix.MultiplyPoint3x4(origins[index]); -// p = m_HandleRotationOrigin * p; -// p = delta.MultiplyPoint3x4(p); -// p = Quaternion.Inverse(m_HandleRotationOrigin) * p; -// positions[index] = group.inverseMatrix.MultiplyPoint3x4(p); -// } - } - } - - mesh.mesh.vertices = positions; - mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); - mesh.Refresh(RefreshMask.Normals); - } - - ProBuilderEditor.UpdateMeshHandles(false); - } - } - - class MoveTool : VertexManipulationTool - { - Vector3 m_HandlePosition; - Vector3 delta = Vector3.zero; - - void DoTranslate(Vector3 deltaInWorldSpace) { foreach (var key in m_Selection) { var mesh = key.mesh; - var meshRotation = mesh.transform.rotation; var worldToLocal = mesh.transform.worldToLocalMatrix; var origins = key.positions; var positions = mesh.positionsInternal; - var delta = key.applyDeltaInWorldSpace - ? deltaInWorldSpace - : (handleRotationOriginInverse * deltaInWorldSpace); - - var mat = Matrix4x4.Translate(delta); - foreach (var group in key.selection) { foreach (var index in group.indices) { positions[index] = worldToLocal.MultiplyPoint3x4( group.inverseMatrix.MultiplyPoint3x4( - mat.MultiplyPoint3x4(group.matrix.MultiplyPoint3x4(origins[index])))); + delta.MultiplyPoint3x4(group.matrix.MultiplyPoint3x4(origins[index])))); } } @@ -320,6 +252,12 @@ void DoTranslate(Vector3 deltaInWorldSpace) ProBuilderEditor.UpdateMeshHandles(false); } + } + + class MoveTool : VertexManipulationTool + { + Vector3 m_HandlePosition; + Matrix4x4 m_Translation = Matrix4x4.identity; protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { @@ -335,9 +273,25 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation if (!m_IsEditing) BeginEdit(); - delta = m_HandlePosition - handlePositionOrigin; + var delta = m_HandlePosition - handlePositionOrigin; - DoTranslate(delta); + switch (pivotPoint) + { + case PivotPoint.WorldBoundingBoxCenter: + break; + + case PivotPoint.ModelBoundingBoxCenter: + delta = handleRotationOriginInverse * delta; + break; + + case PivotPoint.IndividualOrigins: + delta = handleRotationOriginInverse * delta; + break; + } + + m_Translation.SetTRS(delta, Quaternion.identity, Vector3.one); + + Apply(m_Translation); } } } @@ -349,17 +303,27 @@ class RotateTool : VertexManipulationTool protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { if (!m_IsEditing) - m_Rotation = handleRotation; + m_Rotation = Quaternion.identity; EditorGUI.BeginChangeCheck(); - m_Rotation = Handles.RotationHandle(m_Rotation, handlePosition); + + var hm = Handles.matrix; + Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one); + m_Rotation = Handles.RotationHandle(m_Rotation, Vector3.zero); + Handles.matrix = hm; + if (EditorGUI.EndChangeCheck()) { if (!m_IsEditing) BeginEdit(); - Apply(Matrix4x4.Rotate(m_Rotation * handleRotationOriginInverse)); + Apply(Matrix4x4.Rotate(m_Rotation)); } + + Handles.BeginGUI(); + GUILayout.Label("rotate handle: " + (m_Rotation * handleRotationOriginInverse).eulerAngles); + GUILayout.Label("rotate handle: " + ( (m_Rotation * handleRotationOriginInverse) * handleRotationOriginInverse).eulerAngles); + Handles.EndGUI(); } } diff --git a/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs index 62babd602..e8d43e66e 100644 --- a/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs +++ b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs @@ -33,68 +33,180 @@ static void Init() s_FaceMaterial.SetFloat("_Dither", (s_UseUnityColors || s_DitherFaceHandle) ? 1f : 0f); } - internal static bool BeginDrawingLines(Color color, CompareFunction zTest = CompareFunction.LessEqual, float thickness = -1f) + internal static void DrawGizmo(Vector3 position, Quaternion rotation, float size = -1f) { - if (Event.current.type != EventType.Repaint) - return false; + var p = position; + size = HandleUtility.GetHandleSize(p) * size < 0f ? .5f : size; - Init(); + using (var lineDrawer = new LineDrawingScope(Color.green, -1f, CompareFunction.Always)) + { + lineDrawer.DrawLine(p, p + rotation * Vector3.up * size); + lineDrawer.color = Color.red; + lineDrawer.DrawLine(p, p + rotation * Vector3.right * size); + lineDrawer.color = Color.blue; + lineDrawer.DrawLine(p, p + rotation * Vector3.forward * size); + } + } + + internal static void DrawGizmo(Vector3 position, Matrix4x4 matrix, float size = -1f) + { + var p = matrix.MultiplyPoint3x4(position); + size = HandleUtility.GetHandleSize(p) * size < 0f ? .5f : size; + + using (var lineDrawer = new LineDrawingScope(Color.green, -1f, CompareFunction.Always)) + { + lineDrawer.DrawLine(p, p + matrix.MultiplyVector(Vector3.up) * size); + lineDrawer.color = Color.red; + lineDrawer.DrawLine(p, p + matrix.MultiplyVector(Vector3.right) * size); + lineDrawer.color = Color.blue; + lineDrawer.DrawLine(p, p + matrix.MultiplyVector(Vector3.forward) * size); + } + } - if (thickness < Mathf.Epsilon) - thickness = s_EdgeLineSize; + internal class LineDrawingScope : IDisposable + { + Color m_Color; + float m_Thickness; + CompareFunction m_ZTest; + bool m_IsDisposed; - s_LineMaterial.SetColor("_Color", color); - s_LineMaterial.SetInt("_HandleZTest", (int) zTest); + public Color color + { + get { return m_Color; } + set + { + End(); + m_Color = value; + Begin(); + } + } - if(BuiltinMaterials.geometryShadersSupported) - s_LineMaterial.SetFloat("_Scale", thickness * EditorGUIUtility.pixelsPerPoint); + public float thickness + { + get { return m_Thickness; } + set + { + End(); + if (value < Mathf.Epsilon) + m_Thickness = s_EdgeLineSize; + else + m_Thickness = value; + Begin(); + } + } - if (!BuiltinMaterials.geometryShadersSupported || - !s_LineMaterial.SetPass(0)) + public CompareFunction zTest { - if (s_ApplyWireMaterial == null) + get { return m_ZTest; } + + set { - s_ApplyWireMaterial = typeof(HandleUtility).GetMethod( - "ApplyWireMaterial", - BindingFlags.Static | BindingFlags.NonPublic, - null, - new System.Type[] { typeof(CompareFunction) }, - null); + End(); + m_ZTest = value; + Begin(); + } + } + + public LineDrawingScope(Color color, float thickness = -1f, CompareFunction zTest = CompareFunction.LessEqual) + { + Init(); + m_Color = color; + m_Thickness = thickness; + Begin(); + } + void Begin() + { + s_LineMaterial.SetColor("_Color", color); + s_LineMaterial.SetInt("_HandleZTest", (int) zTest); + + if(BuiltinMaterials.geometryShadersSupported) + s_LineMaterial.SetFloat("_Scale", thickness * EditorGUIUtility.pixelsPerPoint); + + if (!BuiltinMaterials.geometryShadersSupported || + !s_LineMaterial.SetPass(0)) + { if (s_ApplyWireMaterial == null) { - Log.Info("Failed to find wire material, stopping draw lines."); - return false; + s_ApplyWireMaterial = typeof(HandleUtility).GetMethod( + "ApplyWireMaterial", + BindingFlags.Static | BindingFlags.NonPublic, + null, + new System.Type[] { typeof(CompareFunction) }, + null); + + if (s_ApplyWireMaterial == null) + throw new Exception("Failed to find wire material, stopping draw lines."); } + + s_ApplyWireMaterialArgs[0] = zTest; + s_ApplyWireMaterial.Invoke(null, s_ApplyWireMaterialArgs); } - s_ApplyWireMaterialArgs[0] = zTest; - s_ApplyWireMaterial.Invoke(null, s_ApplyWireMaterialArgs); + GL.PushMatrix(); + GL.Begin(GL.LINES); + } + + void End() + { + GL.End(); + GL.PopMatrix(); } - GL.PushMatrix(); - GL.Begin(GL.LINES); + public void DrawLine(Vector3 a, Vector3 b) + { + GL.Vertex(a); + GL.Vertex(b); + } - return true; - } + public void Dispose() + { + if (m_IsDisposed) + return; + m_IsDisposed = true; - internal static void EndDrawingLines() - { - GL.End(); - GL.PopMatrix(); + End(); + } } - internal static void DrawLine(Vector3 a, Vector3 b) + internal class TriangleDrawingScope : IDisposable { - GL.Vertex(a); - GL.Vertex(b); - } + Color m_Color; + CompareFunction m_ZTest; + bool m_IsDisposed; - internal class FaceDrawingScope : IDisposable - { - Vector3[] m_Positions; + public Color color + { + get { return m_Color; } + set + { + End(); + m_Color = value; + Begin(); + } + } + + public CompareFunction zTest + { + get { return m_ZTest; } + + set + { + End(); + m_ZTest = value; + Begin(); + } + } - public FaceDrawingScope(Color color, CompareFunction zTest = CompareFunction.LessEqual) + public TriangleDrawingScope(Color color, CompareFunction zTest = CompareFunction.LessEqual) + { + Init(); + m_Color = color; + m_ZTest = zTest; + Begin(); + } + + void Begin() { s_FaceMaterial.SetColor("_Color", color); s_FaceMaterial.SetInt("_HandleZTest", (int) zTest); @@ -106,12 +218,20 @@ public FaceDrawingScope(Color color, CompareFunction zTest = CompareFunction.Les GL.Begin(GL.TRIANGLES); } - public void Dispose() + void End() { GL.End(); GL.PopMatrix(); } + public void Dispose() + { + if (m_IsDisposed) + return; + m_IsDisposed = true; + End(); + } + public void Draw(Vector3 a, Vector3 b, Vector3 c) { GL.Vertex(a); diff --git a/com.unity.probuilder/Runtime/Core/ProBuilderMeshSelection.cs b/com.unity.probuilder/Runtime/Core/ProBuilderMeshSelection.cs index 21536ede8..5d75b20ad 100644 --- a/com.unity.probuilder/Runtime/Core/ProBuilderMeshSelection.cs +++ b/com.unity.probuilder/Runtime/Core/ProBuilderMeshSelection.cs @@ -113,6 +113,11 @@ internal Face[] selectedFacesInternal get { return GetSelectedFaces(); } } + internal int[] selectedFaceIndicesInternal + { + get { return m_SelectedFaces; } + } + /// /// A collection of the currently selected faces by their index in the @"UnityEngine.ProBuilder.ProBuilderMesh.faces" array. /// From fc331eed96d47f7106aadad2cfb692ffc5036c07 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Wed, 24 Oct 2018 13:19:39 -0400 Subject: [PATCH 11/27] remove debug code --- .../Editor/EditorCore/MoveTool.cs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs index 2aa3e19f6..98b6cff70 100644 --- a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs @@ -150,7 +150,7 @@ public void OnSceneGUI(Event evt) } else { -#if DEBUG +#if DEBUG_HANDLES if (evt.type == EventType.Repaint) #else if (evt.type == EventType.Repaint && pivotPoint != PivotPoint.WorldBoundingBoxCenter) @@ -158,9 +158,9 @@ public void OnSceneGUI(Event evt) { foreach (var key in m_Selection) { -#if DEBUG foreach (var group in key.selection) { +#if DEBUG_HANDLES using (var faceDrawer = new EditorMeshHandles.TriangleDrawingScope(Color.cyan, CompareFunction.Always)) { foreach (var face in key.mesh.GetSelectedFaces()) @@ -184,12 +184,6 @@ public void OnSceneGUI(Event evt) } } - Handles.BeginGUI(); - GUILayout.Label("pivot: " + pivotPoint); - GUILayout.Label("position: " + m_HandlePosition); - GUILayout.Label("rotation: " + m_HandleRotation.eulerAngles); - Handles.EndGUI(); - DoTool(m_HandlePosition, m_HandleRotation); } @@ -319,11 +313,6 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation Apply(Matrix4x4.Rotate(m_Rotation)); } - - Handles.BeginGUI(); - GUILayout.Label("rotate handle: " + (m_Rotation * handleRotationOriginInverse).eulerAngles); - GUILayout.Label("rotate handle: " + ( (m_Rotation * handleRotationOriginInverse) * handleRotationOriginInverse).eulerAngles); - Handles.EndGUI(); } } From 93c730bf090be2b3ad5ab6dabd6733cc6be54633 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Wed, 24 Oct 2018 13:23:41 -0400 Subject: [PATCH 12/27] draw handle guide in world coordinates too --- com.unity.probuilder/Editor/EditorCore/MoveTool.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs index 98b6cff70..8f946c60d 100644 --- a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs @@ -150,11 +150,7 @@ public void OnSceneGUI(Event evt) } else { -#if DEBUG_HANDLES if (evt.type == EventType.Repaint) -#else - if (evt.type == EventType.Repaint && pivotPoint != PivotPoint.WorldBoundingBoxCenter) -#endif { foreach (var key in m_Selection) { @@ -326,11 +322,14 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation m_Scale = Vector3.one; EditorGUI.BeginChangeCheck(); - m_Scale = Handles.ScaleHandle(m_Scale, handlePosition, handleRotation, UnityEditor.HandleUtility.GetHandleSize(handlePosition)); + + m_Scale = Handles.ScaleHandle(m_Scale, handlePosition, handleRotation, HandleUtility.GetHandleSize(handlePosition)); + if (EditorGUI.EndChangeCheck()) { if (!m_IsEditing) BeginEdit(); + Apply(Matrix4x4.Scale(m_Scale)); } } From f5c5d7ef2562e65974888fd4e52e843aa764e98c Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Wed, 24 Oct 2018 13:52:48 -0400 Subject: [PATCH 13/27] move vertex manipulation tools to their own files --- .../Editor/EditorCore/MoveTool.cs | 292 +----------------- .../Editor/EditorCore/RotateTool.cs | 56 ++++ .../Editor/EditorCore/RotateTool.cs.meta | 11 + .../Editor/EditorCore/ScaleTool.cs | 28 ++ .../Editor/EditorCore/ScaleTool.cs.meta | 11 + .../EditorCore/VertexManipulationTool.cs | 245 +++++++++++++++ .../EditorCore/VertexManipulationTool.cs.meta | 11 + 7 files changed, 363 insertions(+), 291 deletions(-) create mode 100644 com.unity.probuilder/Editor/EditorCore/RotateTool.cs create mode 100644 com.unity.probuilder/Editor/EditorCore/RotateTool.cs.meta create mode 100644 com.unity.probuilder/Editor/EditorCore/ScaleTool.cs create mode 100644 com.unity.probuilder/Editor/EditorCore/ScaleTool.cs.meta create mode 100644 com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs create mode 100644 com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs.meta diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs index 8f946c60d..695aeec21 100644 --- a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs @@ -1,249 +1,8 @@ -using System.Collections.Generic; -using System.Linq; -using UnityEngine; +using UnityEngine; using UnityEngine.ProBuilder; -using UnityEngine.Rendering; namespace UnityEditor.ProBuilder { - struct MeshAndElementSelection - { - ProBuilderMesh m_Mesh; - Vector3[] m_Positions; - List m_Selection; - - public ProBuilderMesh mesh - { - get { return m_Mesh; } - } - - public Vector3[] positions - { - get { return m_Positions; } - } - - public List selection - { - get { return m_Selection; } - } - - public MeshAndElementSelection(ProBuilderMesh mesh, PivotPoint pivot) - { - m_Mesh = mesh; - m_Positions = mesh.positions.ToArray(); - var l2w = m_Mesh.transform.localToWorldMatrix; - for (int i = 0, c = m_Positions.Length; i < c; i++) - m_Positions[i] = l2w.MultiplyPoint3x4(m_Positions[i]); - var groups = new List(); - ElementGroup.GetElementGroups(mesh, pivot, groups); - m_Selection = groups; - } - } - - struct ElementGroup - { - List m_Indices; - Matrix4x4 m_PreApplyPositionsMatrix; - Matrix4x4 m_PostApplyPositionsMatrix; - - public List indices - { - get { return m_Indices; } - } - - /// - /// An additional transform to be applied to world space vertices prior to handle apply. - /// - public Matrix4x4 matrix - { - get { return m_PreApplyPositionsMatrix; } - } - - public Matrix4x4 inverseMatrix - { - get { return m_PostApplyPositionsMatrix; } - } - - public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List groups) - { - Matrix4x4 postApplyPositionsMatrix, handleMatrix; - var trs = mesh.transform.localToWorldMatrix; - - switch (pivot) - { - case PivotPoint.ModelBoundingBoxCenter: - { - var bounds = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); - postApplyPositionsMatrix = Matrix4x4.TRS(trs.MultiplyPoint3x4(bounds.center), mesh.transform.rotation, Vector3.one); - break; - } - - case PivotPoint.IndividualOrigins: - { - var bounds = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); - var ntb = Math.NormalTangentBitangent(mesh, mesh.selectedFacesInternal[0]); - var rot = mesh.transform.rotation * Quaternion.LookRotation(ntb.normal, ntb.bitangent); - postApplyPositionsMatrix = Matrix4x4.TRS(trs.MultiplyPoint3x4(bounds.center), rot, Vector3.one); - break; - } - - default: - { - postApplyPositionsMatrix = Matrix4x4.Translate(MeshSelection.GetHandlePosition()); - break; - } - } - - groups.Add(new ElementGroup() - { - m_Indices = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal), - m_PostApplyPositionsMatrix = postApplyPositionsMatrix, - m_PreApplyPositionsMatrix = postApplyPositionsMatrix.inverse - }); - } - } - - abstract class VertexManipulationTool - { - Vector3 m_HandlePosition; - Quaternion m_HandleRotation; - - Vector3 m_HandlePositionOrigin; - Quaternion m_HandleRotationOrigin; - protected Quaternion handleRotationOriginInverse { get; private set; } - - protected PivotPoint pivotPoint { get; private set; } - - protected Vector3 handlePositionOrigin - { - get { return m_HandlePositionOrigin; } - } - - protected Quaternion handleRotationOrigin - { - get { return m_HandleRotationOrigin; } - } - - protected List m_Selection = new List(); - - protected bool m_IsEditing; - - public void OnSceneGUI(Event evt) - { - if (evt.type == EventType.MouseUp || evt.type == EventType.Ignore) - FinishEdit(); - - if (evt.alt) - return; - - if (Tools.pivotMode == PivotMode.Center) - pivotPoint = PivotPoint.WorldBoundingBoxCenter; - else if(ProBuilderEditor.handleOrientation == HandleOrientation.Normal) - pivotPoint = PivotPoint.IndividualOrigins; - else - pivotPoint = PivotPoint.ModelBoundingBoxCenter; - - if (!m_IsEditing) - { - m_HandlePosition = MeshSelection.GetHandlePosition(); - m_HandleRotation = MeshSelection.GetHandleRotation(ProBuilderEditor.handleOrientation); - } - else - { - if (evt.type == EventType.Repaint) - { - foreach (var key in m_Selection) - { - foreach (var group in key.selection) - { -#if DEBUG_HANDLES - using (var faceDrawer = new EditorMeshHandles.TriangleDrawingScope(Color.cyan, CompareFunction.Always)) - { - foreach (var face in key.mesh.GetSelectedFaces()) - { - var indices = face.indexesInternal; - - for (int i = 0, c = indices.Length; i < c; i += 3) - { - faceDrawer.Draw( - group.matrix.MultiplyPoint3x4(key.positions[indices[i]]), - group.matrix.MultiplyPoint3x4(key.positions[indices[i + 1]]), - group.matrix.MultiplyPoint3x4(key.positions[indices[i + 2]]) - ); - } - } - } -#endif - EditorMeshHandles.DrawGizmo(Vector3.zero, group.matrix.inverse); - } - } - } - } - - DoTool(m_HandlePosition, m_HandleRotation); - } - - protected abstract void DoTool(Vector3 handlePosition, Quaternion handleRotation); - - protected void BeginEdit() - { - if (m_IsEditing) - return; - - m_IsEditing = true; - - m_HandlePositionOrigin = m_HandlePosition; - m_HandleRotationOrigin = m_HandleRotation; - handleRotationOriginInverse = Quaternion.Inverse(m_HandleRotation); - - ProBuilderEditor.instance.OnBeginVertexMovement(); - - m_Selection.Clear(); - - foreach (var mesh in MeshSelection.topInternal) - { - m_Selection.Add(new MeshAndElementSelection(mesh, pivotPoint)); - } - } - - protected void FinishEdit() - { - if (!m_IsEditing) - return; - - ProBuilderEditor.instance.OnFinishVertexModification(); - - m_IsEditing = false; - } - - protected void Apply(Matrix4x4 delta) - { - foreach (var key in m_Selection) - { - var mesh = key.mesh; - var worldToLocal = mesh.transform.worldToLocalMatrix; - var origins = key.positions; - var positions = mesh.positionsInternal; - - foreach (var group in key.selection) - { - foreach (var index in group.indices) - { - positions[index] = worldToLocal.MultiplyPoint3x4( - group.inverseMatrix.MultiplyPoint3x4( - delta.MultiplyPoint3x4(group.matrix.MultiplyPoint3x4(origins[index])))); - } - } - - mesh.mesh.vertices = positions; - mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); - mesh.Refresh(RefreshMask.Normals); - } - - ProBuilderEditor.UpdateMeshHandles(false); - } - } - class MoveTool : VertexManipulationTool { Vector3 m_HandlePosition; @@ -285,53 +44,4 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation } } } - - class RotateTool : VertexManipulationTool - { - Quaternion m_Rotation; - - protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) - { - if (!m_IsEditing) - m_Rotation = Quaternion.identity; - - EditorGUI.BeginChangeCheck(); - - var hm = Handles.matrix; - Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one); - m_Rotation = Handles.RotationHandle(m_Rotation, Vector3.zero); - Handles.matrix = hm; - - if (EditorGUI.EndChangeCheck()) - { - if (!m_IsEditing) - BeginEdit(); - - Apply(Matrix4x4.Rotate(m_Rotation)); - } - } - } - - class ScaleTool : VertexManipulationTool - { - Vector3 m_Scale; - - protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) - { - if (!m_IsEditing) - m_Scale = Vector3.one; - - EditorGUI.BeginChangeCheck(); - - m_Scale = Handles.ScaleHandle(m_Scale, handlePosition, handleRotation, HandleUtility.GetHandleSize(handlePosition)); - - if (EditorGUI.EndChangeCheck()) - { - if (!m_IsEditing) - BeginEdit(); - - Apply(Matrix4x4.Scale(m_Scale)); - } - } - } } \ No newline at end of file diff --git a/com.unity.probuilder/Editor/EditorCore/RotateTool.cs b/com.unity.probuilder/Editor/EditorCore/RotateTool.cs new file mode 100644 index 000000000..85fc0a549 --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/RotateTool.cs @@ -0,0 +1,56 @@ +using UnityEngine; +using UnityEngine.ProBuilder; + +namespace UnityEditor.ProBuilder +{ + class RotateTool : VertexManipulationTool + { + Quaternion m_Rotation; + + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) + { + if (Tools.pivotMode == PivotMode.Pivot) + { + EditorGUI.BeginChangeCheck(); + + if (!m_IsEditing) + m_Rotation = Quaternion.identity; + + var hm = Handles.matrix; + Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one); + m_Rotation = Handles.RotationHandle(m_Rotation, Vector3.zero); + Handles.matrix = hm; + + if (EditorGUI.EndChangeCheck()) + { + if (!m_IsEditing) + BeginEdit(); + + Apply(Matrix4x4.Rotate(m_Rotation)); + } + } + else + { + EditorGUI.BeginChangeCheck(); + + if (!m_IsEditing) + m_Rotation = handleRotation; + + m_Rotation = Handles.RotationHandle(m_Rotation, handlePosition); + + if (EditorGUI.EndChangeCheck()) + { + if (!m_IsEditing) + BeginEdit(); + + Apply(Matrix4x4.Rotate(m_Rotation * Quaternion.Inverse(handleRotationOrigin))); + } + } + + + Handles.BeginGUI(); + GUILayout.Label("Rotation: " + m_Rotation.eulerAngles); + Handles.EndGUI(); + } + } +} \ No newline at end of file diff --git a/com.unity.probuilder/Editor/EditorCore/RotateTool.cs.meta b/com.unity.probuilder/Editor/EditorCore/RotateTool.cs.meta new file mode 100644 index 000000000..2d4474ff0 --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/RotateTool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ad47c69dfccd598478ddc2368ca5a5d6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs b/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs new file mode 100644 index 000000000..d4f0cfa34 --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs @@ -0,0 +1,28 @@ +using UnityEngine; + +namespace UnityEditor.ProBuilder +{ + class ScaleTool : VertexManipulationTool + { + Vector3 m_Scale; + + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) + { + if (!m_IsEditing) + m_Scale = Vector3.one; + + EditorGUI.BeginChangeCheck(); + + m_Scale = Handles.ScaleHandle(m_Scale, handlePosition, handleRotation, HandleUtility.GetHandleSize(handlePosition)); + + if (EditorGUI.EndChangeCheck()) + { + if (!m_IsEditing) + BeginEdit(); + + Apply(Matrix4x4.Scale(m_Scale)); + } + } + } + +} diff --git a/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs.meta b/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs.meta new file mode 100644 index 000000000..e203b5340 --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9902f16875bf9cd4f99701f6d2721272 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs new file mode 100644 index 000000000..68b21ec63 --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs @@ -0,0 +1,245 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.ProBuilder; +#if DEBUG_HANDLES +using UnityEngine.Rendering; +#endif + +namespace UnityEditor.ProBuilder +{ + struct MeshAndElementSelection + { + ProBuilderMesh m_Mesh; + Vector3[] m_Positions; + List m_Selection; + + public ProBuilderMesh mesh + { + get { return m_Mesh; } + } + + public Vector3[] positions + { + get { return m_Positions; } + } + + public List selection + { + get { return m_Selection; } + } + + public MeshAndElementSelection(ProBuilderMesh mesh, PivotPoint pivot) + { + m_Mesh = mesh; + m_Positions = mesh.positions.ToArray(); + var l2w = m_Mesh.transform.localToWorldMatrix; + for (int i = 0, c = m_Positions.Length; i < c; i++) + m_Positions[i] = l2w.MultiplyPoint3x4(m_Positions[i]); + var groups = new List(); + ElementGroup.GetElementGroups(mesh, pivot, groups); + m_Selection = groups; + } + } + + struct ElementGroup + { + List m_Indices; + Matrix4x4 m_PreApplyPositionsMatrix; + Matrix4x4 m_PostApplyPositionsMatrix; + + public List indices + { + get { return m_Indices; } + } + + public Matrix4x4 matrix + { + get { return m_PreApplyPositionsMatrix; } + } + + public Matrix4x4 inverseMatrix + { + get { return m_PostApplyPositionsMatrix; } + } + + public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List groups) + { + Matrix4x4 postApplyPositionsMatrix; + var trs = mesh.transform.localToWorldMatrix; + + switch (pivot) + { + case PivotPoint.ModelBoundingBoxCenter: + { + var bounds = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); + postApplyPositionsMatrix = Matrix4x4.TRS(trs.MultiplyPoint3x4(bounds.center), mesh.transform.rotation, Vector3.one); + break; + } + + case PivotPoint.IndividualOrigins: + { + var bounds = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); + var ntb = Math.NormalTangentBitangent(mesh, mesh.selectedFacesInternal[0]); + var rot = mesh.transform.rotation * Quaternion.LookRotation(ntb.normal, ntb.bitangent); + postApplyPositionsMatrix = Matrix4x4.TRS(trs.MultiplyPoint3x4(bounds.center), rot, Vector3.one); + break; + } + + default: + { + postApplyPositionsMatrix = Matrix4x4.Translate(MeshSelection.GetHandlePosition()); + break; + } + } + + groups.Add(new ElementGroup() + { + m_Indices = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal), + m_PostApplyPositionsMatrix = postApplyPositionsMatrix, + m_PreApplyPositionsMatrix = postApplyPositionsMatrix.inverse + }); + } + } + + abstract class VertexManipulationTool + { + Vector3 m_HandlePosition; + Quaternion m_HandleRotation; + + Vector3 m_HandlePositionOrigin; + Quaternion m_HandleRotationOrigin; + protected Quaternion handleRotationOriginInverse { get; private set; } + + protected PivotPoint pivotPoint { get; private set; } + + protected Vector3 handlePositionOrigin + { + get { return m_HandlePositionOrigin; } + } + + protected Quaternion handleRotationOrigin + { + get { return m_HandleRotationOrigin; } + } + + protected List m_Selection = new List(); + + protected bool m_IsEditing; + + public void OnSceneGUI(Event evt) + { + if (evt.type == EventType.MouseUp || evt.type == EventType.Ignore) + FinishEdit(); + + if (evt.alt) + return; + + if (Tools.pivotMode == PivotMode.Center) + pivotPoint = PivotPoint.WorldBoundingBoxCenter; + else if(ProBuilderEditor.handleOrientation == HandleOrientation.Normal) + pivotPoint = PivotPoint.IndividualOrigins; + else + pivotPoint = PivotPoint.ModelBoundingBoxCenter; + + if (!m_IsEditing) + { + m_HandlePosition = MeshSelection.GetHandlePosition(); + m_HandleRotation = MeshSelection.GetHandleRotation(ProBuilderEditor.handleOrientation); + } + else + { + if (evt.type == EventType.Repaint) + { + foreach (var key in m_Selection) + { + foreach (var group in key.selection) + { +#if DEBUG_HANDLES + using (var faceDrawer = new EditorMeshHandles.TriangleDrawingScope(Color.cyan, CompareFunction.Always)) + { + foreach (var face in key.mesh.GetSelectedFaces()) + { + var indices = face.indexesInternal; + + for (int i = 0, c = indices.Length; i < c; i += 3) + { + faceDrawer.Draw( + group.matrix.MultiplyPoint3x4(key.positions[indices[i]]), + group.matrix.MultiplyPoint3x4(key.positions[indices[i + 1]]), + group.matrix.MultiplyPoint3x4(key.positions[indices[i + 2]]) + ); + } + } + } +#endif + EditorMeshHandles.DrawGizmo(Vector3.zero, group.matrix.inverse); + } + } + } + } + + DoTool(m_HandlePosition, m_HandleRotation); + } + + protected abstract void DoTool(Vector3 handlePosition, Quaternion handleRotation); + + protected void BeginEdit() + { + if (m_IsEditing) + return; + + m_IsEditing = true; + + m_HandlePositionOrigin = m_HandlePosition; + m_HandleRotationOrigin = m_HandleRotation; + handleRotationOriginInverse = Quaternion.Inverse(m_HandleRotation); + + ProBuilderEditor.instance.OnBeginVertexMovement(); + + m_Selection.Clear(); + + foreach (var mesh in MeshSelection.topInternal) + { + m_Selection.Add(new MeshAndElementSelection(mesh, pivotPoint)); + } + } + + protected void FinishEdit() + { + if (!m_IsEditing) + return; + + ProBuilderEditor.instance.OnFinishVertexModification(); + + m_IsEditing = false; + } + + protected void Apply(Matrix4x4 delta) + { + foreach (var key in m_Selection) + { + var mesh = key.mesh; + var worldToLocal = mesh.transform.worldToLocalMatrix; + var origins = key.positions; + var positions = mesh.positionsInternal; + + foreach (var group in key.selection) + { + foreach (var index in group.indices) + { + positions[index] = worldToLocal.MultiplyPoint3x4( + group.inverseMatrix.MultiplyPoint3x4( + delta.MultiplyPoint3x4(group.matrix.MultiplyPoint3x4(origins[index])))); + } + } + + mesh.mesh.vertices = positions; + mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); + mesh.Refresh(RefreshMask.Normals); + } + + ProBuilderEditor.UpdateMeshHandles(false); + } + } +} diff --git a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs.meta b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs.meta new file mode 100644 index 000000000..14316b76f --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e4919131c75b7914b99be1a9252658bc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From cf362edec0bb6c348ad706fc8c3cf2a93d563baa Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Wed, 24 Oct 2018 16:23:02 -0400 Subject: [PATCH 14/27] pivot + normal orientation uses face selection groups for coordinate space --- .../Editor/EditorCore/EditorMeshHandles.cs | 34 ++-- .../Editor/EditorCore/ProBuilderEditor.cs | 64 ------- .../Editor/EditorCore/RotateTool.cs | 5 - .../EditorCore/StaticEditorMeshHandles.cs | 2 +- .../EditorCore/VertexManipulationTool.cs | 158 ++++++++++++++++-- .../MenuActions/Geometry/ExtrudeEdges.cs | 4 +- .../MenuActions/Geometry/ExtrudeFaces.cs | 6 +- com.unity.probuilder/Runtime/Core/Math.cs | 39 +++++ .../Runtime/Core/MeshHandle.cs | 3 + .../Runtime/Core/ProBuilderMeshFunction.cs | 34 ++++ .../Runtime/Core/WingedEdge.cs | 3 +- 11 files changed, 239 insertions(+), 113 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs b/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs index 62d5f52b4..2c3d5c1bf 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs @@ -52,6 +52,9 @@ partial class EditorMeshHandles : IDisposable, IHasPreferences [UserSetting] static Pref s_VertexPointSize = new Pref("graphics.vertexPointSize", 3f, SettingsScopes.User); + [UserSetting("Graphics", "Handle Z Test", "The compare function to use when drawing mesh handles.")] + static Pref s_HandleCompareFunction = new Pref("graphics.handleZTest", CompareFunction.Always, SettingsScopes.User); + [UserSettingBlock("Graphics")] static void HandleColorPreferences(string searchContext) { @@ -263,31 +266,24 @@ internal void DrawSceneSelection(SceneSelection selection) // Draw nearest edge if (selection.face != null) { - s_FaceMaterial.SetColor("_Color", preselectionColor); - - if (!s_FaceMaterial.SetPass(0)) - return; - - GL.PushMatrix(); - GL.Begin(GL.TRIANGLES); - GL.MultMatrix(mesh.transform.localToWorldMatrix); + using (new TriangleDrawingScope(preselectionColor, s_HandleCompareFunction)) + { + GL.MultMatrix(mesh.transform.localToWorldMatrix); - var face = selection.face; - var ind = face.indexes; + var face = selection.face; + var ind = face.indexes; - for (int i = 0, c = ind.Count; i < c; i += 3) - { - GL.Vertex(positions[ind[i]]); - GL.Vertex(positions[ind[i+1]]); - GL.Vertex(positions[ind[i+2]]); + for (int i = 0, c = ind.Count; i < c; i += 3) + { + GL.Vertex(positions[ind[i]]); + GL.Vertex(positions[ind[i+1]]); + GL.Vertex(positions[ind[i+2]]); + } } - - GL.End(); - GL.PopMatrix(); } else if (selection.edge != Edge.Empty) { - using (new EditorMeshHandles.LineDrawingScope(preselectionColor, -1f, Handles.zTest)) + using (new LineDrawingScope(preselectionColor, -1f, s_HandleCompareFunction)) { GL.MultMatrix(mesh.transform.localToWorldMatrix); GL.Vertex(positions[selection.edge.a]); diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index 07f54a8b2..9faaa010b 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -68,9 +68,7 @@ public sealed class ProBuilderEditor : EditorWindow, IHasCustomMenu internal Pref m_BackfaceSelectEnabled = new Pref("editor.backFaceSelectEnabled", false); internal Pref m_DragSelectRectMode = new Pref("editor.dragSelectRectMode", RectSelectMode.Partial); - internal Pref m_ExtrudeMethod = new Pref("editor.extrudeMethod", ExtrudeMethod.FaceNormal); internal Pref m_SelectModifierBehavior = new Pref("editor.rectSelectModifier", SelectionModifierBehavior.Difference); - internal Pref m_ExtrudeEdgesAsGroup = new Pref("editor.extrudeEdgesAsGroup", true); Pref m_SelectMode = new Pref("editor.selectMode", SelectMode.Object); internal static Pref s_HandleOrientation = new Pref("editor.handleAlignment", HandleOrientation.World); @@ -883,9 +881,6 @@ void VertexMoveTool() OnBeginVertexMovement(); - if (Event.current.modifiers == EventModifiers.Shift) - ShiftExtrude(); - ProGridsInterface.OnHandleMove(mask); } @@ -937,9 +932,6 @@ void VertexScaleTool() OnBeginVertexMovement(); - if (Event.current.modifiers == EventModifiers.Shift) - ShiftExtrude(); - // cache vertex positions for scaling later m_VertexPositions = new Vector3[selection.Length][]; m_VertexOffset = new Vector3[selection.Length]; @@ -1071,9 +1063,6 @@ void VertexRotateTool() OnBeginVertexMovement(); - if (Event.current.modifiers == EventModifiers.Shift) - ShiftExtrude(); - // cache vertex positions for modifying later m_VertexPositions = new Vector3[selection.Length][]; m_VertexOffset = new Vector3[selection.Length]; @@ -1136,59 +1125,6 @@ void VertexRotateTool() } #pragma warning restore 612 - /// - /// Extrude the current selection with no translation. - /// - void ShiftExtrude() - { - int ef = 0; - foreach (ProBuilderMesh pb in selection) - { - Undo.RegisterCompleteObjectUndo(selection, "Extrude Vertices"); - - switch (selectMode) - { - case SelectMode.Edge: - if (pb.selectedFaceCount > 0) - goto default; - - Edge[] newEdges = pb.Extrude(pb.selectedEdges, - 0.0001f, - m_ExtrudeEdgesAsGroup, - s_AllowNonManifoldActions); - - if (newEdges != null) - { - ef += newEdges.Length; - pb.SetSelectedEdges(newEdges); - } - break; - - default: - int len = pb.selectedFacesInternal.Length; - - if (len > 0) - { - pb.Extrude(pb.selectedFacesInternal, m_ExtrudeMethod, - 0.0001f); - pb.SetSelectedFaces(pb.selectedFacesInternal); - ef += len; - } - - break; - } - - pb.ToMesh(); - pb.Refresh(); - } - - if (ef > 0) - { - EditorUtility.ShowNotification("Extrude"); - UpdateSelection(); - } - } - void TextureMoveTool() { UVEditor uvEditor = UVEditor.instance; diff --git a/com.unity.probuilder/Editor/EditorCore/RotateTool.cs b/com.unity.probuilder/Editor/EditorCore/RotateTool.cs index 85fc0a549..ca68bd4b3 100644 --- a/com.unity.probuilder/Editor/EditorCore/RotateTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/RotateTool.cs @@ -46,11 +46,6 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation Apply(Matrix4x4.Rotate(m_Rotation * Quaternion.Inverse(handleRotationOrigin))); } } - - - Handles.BeginGUI(); - GUILayout.Label("Rotation: " + m_Rotation.eulerAngles); - Handles.EndGUI(); } } } \ No newline at end of file diff --git a/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs index e8d43e66e..c192e66b9 100644 --- a/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs +++ b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs @@ -51,7 +51,7 @@ internal static void DrawGizmo(Vector3 position, Quaternion rotation, float size internal static void DrawGizmo(Vector3 position, Matrix4x4 matrix, float size = -1f) { var p = matrix.MultiplyPoint3x4(position); - size = HandleUtility.GetHandleSize(p) * size < 0f ? .5f : size; + size = HandleUtility.GetHandleSize(p) * size < 0f ? .25f : size; using (var lineDrawer = new LineDrawingScope(Color.green, -1f, CompareFunction.Always)) { diff --git a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs index 68b21ec63..04620bba4 100644 --- a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs @@ -2,6 +2,8 @@ using System.Linq; using UnityEngine; using UnityEngine.ProBuilder; +using UnityEngine.ProBuilder.MeshOperations; + #if DEBUG_HANDLES using UnityEngine.Rendering; #endif @@ -65,7 +67,6 @@ public Matrix4x4 inverseMatrix public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List groups) { - Matrix4x4 postApplyPositionsMatrix; var trs = mesh.transform.localToWorldMatrix; switch (pivot) @@ -73,37 +74,105 @@ public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List< case PivotPoint.ModelBoundingBoxCenter: { var bounds = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); - postApplyPositionsMatrix = Matrix4x4.TRS(trs.MultiplyPoint3x4(bounds.center), mesh.transform.rotation, Vector3.one); + var post = Matrix4x4.TRS(trs.MultiplyPoint3x4(bounds.center), mesh.transform.rotation, Vector3.one); + + groups.Add(new ElementGroup() + { + m_Indices = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal), + m_PostApplyPositionsMatrix = post, + m_PreApplyPositionsMatrix = post.inverse + }); + break; } case PivotPoint.IndividualOrigins: { - var bounds = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); - var ntb = Math.NormalTangentBitangent(mesh, mesh.selectedFacesInternal[0]); - var rot = mesh.transform.rotation * Quaternion.LookRotation(ntb.normal, ntb.bitangent); - postApplyPositionsMatrix = Matrix4x4.TRS(trs.MultiplyPoint3x4(bounds.center), rot, Vector3.one); + if (ProBuilderEditor.selectMode != SelectMode.Face) + goto case PivotPoint.ModelBoundingBoxCenter; + + foreach (var list in GetFaceSelectionGroups(mesh)) + { + var bounds = Math.GetBounds(mesh.positionsInternal, list); + var ntb = Math.NormalTangentBitangent(mesh, list[0]); + var rot = mesh.transform.rotation * Quaternion.LookRotation(ntb.normal, ntb.bitangent); + var post = Matrix4x4.TRS(trs.MultiplyPoint3x4(bounds.center), rot, Vector3.one); + + var indices = new List(); + mesh.GetCoincidentVertices(list, indices); + + groups.Add(new ElementGroup() + { + m_Indices = indices, + m_PostApplyPositionsMatrix = post, + m_PreApplyPositionsMatrix = post.inverse + }); + } break; } default: { - postApplyPositionsMatrix = Matrix4x4.Translate(MeshSelection.GetHandlePosition()); + var post = Matrix4x4.Translate(MeshSelection.GetHandlePosition()); + + groups.Add(new ElementGroup() + { + m_Indices = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal), + m_PostApplyPositionsMatrix = Matrix4x4.Translate(MeshSelection.GetHandlePosition()), + m_PreApplyPositionsMatrix = post.inverse + }); + break; } } + } - groups.Add(new ElementGroup() + internal static List> GetFaceSelectionGroups(ProBuilderMesh mesh) + { + var wings = WingedEdge.GetWingedEdges(mesh, mesh.selectedFacesInternal, true); + var filter = new HashSet(); + var groups = new List>(); + + foreach (var wing in wings) { - m_Indices = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal), - m_PostApplyPositionsMatrix = postApplyPositionsMatrix, - m_PreApplyPositionsMatrix = postApplyPositionsMatrix.inverse - }); + if (!filter.Add(wing.face)) + continue; + + var group = new List() { wing.face }; + CollectAdjacentFaces(wing, filter, group); + groups.Add(group); + } + + return groups; + } + + static void CollectAdjacentFaces(WingedEdge wing, HashSet filter, List group) + { + var enumerator = new WingedEdgeEnumerator(wing); + + while (enumerator.MoveNext()) + { + var cur = enumerator.Current.opposite; + + if (cur == null) + continue; + + var face = cur.face; + + if (!filter.Add(face)) + continue; + + group.Add(face); + CollectAdjacentFaces(enumerator.Current, filter, group); + } } } abstract class VertexManipulationTool { + internal static Pref s_ExtrudeEdgesAsGroup = new Pref("editor.extrudeEdgesAsGroup", true); + internal static Pref s_ExtrudeMethod = new Pref("editor.extrudeMethod", ExtrudeMethod.FaceNormal); + Vector3 m_HandlePosition; Quaternion m_HandleRotation; @@ -111,6 +180,8 @@ abstract class VertexManipulationTool Quaternion m_HandleRotationOrigin; protected Quaternion handleRotationOriginInverse { get; private set; } + protected Event currentEvent { get; private set; } + protected PivotPoint pivotPoint { get; private set; } protected Vector3 handlePositionOrigin @@ -129,12 +200,11 @@ protected Quaternion handleRotationOrigin public void OnSceneGUI(Event evt) { + currentEvent = evt; + if (evt.type == EventType.MouseUp || evt.type == EventType.Ignore) FinishEdit(); - if (evt.alt) - return; - if (Tools.pivotMode == PivotMode.Center) pivotPoint = PivotPoint.WorldBoundingBoxCenter; else if(ProBuilderEditor.handleOrientation == HandleOrientation.Normal) @@ -189,6 +259,9 @@ protected void BeginEdit() if (m_IsEditing) return; + if (currentEvent.shift) + Extrude(); + m_IsEditing = true; m_HandlePositionOrigin = m_HandlePosition; @@ -200,9 +273,7 @@ protected void BeginEdit() m_Selection.Clear(); foreach (var mesh in MeshSelection.topInternal) - { m_Selection.Add(new MeshAndElementSelection(mesh, pivotPoint)); - } } protected void FinishEdit() @@ -241,5 +312,58 @@ protected void Apply(Matrix4x4 delta) ProBuilderEditor.UpdateMeshHandles(false); } + + static void Extrude() + { + int ef = 0; + + var selection = MeshSelection.topInternal; + var selectMode = ProBuilderEditor.selectMode; + + UndoUtility.RecordSelection("Extrude Vertices"); + + foreach (var mesh in selection) + { + switch (selectMode) + { + case SelectMode.Edge: + if (mesh.selectedFaceCount > 0) + goto default; + + Edge[] newEdges = mesh.Extrude(mesh.selectedEdges, + 0.0001f, + s_ExtrudeEdgesAsGroup, + ProBuilderEditor.s_AllowNonManifoldActions); + + if (newEdges != null) + { + ef += newEdges.Length; + mesh.SetSelectedEdges(newEdges); + } + break; + + default: + int len = mesh.selectedFacesInternal.Length; + + if (len > 0) + { + mesh.Extrude(mesh.selectedFacesInternal, s_ExtrudeMethod, 0.0001f); + mesh.SetSelectedFaces(mesh.selectedFacesInternal); + ef += len; + } + + break; + } + + mesh.ToMesh(); + mesh.Refresh(); + } + + if (ef > 0) + { + EditorUtility.ShowNotification("Extrude"); + ProBuilderEditor.Refresh(); + } + } } } diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeEdges.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeEdges.cs index 7c8e78c84..067ba3b7e 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeEdges.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeEdges.cs @@ -46,7 +46,7 @@ protected override void OnSettingsGUI() EditorGUI.BeginChangeCheck(); - ProBuilderEditor.instance.m_ExtrudeEdgesAsGroup.value = EditorGUILayout.Toggle("As Group", ProBuilderEditor.instance.m_ExtrudeEdgesAsGroup); + VertexManipulationTool.s_ExtrudeEdgesAsGroup.value = EditorGUILayout.Toggle("As Group", VertexManipulationTool.s_ExtrudeEdgesAsGroup); m_ExtrudeEdgeDistance.value = EditorGUILayout.FloatField("Distance", m_ExtrudeEdgeDistance); @@ -81,7 +81,7 @@ public override ActionResult DoAction() Edge[] newEdges = pb.Extrude(pb.selectedEdges, m_ExtrudeEdgeDistance, - ProBuilderEditor.instance.m_ExtrudeEdgesAsGroup, + VertexManipulationTool.s_ExtrudeEdgesAsGroup, ProBuilderEditor.s_AllowNonManifoldActions); success |= newEdges != null; diff --git a/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeFaces.cs b/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeFaces.cs index df5a6cddc..065a7116d 100644 --- a/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeFaces.cs +++ b/com.unity.probuilder/Editor/MenuActions/Geometry/ExtrudeFaces.cs @@ -11,8 +11,8 @@ sealed class ExtrudeFaces : MenuAction ExtrudeMethod extrudeMethod { - get { return ProBuilderEditor.instance.m_ExtrudeMethod; } - set { ProBuilderEditor.instance.m_ExtrudeMethod.value = value; } + get { return VertexManipulationTool.s_ExtrudeMethod; } + set { VertexManipulationTool.s_ExtrudeMethod.value = value; } } static string GetExtrudeIconString(ExtrudeMethod m) @@ -126,7 +126,7 @@ public override ActionResult DoAction() var selectedFaces = mesh.GetSelectedFaces(); mesh.Extrude(selectedFaces, - ProBuilderEditor.instance.m_ExtrudeMethod, + VertexManipulationTool.s_ExtrudeMethod, m_ExtrudeDistance); mesh.SetSelectedFaces(selectedFaces); diff --git a/com.unity.probuilder/Runtime/Core/Math.cs b/com.unity.probuilder/Runtime/Core/Math.cs index bb8d4cab7..f63f9abb5 100644 --- a/com.unity.probuilder/Runtime/Core/Math.cs +++ b/com.unity.probuilder/Runtime/Core/Math.cs @@ -979,6 +979,45 @@ internal static Bounds GetBounds(Vector3[] positions, int[] indices = null) return new Bounds((min+max) * .5f, max - min); } + /// + /// Creates an AABB with a set of vertices. + /// + /// + /// + internal static Bounds GetBounds(Vector3[] positions, IEnumerable faces) + { + bool initialized = false; + + Vector3 min = Vector3.zero; + Vector3 max = min; + + foreach (var face in faces) + { + var indices = face.distinctIndexesInternal; + + if (!initialized) + { + initialized = true; + min = positions[indices[0]]; + max = positions[indices[0]]; + } + + for(int i = 0, c = indices.Length; i < c; i++) + { + min.x = Mathf.Min(positions[indices[i]].x, min.x); + max.x = Mathf.Max(positions[indices[i]].x, max.x); + + min.y = Mathf.Min(positions[indices[i]].y, min.y); + max.y = Mathf.Max(positions[indices[i]].y, max.y); + + min.z = Mathf.Min(positions[indices[i]].z, min.z); + max.z = Mathf.Max(positions[indices[i]].z, max.z); + } + } + + return new Bounds((min+max) * .5f, max - min); + } + /// /// Gets the average of a vector array. /// diff --git a/com.unity.probuilder/Runtime/Core/MeshHandle.cs b/com.unity.probuilder/Runtime/Core/MeshHandle.cs index eb521c99d..503780765 100644 --- a/com.unity.probuilder/Runtime/Core/MeshHandle.cs +++ b/com.unity.probuilder/Runtime/Core/MeshHandle.cs @@ -21,6 +21,9 @@ public MeshHandle(Transform transform, Mesh mesh) public void DrawMeshNow(int submeshIndex) { + if (m_Transform == null || m_Mesh == null) + return; + Graphics.DrawMeshNow(m_Mesh, m_Transform.localToWorldMatrix, submeshIndex); } } diff --git a/com.unity.probuilder/Runtime/Core/ProBuilderMeshFunction.cs b/com.unity.probuilder/Runtime/Core/ProBuilderMeshFunction.cs index 2304a96f8..dd788ce62 100644 --- a/com.unity.probuilder/Runtime/Core/ProBuilderMeshFunction.cs +++ b/com.unity.probuilder/Runtime/Core/ProBuilderMeshFunction.cs @@ -459,6 +459,40 @@ public List GetCoincidentVertices(IEnumerable vertices) return shared; } + /// + /// Populate a list of vertices that are coincident to any of the vertices in the passed vertices parameter. + /// + /// A collection of faces to gather vertices from. + /// A list to be cleared and populated with any vertices that are coincident. + /// The vertices and coincident parameters may not be null. + public void GetCoincidentVertices(IEnumerable faces, List coincident) + { + if (faces == null) + throw new ArgumentNullException("faces"); + + if (coincident == null) + throw new ArgumentNullException("coincident"); + + s_CachedHashSet.Clear(); + var lookup = sharedVertexLookup; + + foreach(var face in faces) + { + foreach (var v in face.distinctIndexesInternal) + { + var common = lookup[v]; + + if (s_CachedHashSet.Add(common)) + { + var indices = m_SharedVertices[common]; + + for (int i = 0, c = indices.Count; i < c; i++) + coincident.Add(indices[i]); + } + } + } + } + /// /// Populate a list of vertices that are coincident to any of the vertices in the passed vertices parameter. /// diff --git a/com.unity.probuilder/Runtime/Core/WingedEdge.cs b/com.unity.probuilder/Runtime/Core/WingedEdge.cs index eec7cc3e2..963323285 100644 --- a/com.unity.probuilder/Runtime/Core/WingedEdge.cs +++ b/com.unity.probuilder/Runtime/Core/WingedEdge.cs @@ -331,12 +331,11 @@ public static List GetWingedEdges(ProBuilderMesh mesh, IEnumerable distinct = faces.Distinct(); List winged = new List(); Dictionary opposites = new Dictionary(); - foreach (Face f in distinct) + foreach (Face f in faces) { List edges = SortEdgesByAdjacency(f); int edgeLength = edges.Count; From 85d6fbceb7c9ed80990245e7730d6d8a0ad3fe39 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Thu, 25 Oct 2018 15:56:58 -0400 Subject: [PATCH 15/27] support vertex snapping in move tool --- .../Editor/EditorCore/MoveTool.cs | 25 +- .../Editor/EditorCore/ProBuilderEditor.cs | 828 +++++------------- .../Editor/EditorCore/ProBuilderMeshEditor.cs | 10 +- .../Editor/EditorCore/RotateTool.cs | 4 +- .../Editor/EditorCore/ScaleTool.cs | 2 +- .../Editor/EditorCore/SmoothGroupEditor.cs | 4 +- .../EditorCore/StaticEditorMeshHandles.cs | 21 +- .../EditorCore/VertexManipulationTool.cs | 135 ++- .../Runtime/Core/InternalUtility.cs | 2 +- 9 files changed, 414 insertions(+), 617 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs index 695aeec21..095d8e770 100644 --- a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs @@ -5,6 +5,7 @@ namespace UnityEditor.ProBuilder { class MoveTool : VertexManipulationTool { + const float k_CardinalAxisError = .001f; Vector3 m_HandlePosition; Matrix4x4 m_Translation = Matrix4x4.identity; @@ -20,10 +21,32 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation if (EditorGUI.EndChangeCheck()) { if (!m_IsEditing) - BeginEdit(); + BeginEdit("Translate Selection"); var delta = m_HandlePosition - handlePositionOrigin; + if (vertexDragging) + { + Vector3 nearest; + + if (FindNearestVertex(currentEvent.mousePosition, out nearest)) + { + var unrotated = handleRotationOriginInverse * delta; + var dir = Math.ToMask(unrotated, k_CardinalAxisError); + + if (dir.IntSum() == 1) + { + var rot_dir = handleRotationOrigin * dir * 1000f; + + m_HandlePosition = HandleUtility.ProjectPointLine(nearest, + handlePositionOrigin + rot_dir, + handlePositionOrigin - rot_dir); + + delta = m_HandlePosition - handlePositionOrigin; + } + } + } + switch (pivotPoint) { case PivotPoint.WorldBoundingBoxCenter: diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index 9faaa010b..e8ed99ce3 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -27,16 +27,6 @@ public sealed class ProBuilderEditor : EditorWindow, IHasCustomMenu /// public static event Action selectionUpdated; - /// - /// Called when vertex modifications are complete. - /// - public static event Action afterMeshModification; - - /// - /// Called immediately prior to beginning vertex modifications. The ProBuilderMesh will be in un-altered state at this point (meaning ProBuilderMesh.ToMesh and ProBuilderMesh.Refresh have been called, but not Optimize). - /// - public static event Action beforeMeshModification; - /// /// Raised when the EditLevel is changed. /// @@ -111,11 +101,7 @@ internal static HandleOrientation handleOrientation value = HandleOrientation.Normal; s_HandleOrientation.SetValue(value, true); - - if(instance != null) - instance.m_HandleRotation = MeshSelection.GetHandleRotation(s_HandleOrientation); } - } internal bool backfaceSelectionEnabled @@ -132,10 +118,6 @@ internal bool backfaceSelectionEnabled } } - float m_SnapValue = .25f; - bool m_SnapAxisConstraint = true; - bool m_SnapEnabled; - MethodInfo m_FindNearestVertex; // used for 'g' key shortcut to swap between object/vef modes SelectMode m_LastComponentMode; HandleOrientation m_PreviousHandleOrientation; @@ -160,40 +142,15 @@ internal bool backfaceSelectionEnabled // prevents leftClickUp from stealing focus after double click bool m_WasDoubleClick; // vertex handles - Vector3 m_ElementHandlePosition; - Vector3 m_ElementHandleCachedPosition; - bool m_IsMovingElements; bool m_IsRightMouseDown; - bool m_DoSnapToVertex; - bool m_DoSnapToFace; - Vector3 m_HandleScalePrevious = Vector3.one; - Vector3 m_HandleScale = Vector3.one; Vector3[][] m_VertexPositions; Vector3[] m_VertexOffset; - Quaternion m_HandleRotationPrevious = Quaternion.identity; - Quaternion m_HandleRotation = Quaternion.identity; - Quaternion m_RotationInitial; - Quaternion m_RotationInitialInverse; GUIContent m_SceneInfo = new GUIContent(); - // Use for delta display - Vector3 m_TranslateOrigin = Vector3.zero; - Vector3 m_RotateOrigin = Vector3.zero; - Vector3 m_ScaleOrigin = Vector3.zero; - - Vector3 m_TextureHandlePosition = Vector3.zero; - Vector3 m_TextureHandlePositionPrevious = Vector3.zero; - bool m_IsMovingTextures; - Quaternion m_TextureRotation = Quaternion.identity; - Vector3 m_TextureScale = Vector3.one; Rect m_SceneInfoRect = new Rect(10, 10, 200, 40); - Vector3 m_HandlePosition = Vector3.zero; - - Matrix4x4 handleMatrix = Matrix4x4.identity; - #if !UNITY_2018_2_OR_NEWER static MethodInfo s_ResetOnSceneGUIState = null; #endif @@ -371,9 +328,6 @@ void OnEnable() UpdateSelection(); HideSelectedWireframe(); - m_FindNearestVertex = typeof(HandleUtility).GetMethod("FindNearestVertex", - BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance); - if (selectModeChanged != null) selectModeChanged(selectMode); } @@ -434,10 +388,6 @@ void LoadSettings() // workaround for old single-key shortcuts if(s_Shortcuts.value == null || s_Shortcuts.value.Length < 1) s_Shortcuts.SetValue(Shortcut.DefaultShortcuts().ToArray(), true); - - m_SnapEnabled = ProGridsInterface.SnapEnabled(); - m_SnapValue = ProGridsInterface.SnapValue(); - m_SnapAxisConstraint = ProGridsInterface.UseAxisConstraints(); } void InitGUI() @@ -571,20 +521,20 @@ void OnSceneGUI(SceneView sceneView) m_CurrentEvent = Event.current; - if(selectMode.ContainsFlag(SelectMode.Face | SelectMode.Edge | SelectMode.Vertex)) - { - if (m_CurrentEvent.Equals(Event.KeyboardEvent("v"))) - m_DoSnapToVertex = true; - else if (m_CurrentEvent.Equals(Event.KeyboardEvent("c"))) - m_DoSnapToFace = true; - } +// if(selectMode.ContainsFlag(SelectMode.Face | SelectMode.Edge | SelectMode.Vertex)) +// { +// if (m_CurrentEvent.Equals(Event.KeyboardEvent("v"))) +// m_DoSnapToVertex = true; +// else if (m_CurrentEvent.Equals(Event.KeyboardEvent("c"))) +// m_DoSnapToFace = true; +// } // Snap stuff - if (m_CurrentEvent.type == EventType.KeyUp) - { - m_DoSnapToFace = false; - m_DoSnapToVertex = false; - } +// if (m_CurrentEvent.type == EventType.KeyUp) +// { +// m_DoSnapToFace = false; +// m_DoSnapToVertex = false; +// } if (m_CurrentEvent.type == EventType.MouseDown && m_CurrentEvent.button == 1) m_IsRightMouseDown = true; @@ -613,14 +563,14 @@ void OnSceneGUI(SceneView sceneView) if (selectMode == SelectMode.Object) return; - - // Finished moving vertices, scaling, or adjusting uvs - if ((m_IsMovingElements || m_IsMovingTextures) && GUIUtility.hotControl < 1) - { - OnFinishVertexModification(); - m_HandleRotation = MeshSelection.GetHandleRotation(s_HandleOrientation); - UpdateTextureHandles(); - } +// +// // Finished moving vertices, scaling, or adjusting uvs +// if ((m_IsMovingElements || m_IsMovingTextures) && GUIUtility.hotControl < 1) +// { +// OnFinishVertexModification(); +// m_HandleRotation = MeshSelection.GetHandleRotation(s_HandleOrientation); +// UpdateTextureHandles(); +// } // Check mouse position in scene and determine if we should highlight something if (s_ShowHoverHighlight @@ -811,402 +761,197 @@ void VertexMoveTool() s_MoveTool.OnSceneGUI(Event.current); return; - - if (!m_IsMovingElements) - m_ElementHandlePosition = m_HandlePosition; - - m_ElementHandleCachedPosition = m_ElementHandlePosition; - - m_ElementHandlePosition = Handles.PositionHandle(m_ElementHandlePosition, m_HandleRotation); - - if (m_CurrentEvent.alt) - return; - - if (m_ElementHandlePosition != m_ElementHandleCachedPosition) - { - Vector3 diff = m_ElementHandlePosition - m_ElementHandleCachedPosition; - - Vector3 mask = diff.ToMask(Math.handleEpsilon); - - if (m_DoSnapToVertex) - { - Vector3 v; - - if (FindNearestVertex(m_CurrentEvent.mousePosition, out v)) - diff = Vector3.Scale(v - m_ElementHandleCachedPosition, mask); - } - else if (m_DoSnapToFace) - { - ProBuilderMesh obj = null; - RaycastHit hit; - Dictionary> ignore = new Dictionary>(); - foreach (ProBuilderMesh pb in selection) - ignore.Add(pb, new HashSet(pb.selectedFacesInternal)); - - if (EditorHandleUtility.FaceRaycast(m_CurrentEvent.mousePosition, out obj, out hit, ignore)) - { - if (mask.IntSum() == 1) - { - Ray r = new Ray(m_ElementHandleCachedPosition, -mask); - Plane plane = new Plane(obj.transform.TransformDirection(hit.normal).normalized, - obj.transform.TransformPoint(hit.point)); - - float forward, backward; - plane.Raycast(r, out forward); - plane.Raycast(r, out backward); - float planeHit = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; - r.direction = -r.direction; - plane.Raycast(r, out forward); - plane.Raycast(r, out backward); - float rev = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; - if (Mathf.Abs(rev) > Mathf.Abs(planeHit)) - planeHit = rev; - - if (Mathf.Abs(planeHit) > Mathf.Epsilon) - diff = mask * -planeHit; - } - else - { - diff = Vector3.Scale(obj.transform.TransformPoint(hit.point) - m_ElementHandleCachedPosition, mask.Abs()); - } - } - } - - if (!m_IsMovingElements) - { - m_IsMovingElements = true; - m_TranslateOrigin = m_ElementHandleCachedPosition; - m_RotateOrigin = m_HandleRotation.eulerAngles; - m_ScaleOrigin = m_HandleScale; - - OnBeginVertexMovement(); - - ProGridsInterface.OnHandleMove(mask); - } - - for (int i = 0; i < selection.Length; i++) - { - var mesh = selection[i]; - - mesh.TranslateVerticesInWorldSpace(mesh.selectedIndexesInternal, - diff, - m_SnapEnabled ? m_SnapValue : 0f, - m_SnapAxisConstraint); - - mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); - mesh.Refresh(RefreshMask.Normals); - mesh.mesh.RecalculateBounds(); - } - - UpdateMeshHandles(false); - } +// +// if (!m_IsMovingElements) +// m_ElementHandlePosition = m_HandlePosition; +// +// m_ElementHandleCachedPosition = m_ElementHandlePosition; +// +// m_ElementHandlePosition = Handles.PositionHandle(m_ElementHandlePosition, m_HandleRotation); +// +// if (m_CurrentEvent.alt) +// return; +// +// if (m_ElementHandlePosition != m_ElementHandleCachedPosition) +// { +// Vector3 diff = m_ElementHandlePosition - m_ElementHandleCachedPosition; +// +// Vector3 mask = diff.ToMask(Math.handleEpsilon); +// +// if (m_DoSnapToVertex) +// { +// Vector3 v; +// +// if (FindNearestVertex(m_CurrentEvent.mousePosition, out v)) +// diff = Vector3.Scale(v - m_ElementHandleCachedPosition, mask); +// } +// else if (m_DoSnapToFace) +// { +// ProBuilderMesh obj = null; +// RaycastHit hit; +// Dictionary> ignore = new Dictionary>(); +// foreach (ProBuilderMesh pb in selection) +// ignore.Add(pb, new HashSet(pb.selectedFacesInternal)); +// +// if (EditorHandleUtility.FaceRaycast(m_CurrentEvent.mousePosition, out obj, out hit, ignore)) +// { +// if (mask.IntSum() == 1) +// { +// Ray r = new Ray(m_ElementHandleCachedPosition, -mask); +// Plane plane = new Plane(obj.transform.TransformDirection(hit.normal).normalized, +// obj.transform.TransformPoint(hit.point)); +// +// float forward, backward; +// plane.Raycast(r, out forward); +// plane.Raycast(r, out backward); +// float planeHit = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; +// r.direction = -r.direction; +// plane.Raycast(r, out forward); +// plane.Raycast(r, out backward); +// float rev = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; +// if (Mathf.Abs(rev) > Mathf.Abs(planeHit)) +// planeHit = rev; +// +// if (Mathf.Abs(planeHit) > Mathf.Epsilon) +// diff = mask * -planeHit; +// } +// else +// { +// diff = Vector3.Scale(obj.transform.TransformPoint(hit.point) - m_ElementHandleCachedPosition, mask.Abs()); +// } +// } +// } +// +// if (!m_IsMovingElements) +// { +// m_IsMovingElements = true; +// m_TranslateOrigin = m_ElementHandleCachedPosition; +// m_RotateOrigin = m_HandleRotation.eulerAngles; +// m_ScaleOrigin = m_HandleScale; +// +// OnBeginVertexMovement(); +// +// ProGridsInterface.OnHandleMove(mask); +// } +// +// for (int i = 0; i < selection.Length; i++) +// { +// var mesh = selection[i]; +// +// mesh.TranslateVerticesInWorldSpace(mesh.selectedIndexesInternal, +// diff, +// m_SnapEnabled ? m_SnapValue : 0f, +// m_SnapAxisConstraint); +// +// mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); +// mesh.Refresh(RefreshMask.Normals); +// mesh.mesh.RecalculateBounds(); +// } +// +// UpdateMeshHandles(false); +// } } void VertexScaleTool() { if (m_ScaleTool == null) m_ScaleTool = new ScaleTool(); - m_ScaleTool.OnSceneGUI(Event.current); - - return; - - m_ElementHandlePosition = m_HandlePosition; - - m_HandleScalePrevious = m_HandleScale; - - m_HandleScale = Handles.ScaleHandle(m_HandleScale, m_ElementHandlePosition, m_HandleRotation, - HandleUtility.GetHandleSize(m_ElementHandlePosition)); - - if (m_CurrentEvent.alt) return; - - bool previouslyMoving = m_IsMovingElements; - if (m_HandleScalePrevious != m_HandleScale) - { - m_IsMovingElements = true; - if (previouslyMoving == false) - { - m_TranslateOrigin = m_ElementHandleCachedPosition; - m_RotateOrigin = m_HandleRotation.eulerAngles; - m_ScaleOrigin = m_HandleScale; - - OnBeginVertexMovement(); - - // cache vertex positions for scaling later - m_VertexPositions = new Vector3[selection.Length][]; - m_VertexOffset = new Vector3[selection.Length]; - - for (int i = 0; i < selection.Length; i++) - { - m_VertexPositions[i] = selection[i].positionsInternal.ValuesWithIndexes(selection[i].selectedIndexesInternal); - m_VertexOffset[i] = Math.Average(m_VertexPositions[i]); - } - } - - Vector3 ver; // resulting vertex from modification - Vector3 over; // vertex point to modify. different for world, local, and plane - - bool gotoWorld = Selection.transforms.Length > 1 && s_HandleOrientation == HandleOrientation.Normal; - bool gotoLocal = MeshSelection.selectedFaceCount < 1; - - // if(pref_snapEnabled) - // pbUndo.RecordSelection(selection as Object[], "Move vertices"); - - for (int i = 0; i < selection.Length; i++) - { - // get the plane rotation in local space - var mesh = selection[i]; - Vector3 nrm = Math.Normal(m_VertexPositions[i]); - Quaternion localRot = Quaternion.LookRotation(nrm == Vector3.zero ? Vector3.forward : nrm, Vector3.up); - - Vector3[] v = mesh.positionsInternal; - List coincident = new List(); - - for (int n = 0; n < mesh.selectedIndexesInternal.Length; n++) - { - switch (s_HandleOrientation.value) - { - case HandleOrientation.Normal: - { - if (gotoWorld) - goto case HandleOrientation.World; - - if (gotoLocal) - goto case HandleOrientation.Local; - - // move center of vertices to 0,0,0 and set rotation as close to identity as possible - over = Quaternion.Inverse(localRot) * (m_VertexPositions[i][n] - m_VertexOffset[i]); - - // apply scale - ver = Vector3.Scale(over, m_HandleScale); - - // re-apply original rotation - if (m_VertexPositions[i].Length > 2) - ver = localRot * ver; - - // re-apply world position offset - ver += m_VertexOffset[i]; - - coincident.Clear(); - mesh.GetCoincidentVertices(mesh.selectedIndexesInternal[n], coincident); - - for (int t = 0, c = coincident.Count; t < c; t++) - v[coincident[t]] = ver; - - break; - } - - case HandleOrientation.World: - case HandleOrientation.Local: - { - // move vertex to relative origin from center of selection - over = m_VertexPositions[i][n] - m_VertexOffset[i]; - // apply scale - ver = Vector3.Scale(over, m_HandleScale); - // move vertex back to locally offset position - ver += m_VertexOffset[i]; - - // set vertex in local space on pb-Object - coincident.Clear(); - mesh.GetCoincidentVertices(mesh.selectedIndexesInternal[n], coincident); - - for (int t = 0, c = coincident.Count; t < c; t++) - v[coincident[t]] = ver; - - break; - } - } - } - - mesh.mesh.vertices = v; - mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[selection[i]]); - mesh.Refresh(RefreshMask.Normals); - mesh.mesh.RecalculateBounds(); - } - - UpdateMeshHandles(false); - } + m_ScaleTool.OnSceneGUI(Event.current); } void VertexRotateTool() { - if(s_RotateTool == null) + if (s_RotateTool == null) s_RotateTool = new RotateTool(); s_RotateTool.OnSceneGUI(Event.current); - - return; - - if (!m_IsMovingElements) - m_ElementHandlePosition = m_HandlePosition; - - m_HandleRotationPrevious = m_HandleRotation; - - if (m_CurrentEvent.alt) - Handles.RotationHandle(m_HandleRotation, m_ElementHandlePosition); - else - m_HandleRotation = Handles.RotationHandle(m_HandleRotation, m_ElementHandlePosition); - - if (m_HandleRotation != m_HandleRotationPrevious) - { - // profiler.BeginSample("Rotate"); - if (!m_IsMovingElements) - { - m_IsMovingElements = true; - - m_TranslateOrigin = m_ElementHandleCachedPosition; - m_RotateOrigin = m_HandleRotation.eulerAngles; - m_ScaleOrigin = m_HandleScale; - - m_RotationInitial = m_HandleRotationPrevious; - m_RotationInitialInverse = Quaternion.Inverse(m_HandleRotationPrevious); - - OnBeginVertexMovement(); - - // cache vertex positions for modifying later - m_VertexPositions = new Vector3[selection.Length][]; - m_VertexOffset = new Vector3[selection.Length]; - - for (int i = 0; i < selection.Length; i++) - { - Vector3[] vertices = selection[i].positionsInternal; - int[] triangles = selection[i].selectedIndexesInternal; - m_VertexPositions[i] = new Vector3[triangles.Length]; - - for (int nn = 0; nn < triangles.Length; nn++) - m_VertexPositions[i][nn] = selection[i].transform.TransformPoint(vertices[triangles[nn]]); - - if (s_HandleOrientation == HandleOrientation.World) - m_VertexOffset[i] = m_ElementHandlePosition; - else - m_VertexOffset[i] = Math.GetBounds(m_VertexPositions[i]).center; - } - } - - // profiler.BeginSample("Calc Matrix"); - Quaternion transformedRotation = m_RotationInitialInverse * m_HandleRotation; - List coincident = new List(); - - // profiler.BeginSample("matrix mult"); - for (int i = 0; i < selection.Length; i++) - { - Vector3[] v = selection[i].positionsInternal; - SharedVertex[] sharedIndexes = selection[i].sharedVerticesInternal; - - Quaternion lr = m_RotationInitial; // selection[0].transform.localRotation; - Quaternion ilr = m_RotationInitialInverse; // Quaternion.Inverse(lr); - - for (int n = 0; n < selection[i].selectedIndexesInternal.Length; n++) - { - // move vertex to relative origin from center of selection - Vector3 ver = ilr * (m_VertexPositions[i][n] - m_VertexOffset[i]); - - // rotate - ver = transformedRotation * ver; - - // move vertex back to locally offset position - ver = (lr * ver) + m_VertexOffset[i]; - - coincident.Clear(); - selection[i].GetCoincidentVertices(selection[i].selectedIndexesInternal[n], coincident); - - for (int t = 0, c = coincident.Count; t < c; t++) - v[coincident[t]] = selection[i].transform.InverseTransformPoint(ver); - } - - selection[i].mesh.vertices = v; - selection[i].RefreshUV(MeshSelection.selectedFacesInEditZone[selection[i]]); - selection[i].Refresh(RefreshMask.Normals); - selection[i].mesh.RecalculateBounds(); - } - - UpdateMeshHandles(false); - } } + #pragma warning restore 612 void TextureMoveTool() { - UVEditor uvEditor = UVEditor.instance; - if (!uvEditor) return; - - Vector3 cached = m_TextureHandlePosition; - - m_TextureHandlePosition = Handles.PositionHandle(m_TextureHandlePosition, m_HandleRotation); - - if (m_CurrentEvent.alt) return; - - if (m_TextureHandlePosition != cached) - { - cached = Quaternion.Inverse(m_HandleRotation) * m_TextureHandlePosition; - cached.y = -cached.y; - - Vector3 lossyScale = selection[0].transform.lossyScale; - Vector3 pos = cached.DivideBy(lossyScale); - - if (!m_IsMovingTextures) - { - m_TextureHandlePositionPrevious = pos; - m_IsMovingTextures = true; - } - - uvEditor.SceneMoveTool(pos - m_TextureHandlePositionPrevious); - m_TextureHandlePositionPrevious = pos; - uvEditor.Repaint(); - } +// UVEditor uvEditor = UVEditor.instance; +// if (!uvEditor) return; +// +// Vector3 cached = m_TextureHandlePosition; +// +// m_TextureHandlePosition = Handles.PositionHandle(m_TextureHandlePosition, m_HandleRotation); +// +// if (m_CurrentEvent.alt) return; +// +// if (m_TextureHandlePosition != cached) +// { +// cached = Quaternion.Inverse(m_HandleRotation) * m_TextureHandlePosition; +// cached.y = -cached.y; +// +// Vector3 lossyScale = selection[0].transform.lossyScale; +// Vector3 pos = cached.DivideBy(lossyScale); +// +// if (!m_IsMovingTextures) +// { +// m_TextureHandlePositionPrevious = pos; +// m_IsMovingTextures = true; +// } +// +// uvEditor.SceneMoveTool(pos - m_TextureHandlePositionPrevious); +// m_TextureHandlePositionPrevious = pos; +// uvEditor.Repaint(); +// } } void TextureRotateTool() { - UVEditor uvEditor = UVEditor.instance; - if (!uvEditor) return; - - float size = HandleUtility.GetHandleSize(m_HandlePosition); - - if (m_CurrentEvent.alt) return; - - Matrix4x4 prev = Handles.matrix; - Handles.matrix = handleMatrix; - - Quaternion cached = m_TextureRotation; - - m_TextureRotation = Handles.Disc(m_TextureRotation, Vector3.zero, Vector3.forward, size, false, 0f); - - if (m_TextureRotation != cached) - { - if (!m_IsMovingTextures) - m_IsMovingTextures = true; - - uvEditor.SceneRotateTool(-m_TextureRotation.eulerAngles.z); - } - - Handles.matrix = prev; +// UVEditor uvEditor = UVEditor.instance; +// if (!uvEditor) return; +// +// float size = HandleUtility.GetHandleSize(m_HandlePosition); +// +// if (m_CurrentEvent.alt) return; +// +// Matrix4x4 prev = Handles.matrix; +// Handles.matrix = handleMatrix; +// +// Quaternion cached = m_TextureRotation; +// +// m_TextureRotation = Handles.Disc(m_TextureRotation, Vector3.zero, Vector3.forward, size, false, 0f); +// +// if (m_TextureRotation != cached) +// { +// if (!m_IsMovingTextures) +// m_IsMovingTextures = true; +// +// uvEditor.SceneRotateTool(-m_TextureRotation.eulerAngles.z); +// } +// +// Handles.matrix = prev; } void TextureScaleTool() { - UVEditor uvEditor = UVEditor.instance; - if (!uvEditor) return; - - float size = HandleUtility.GetHandleSize(m_HandlePosition); - - Matrix4x4 prev = Handles.matrix; - Handles.matrix = handleMatrix; - - Vector3 cached = m_TextureScale; - m_TextureScale = Handles.ScaleHandle(m_TextureScale, Vector3.zero, Quaternion.identity, size); - - if (m_CurrentEvent.alt) return; - - if (cached != m_TextureScale) - { - if (!m_IsMovingTextures) - m_IsMovingTextures = true; - - uvEditor.SceneScaleTool(m_TextureScale, cached); - } - - Handles.matrix = prev; +// UVEditor uvEditor = UVEditor.instance; +// if (!uvEditor) return; +// +// float size = HandleUtility.GetHandleSize(m_HandlePosition); +// +// Matrix4x4 prev = Handles.matrix; +// Handles.matrix = handleMatrix; +// +// Vector3 cached = m_TextureScale; +// m_TextureScale = Handles.ScaleHandle(m_TextureScale, Vector3.zero, Quaternion.identity, size); +// +// if (m_CurrentEvent.alt) return; +// +// if (cached != m_TextureScale) +// { +// if (!m_IsMovingTextures) +// m_IsMovingTextures = true; +// +// uvEditor.SceneScaleTool(m_TextureScale, cached); +// } +// +// Handles.matrix = prev; } void DrawHandleGUI(SceneView sceneView) @@ -1308,26 +1053,27 @@ void DrawHandleGUI(SceneView sceneView) selectMode = SelectMode.Face; } - if (m_IsMovingElements && s_ShowSceneInfo) - { - string handleTransformInfo = string.Format( - "translate: {0}\nrotate: {1}\nscale: {2}", - (m_ElementHandlePosition - m_TranslateOrigin).ToString(), - (m_HandleRotation.eulerAngles - m_RotateOrigin).ToString(), - (m_HandleScale - m_ScaleOrigin).ToString()); - - var gc = UI.EditorGUIUtility.TempContent(handleTransformInfo); - // sceneview screen.height includes the tab and toolbar - var toolbarHeight = EditorStyles.toolbar.CalcHeight(gc, Screen.width); - var size = UI.EditorStyles.sceneTextBox.CalcSize(gc); - - Rect handleTransformInfoRect = new Rect( - sceneView.position.width - (size.x + 8), sceneView.position.height - (size.y + 8 + toolbarHeight), - size.x, - size.y); - - GUI.Label(handleTransformInfoRect, gc, UI.EditorStyles.sceneTextBox); - } + // todo Move to VertexManipulationTool +// if (m_IsMovingElements && s_ShowSceneInfo) +// { +// string handleTransformInfo = string.Format( +// "translate: {0}\nrotate: {1}\nscale: {2}", +// (m_ElementHandlePosition - m_TranslateOrigin).ToString(), +// (m_HandleRotation.eulerAngles - m_RotateOrigin).ToString(), +// (m_HandleScale - m_ScaleOrigin).ToString()); +// +// var gc = UI.EditorGUIUtility.TempContent(handleTransformInfo); +// // sceneview screen.height includes the tab and toolbar +// var toolbarHeight = EditorStyles.toolbar.CalcHeight(gc, Screen.width); +// var size = UI.EditorStyles.sceneTextBox.CalcSize(gc); +// +// Rect handleTransformInfoRect = new Rect( +// sceneView.position.width - (size.x + 8), sceneView.position.height - (size.y + 8 + toolbarHeight), +// size.x, +// size.y); +// +// GUI.Label(handleTransformInfoRect, gc, UI.EditorStyles.sceneTextBox); +// } if (s_ShowSceneInfo) { @@ -1542,8 +1288,8 @@ void UpdateSelection(bool selectionChanged = true) // todo remove selection property selection = MeshSelection.topInternal.ToArray(); - m_HandlePosition = MeshSelection.GetHandlePosition(); - m_HandleRotation = MeshSelection.GetHandleRotation(s_HandleOrientation); +// m_HandlePosition = MeshSelection.GetHandlePosition(); +// m_HandleRotation = MeshSelection.GetHandleRotation(s_HandleOrientation); UpdateTextureHandles(); UpdateMeshHandles(selectionChanged); @@ -1601,63 +1347,34 @@ internal void ClearElementSelection() void UpdateTextureHandles() { - if (!selectMode.ContainsFlag(SelectMode.TextureFace) || !selection.Any()) - return; - - // Reset temp vars - m_TextureHandlePosition = m_HandlePosition; - m_TextureScale = Vector3.one; - m_TextureRotation = Quaternion.identity; - - ProBuilderMesh pb; - Face face; - - handleMatrix = selection[0].transform.localToWorldMatrix; - - if (GetFirstSelectedFace(out pb, out face)) - { - var normals = Math.NormalTangentBitangent(pb, face); - var nrm = normals.normal; - var bitan = normals.bitangent; - - if (nrm == Vector3.zero || bitan == Vector3.zero) - { - nrm = Vector3.up; - bitan = Vector3.right; - } - - handleMatrix *= Matrix4x4.TRS(Math.GetBounds(pb.positionsInternal.ValuesWithIndexes(face.distinctIndexesInternal)).center, - Quaternion.LookRotation(nrm, bitan), Vector3.one); - } - } - - /// - /// Find the nearest vertex among all visible objects. - /// - /// - /// - /// - bool FindNearestVertex(Vector2 mousePosition, out Vector3 vertex) - { - List t = - new List( - (Transform[]) InternalUtility.GetComponents( - HandleUtility.PickRectObjects(new Rect(0, 0, Screen.width, Screen.height)))); - - GameObject nearest = HandleUtility.PickGameObject(mousePosition, false); - - if (nearest != null) - t.Add(nearest.transform); - - object[] parameters = new object[] { (Vector2) mousePosition, t.ToArray(), null }; - - if (m_FindNearestVertex == null) - m_FindNearestVertex = typeof(HandleUtility).GetMethod("findNearestVertex", - BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance); - - object result = m_FindNearestVertex.Invoke(this, parameters); - vertex = (bool) result ? (Vector3) parameters[2] : Vector3.zero; - return (bool) result; +// if (!selectMode.ContainsFlag(SelectMode.TextureFace) || !selection.Any()) +// return; +// +// // Reset temp vars +// m_TextureHandlePosition = m_HandlePosition; +// m_TextureScale = Vector3.one; +// m_TextureRotation = Quaternion.identity; +// +// ProBuilderMesh pb; +// Face face; +// +// handleMatrix = selection[0].transform.localToWorldMatrix; +// +// if (GetFirstSelectedFace(out pb, out face)) +// { +// var normals = Math.NormalTangentBitangent(pb, face); +// var nrm = normals.normal; +// var bitan = normals.bitangent; +// +// if (nrm == Vector3.zero || bitan == Vector3.zero) +// { +// nrm = Vector3.up; +// bitan = Vector3.right; +// } +// +// handleMatrix *= Matrix4x4.TRS(Math.GetBounds(pb.positionsInternal.ValuesWithIndexes(face.distinctIndexesInternal)).center, +// Quaternion.LookRotation(nrm, bitan), Vector3.one); +// } } /// @@ -1762,81 +1479,6 @@ internal void OnBeginTextureModification() VerifyTextureGroupSelection(); } - /// - /// When beginning a vertex modification, nuke the UV2 and rebuild the mesh using PB data so that triangles - /// match vertices (and no inserted vertices from the Unwrapping.GenerateSecondaryUVSet() remain). - /// - internal void OnBeginVertexMovement() - { - switch (m_CurrentTool) - { - case Tool.Move: - UndoUtility.RegisterCompleteObjectUndo(selection, "Translate Vertices"); - break; - - case Tool.Rotate: - UndoUtility.RegisterCompleteObjectUndo(selection, "Rotate Vertices"); - break; - - case Tool.Scale: - UndoUtility.RegisterCompleteObjectUndo(selection, "Scale Vertices"); - break; - - default: - UndoUtility.RegisterCompleteObjectUndo(selection, "Modify Vertices"); - break; - } - - m_SnapEnabled = ProGridsInterface.SnapEnabled(); - m_SnapValue = ProGridsInterface.SnapValue(); - m_SnapAxisConstraint = ProGridsInterface.UseAxisConstraints(); - - // Disable iterative lightmapping - Lightmapping.PushGIWorkflowMode(); - - foreach (ProBuilderMesh pb in selection) - { - pb.ToMesh(); - pb.Refresh(); - } - - if (beforeMeshModification != null) - beforeMeshModification(selection); - } - - internal void OnFinishVertexModification() - { - Lightmapping.PopGIWorkflowMode(); - - m_HandleScale = Vector3.one; - m_HandleRotation = MeshSelection.GetHandleRotation(s_HandleOrientation); - - if (m_IsMovingTextures) - { - if (UVEditor.instance != null) - UVEditor.instance.OnFinishUVModification(); - - UpdateTextureHandles(); - m_IsMovingTextures = false; - } - else if (m_IsMovingElements) - { - foreach (ProBuilderMesh sel in selection) - { - sel.ToMesh(); - sel.Refresh(); - sel.Optimize(); - } - - m_IsMovingElements = false; - } - - UpdateSelection(); - - if (afterMeshModification != null) - afterMeshModification(selection); - } - /// /// Returns the first selected pb_Object and pb_Face, or false if not found. /// diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderMeshEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderMeshEditor.cs index 18f40edd6..c814452a3 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderMeshEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderMeshEditor.cs @@ -6,7 +6,7 @@ namespace UnityEditor.ProBuilder { /// /// - /// Custom editor for pb_Object type. + /// Custom editor for ProBuilderMesh type. /// [CustomEditor(typeof(ProBuilderMesh))] [CanEditMultipleObjects] @@ -70,14 +70,14 @@ void OnEnable() foreach (var mesh in Selection.transforms.GetComponents()) EditorUtility.SynchronizeWithMeshFilter(mesh); - ProBuilderEditor.beforeMeshModification += OnBeginMeshModification; - ProBuilderEditor.afterMeshModification += OnFinishMeshModification; + VertexManipulationTool.beforeMeshModification += OnBeginMeshModification; + VertexManipulationTool.afterMeshModification += OnFinishMeshModification; } void OnDisable() { - ProBuilderEditor.beforeMeshModification -= OnBeginMeshModification; - ProBuilderEditor.afterMeshModification -= OnFinishMeshModification; + VertexManipulationTool.beforeMeshModification -= OnBeginMeshModification; + VertexManipulationTool.afterMeshModification -= OnFinishMeshModification; } void OnBeginMeshModification(ProBuilderMesh[] selection) diff --git a/com.unity.probuilder/Editor/EditorCore/RotateTool.cs b/com.unity.probuilder/Editor/EditorCore/RotateTool.cs index ca68bd4b3..367f85dea 100644 --- a/com.unity.probuilder/Editor/EditorCore/RotateTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/RotateTool.cs @@ -24,7 +24,7 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation if (EditorGUI.EndChangeCheck()) { if (!m_IsEditing) - BeginEdit(); + BeginEdit("Rotate Selection"); Apply(Matrix4x4.Rotate(m_Rotation)); } @@ -41,7 +41,7 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation if (EditorGUI.EndChangeCheck()) { if (!m_IsEditing) - BeginEdit(); + BeginEdit("Rotate Selection"); Apply(Matrix4x4.Rotate(m_Rotation * Quaternion.Inverse(handleRotationOrigin))); } diff --git a/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs b/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs index d4f0cfa34..49177a0cf 100644 --- a/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs @@ -18,7 +18,7 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation if (EditorGUI.EndChangeCheck()) { if (!m_IsEditing) - BeginEdit(); + BeginEdit("Scale Selection"); Apply(Matrix4x4.Scale(m_Scale)); } diff --git a/com.unity.probuilder/Editor/EditorCore/SmoothGroupEditor.cs b/com.unity.probuilder/Editor/EditorCore/SmoothGroupEditor.cs index 2cd93d51f..f8a7ae756 100644 --- a/com.unity.probuilder/Editor/EditorCore/SmoothGroupEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/SmoothGroupEditor.cs @@ -334,8 +334,8 @@ void OnEnable() Selection.selectionChanged += OnSelectionChanged; Undo.undoRedoPerformed += OnSelectionChanged; ProBuilderMesh.elementSelectionChanged += OnElementSelectionChanged; - ProBuilderEditor.beforeMeshModification += OnBeginVertexMovement; - ProBuilderEditor.afterMeshModification += OnFinishVertexMovement; + VertexManipulationTool.beforeMeshModification += OnBeginVertexMovement; + VertexManipulationTool.afterMeshModification += OnFinishVertexMovement; autoRepaintOnSceneChange = true; m_HelpIcon = new GUIContent(IconUtility.GetIcon("Toolbar/Help"), "Open Documentation"); m_BreakSmoothingContent = new GUIContent(IconUtility.GetIcon("Toolbar/Face_BreakSmoothing"), diff --git a/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs index c192e66b9..f728c22f4 100644 --- a/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs +++ b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs @@ -65,6 +65,7 @@ internal static void DrawGizmo(Vector3 position, Matrix4x4 matrix, float size = internal class LineDrawingScope : IDisposable { + bool m_Wire; Color m_Color; float m_Thickness; CompareFunction m_ZTest; @@ -73,17 +74,23 @@ internal class LineDrawingScope : IDisposable public Color color { get { return m_Color; } + set { - End(); + if(!m_Wire) + End(); + m_Color = value; - Begin(); + + if(!m_Wire) + Begin(); } } public float thickness { get { return m_Thickness; } + set { End(); @@ -117,14 +124,15 @@ public LineDrawingScope(Color color, float thickness = -1f, CompareFunction zTes void Begin() { + m_Wire = thickness < .01f || !BuiltinMaterials.geometryShadersSupported; + s_LineMaterial.SetColor("_Color", color); s_LineMaterial.SetInt("_HandleZTest", (int) zTest); - if(BuiltinMaterials.geometryShadersSupported) + if(!m_Wire) s_LineMaterial.SetFloat("_Scale", thickness * EditorGUIUtility.pixelsPerPoint); - if (!BuiltinMaterials.geometryShadersSupported || - !s_LineMaterial.SetPass(0)) + if (m_Wire || !s_LineMaterial.SetPass(0)) { if (s_ApplyWireMaterial == null) { @@ -155,6 +163,9 @@ void End() public void DrawLine(Vector3 a, Vector3 b) { + if(m_Wire) + GL.Color(color); + GL.Vertex(a); GL.Vertex(b); } diff --git a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs index 04620bba4..9ce0890c5 100644 --- a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs @@ -1,8 +1,11 @@ +using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using UnityEngine; using UnityEngine.ProBuilder; using UnityEngine.ProBuilder.MeshOperations; +using Math = UnityEngine.ProBuilder.Math; #if DEBUG_HANDLES using UnityEngine.Rendering; @@ -170,15 +173,43 @@ static void CollectAdjacentFaces(WingedEdge wing, HashSet filter, List + /// Called when vertex modifications are complete. + /// + public static event Action afterMeshModification; + + /// + /// Called immediately prior to beginning vertex modifications. The ProBuilderMesh will be in un-altered state at this point (meaning ProBuilderMesh.ToMesh and ProBuilderMesh.Refresh have been called, but not Optimize). + /// + public static event Action beforeMeshModification; + internal static Pref s_ExtrudeEdgesAsGroup = new Pref("editor.extrudeEdgesAsGroup", true); internal static Pref s_ExtrudeMethod = new Pref("editor.extrudeMethod", ExtrudeMethod.FaceNormal); Vector3 m_HandlePosition; Quaternion m_HandleRotation; - Vector3 m_HandlePositionOrigin; Quaternion m_HandleRotationOrigin; - protected Quaternion handleRotationOriginInverse { get; private set; } + + float m_SnapValue = .25f; + bool m_SnapAxisConstraint = true; + bool m_SnapEnabled; + static bool s_Initialized; + static FieldInfo s_VertexDragging; + static MethodInfo s_FindNearestVertex; + static object[] s_FindNearestVertexArguments = new object[] { null, null, null }; + + protected static bool vertexDragging + { + get + { + Init(); + return s_VertexDragging != null && (bool) s_VertexDragging.GetValue(null); + } + } + + protected List m_Selection = new List(); + protected bool m_IsEditing; protected Event currentEvent { get; private set; } @@ -189,14 +220,37 @@ protected Vector3 handlePositionOrigin get { return m_HandlePositionOrigin; } } + protected Quaternion handleRotationOriginInverse { get; private set; } + protected Quaternion handleRotationOrigin { get { return m_HandleRotationOrigin; } } - protected List m_Selection = new List(); + protected float snapValue + { + get { return m_SnapValue; } + } - protected bool m_IsEditing; + protected bool snapAxisConstraint + { + get { return m_SnapAxisConstraint; } + } + + protected bool snapEnabled + { + get { return m_SnapEnabled; } + } + + static void Init() + { + if (s_Initialized) + return; + s_Initialized = true; + s_VertexDragging = typeof(Tools).GetField("vertexDragging", BindingFlags.NonPublic | BindingFlags.Static); + s_FindNearestVertex = typeof(HandleUtility).GetMethod("FindNearestVertex", + BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance); + } public void OnSceneGUI(Event evt) { @@ -249,12 +303,13 @@ public void OnSceneGUI(Event evt) } } + DoTool(m_HandlePosition, m_HandleRotation); } protected abstract void DoTool(Vector3 handlePosition, Quaternion handleRotation); - protected void BeginEdit() + protected void BeginEdit(string undoMessage) { if (m_IsEditing) return; @@ -268,7 +323,7 @@ protected void BeginEdit() m_HandleRotationOrigin = m_HandleRotation; handleRotationOriginInverse = Quaternion.Inverse(m_HandleRotation); - ProBuilderEditor.instance.OnBeginVertexMovement(); + OnBeginVertexMovement(undoMessage); m_Selection.Clear(); @@ -281,7 +336,7 @@ protected void FinishEdit() if (!m_IsEditing) return; - ProBuilderEditor.instance.OnFinishVertexModification(); + OnFinishVertexModification(); m_IsEditing = false; } @@ -365,5 +420,71 @@ static void Extrude() ProBuilderEditor.Refresh(); } } + + /// + /// Find the nearest vertex among all visible objects. + /// + /// + /// + /// + protected static bool FindNearestVertex(Vector2 mousePosition, out Vector3 vertex) + { + s_FindNearestVertexArguments[0] = mousePosition; + + if (s_FindNearestVertex == null) + s_FindNearestVertex = typeof(HandleUtility).GetMethod("findNearestVertex", + BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance); + + object result = s_FindNearestVertex.Invoke(null, s_FindNearestVertexArguments); + vertex = (bool) result ? (Vector3) s_FindNearestVertexArguments[2] : Vector3.zero; + return (bool) result; + } + + /// + /// When beginning a vertex modification, nuke the UV2 and rebuild the mesh using PB data so that triangles + /// match vertices (and no inserted vertices from the Unwrapping.GenerateSecondaryUVSet() remain). + /// + protected void OnBeginVertexMovement(string undoMessage) + { + UndoUtility.RecordSelection(string.IsNullOrEmpty(undoMessage) ? "Modify Vertices" : undoMessage); + + m_SnapEnabled = ProGridsInterface.SnapEnabled(); + m_SnapValue = ProGridsInterface.SnapValue(); + m_SnapAxisConstraint = ProGridsInterface.UseAxisConstraints(); + + // Disable iterative lightmapping + Lightmapping.PushGIWorkflowMode(); + + var selection = MeshSelection.topInternal.ToArray(); + + foreach (var mesh in selection) + { + mesh.ToMesh(); + mesh.Refresh(); + } + + if (beforeMeshModification != null) + beforeMeshModification(selection); + } + + internal void OnFinishVertexModification() + { + Lightmapping.PopGIWorkflowMode(); + + var selection = MeshSelection.topInternal.ToArray(); + + foreach (var mesh in selection) + { + mesh.ToMesh(); + mesh.Refresh(); + mesh.Optimize(); + } + + ProBuilderEditor.Refresh(); + + if (afterMeshModification != null) + afterMeshModification(selection); + } + } } diff --git a/com.unity.probuilder/Runtime/Core/InternalUtility.cs b/com.unity.probuilder/Runtime/Core/InternalUtility.cs index 5c275bceb..a63e0882c 100644 --- a/com.unity.probuilder/Runtime/Core/InternalUtility.cs +++ b/com.unity.probuilder/Runtime/Core/InternalUtility.cs @@ -12,7 +12,7 @@ namespace UnityEngine.ProBuilder /// static class InternalUtility { - // todo Change to shallow search + [Obsolete] public static T[] GetComponents(this IEnumerable gameObjects) where T : Component { List c = new List(); From fefc8fcab8eb7d0bb61fb9a908c36b5436214cf5 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Fri, 26 Oct 2018 12:23:24 -0400 Subject: [PATCH 16/27] Enable relative snapping when progrids is enabled with move tool --- .../Editor/EditorCore/EditorMeshHandles.cs | 2 +- .../Editor/EditorCore/MoveTool.cs | 8 +- .../EditorCore/StaticEditorMeshHandles.cs | 14 +-- .../EditorCore/VertexManipulationTool.cs | 85 ++++++++----------- .../Settings/Editor/UserSetting.cs | 2 +- 5 files changed, 51 insertions(+), 60 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs b/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs index 6c8636736..ca17d9120 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs @@ -53,7 +53,7 @@ partial class EditorMeshHandles : IDisposable, IHasPreferences static Pref s_VertexPointSize = new Pref("graphics.vertexPointSize", 3f, SettingsScope.User); [UserSetting("Graphics", "Handle Z Test", "The compare function to use when drawing mesh handles.")] - static Pref s_HandleCompareFunction = new Pref("graphics.handleZTest", CompareFunction.Always, SettingsScopes.User); + static Pref s_HandleCompareFunction = new Pref("graphics.handleZTest", CompareFunction.Always, SettingsScope.User); [UserSettingBlock("Graphics")] static void HandleColorPreferences(string searchContext) diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs index 095d8e770..0e9f72a06 100644 --- a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs @@ -36,7 +36,7 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation if (dir.IntSum() == 1) { - var rot_dir = handleRotationOrigin * dir * 1000f; + var rot_dir = handleRotationOrigin * dir * 10000f; m_HandlePosition = HandleUtility.ProjectPointLine(nearest, handlePositionOrigin + rot_dir, @@ -46,6 +46,12 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation } } } + else if (snapEnabled) + { + var travel = delta.magnitude; + delta = delta.normalized * Snapping.SnapValue(travel, snapValue); + m_HandlePosition = handlePosition + delta; + } switch (pivotPoint) { diff --git a/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs index f728c22f4..d2776abad 100644 --- a/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs +++ b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs @@ -90,7 +90,7 @@ public Color color public float thickness { get { return m_Thickness; } - + set { End(); @@ -118,7 +118,8 @@ public LineDrawingScope(Color color, float thickness = -1f, CompareFunction zTes { Init(); m_Color = color; - m_Thickness = thickness; + m_Thickness = thickness < 0f ? s_EdgeLineSize : thickness; + m_ZTest = zTest; Begin(); } @@ -126,11 +127,12 @@ void Begin() { m_Wire = thickness < .01f || !BuiltinMaterials.geometryShadersSupported; - s_LineMaterial.SetColor("_Color", color); - s_LineMaterial.SetInt("_HandleZTest", (int) zTest); - - if(!m_Wire) + if (!m_Wire) + { + s_LineMaterial.SetColor("_Color", color); s_LineMaterial.SetFloat("_Scale", thickness * EditorGUIUtility.pixelsPerPoint); + s_LineMaterial.SetInt("_HandleZTest", (int) zTest); + } if (m_Wire || !s_LineMaterial.SetPass(0)) { diff --git a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs index 9ce0890c5..a1074a3c8 100644 --- a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs @@ -314,6 +314,16 @@ protected void BeginEdit(string undoMessage) if (m_IsEditing) return; + // Disable iterative lightmapping + Lightmapping.PushGIWorkflowMode(); + + var selection = MeshSelection.topInternal.ToArray(); + + UndoUtility.RegisterCompleteObjectUndo(selection, string.IsNullOrEmpty(undoMessage) ? "Modify Vertices" : undoMessage); + + if (beforeMeshModification != null) + beforeMeshModification(selection); + if (currentEvent.shift) Extrude(); @@ -323,7 +333,15 @@ protected void BeginEdit(string undoMessage) m_HandleRotationOrigin = m_HandleRotation; handleRotationOriginInverse = Quaternion.Inverse(m_HandleRotation); - OnBeginVertexMovement(undoMessage); + m_SnapEnabled = ProGridsInterface.SnapEnabled(); + m_SnapValue = ProGridsInterface.SnapValue(); + m_SnapAxisConstraint = ProGridsInterface.UseAxisConstraints(); + + foreach (var mesh in selection) + { + mesh.ToMesh(); + mesh.Refresh(); + } m_Selection.Clear(); @@ -336,7 +354,21 @@ protected void FinishEdit() if (!m_IsEditing) return; - OnFinishVertexModification(); + Lightmapping.PopGIWorkflowMode(); + + var selection = MeshSelection.topInternal.ToArray(); + + foreach (var mesh in selection) + { + mesh.ToMesh(); + mesh.Refresh(); + mesh.Optimize(); + } + + ProBuilderEditor.Refresh(); + + if (afterMeshModification != null) + afterMeshModification(selection); m_IsEditing = false; } @@ -375,8 +407,6 @@ static void Extrude() var selection = MeshSelection.topInternal; var selectMode = ProBuilderEditor.selectMode; - UndoUtility.RecordSelection("Extrude Vertices"); - foreach (var mesh in selection) { switch (selectMode) @@ -439,52 +469,5 @@ protected static bool FindNearestVertex(Vector2 mousePosition, out Vector3 verte vertex = (bool) result ? (Vector3) s_FindNearestVertexArguments[2] : Vector3.zero; return (bool) result; } - - /// - /// When beginning a vertex modification, nuke the UV2 and rebuild the mesh using PB data so that triangles - /// match vertices (and no inserted vertices from the Unwrapping.GenerateSecondaryUVSet() remain). - /// - protected void OnBeginVertexMovement(string undoMessage) - { - UndoUtility.RecordSelection(string.IsNullOrEmpty(undoMessage) ? "Modify Vertices" : undoMessage); - - m_SnapEnabled = ProGridsInterface.SnapEnabled(); - m_SnapValue = ProGridsInterface.SnapValue(); - m_SnapAxisConstraint = ProGridsInterface.UseAxisConstraints(); - - // Disable iterative lightmapping - Lightmapping.PushGIWorkflowMode(); - - var selection = MeshSelection.topInternal.ToArray(); - - foreach (var mesh in selection) - { - mesh.ToMesh(); - mesh.Refresh(); - } - - if (beforeMeshModification != null) - beforeMeshModification(selection); - } - - internal void OnFinishVertexModification() - { - Lightmapping.PopGIWorkflowMode(); - - var selection = MeshSelection.topInternal.ToArray(); - - foreach (var mesh in selection) - { - mesh.ToMesh(); - mesh.Refresh(); - mesh.Optimize(); - } - - ProBuilderEditor.Refresh(); - - if (afterMeshModification != null) - afterMeshModification(selection); - } - } } diff --git a/com.unity.probuilder/Settings/Editor/UserSetting.cs b/com.unity.probuilder/Settings/Editor/UserSetting.cs index 90f8aef97..c3baf4abe 100644 --- a/com.unity.probuilder/Settings/Editor/UserSetting.cs +++ b/com.unity.probuilder/Settings/Editor/UserSetting.cs @@ -245,7 +245,7 @@ public void SetValue(T value, bool saveProjectSettingsImmediately = false) m_Value = value; settings.Set(key, m_Value, m_Scope); - if (m_Scope == SettingsScope.Project && saveProjectSettingsImmediately) + if (saveProjectSettingsImmediately) settings.Save(); } From 1f0f788e78f5a2417889f260ae8f375085bbb1de Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Fri, 26 Oct 2018 14:02:46 -0400 Subject: [PATCH 17/27] support progrids snapping to world space when possible --- .../Editor/EditorCore/MoveTool.cs | 35 +++- .../Editor/EditorCore/UVEditor.cs | 6 +- .../EditorCore/VertexManipulationTool.cs | 7 + com.unity.probuilder/Runtime/Core/Math.cs | 17 -- .../Runtime/Core/VectorMask.cs | 155 ++++++++++++++++++ .../Runtime/Core/VectorMask.cs.meta | 11 ++ .../Runtime/Core/VertexPositioning.cs | 4 +- 7 files changed, 208 insertions(+), 27 deletions(-) create mode 100644 com.unity.probuilder/Runtime/Core/VectorMask.cs create mode 100644 com.unity.probuilder/Runtime/Core/VectorMask.cs.meta diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs index 0e9f72a06..e24563367 100644 --- a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/MoveTool.cs @@ -9,6 +9,16 @@ class MoveTool : VertexManipulationTool Vector3 m_HandlePosition; Matrix4x4 m_Translation = Matrix4x4.identity; + bool m_SnapInWorldCoordinates; + Vector3 m_WorldSnapDirection; + Vector3 m_WorldSnapMask; + + protected override void OnToolEngaged() + { + m_SnapInWorldCoordinates = false; + m_WorldSnapMask = new Vector3Mask(0x0); + } + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { if (!m_IsEditing) @@ -32,9 +42,9 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation if (FindNearestVertex(currentEvent.mousePosition, out nearest)) { var unrotated = handleRotationOriginInverse * delta; - var dir = Math.ToMask(unrotated, k_CardinalAxisError); + var dir = new Vector3Mask(unrotated, k_CardinalAxisError); - if (dir.IntSum() == 1) + if (dir.active == 1) { var rot_dir = handleRotationOrigin * dir * 10000f; @@ -48,9 +58,24 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation } else if (snapEnabled) { - var travel = delta.magnitude; - delta = delta.normalized * Snapping.SnapValue(travel, snapValue); - m_HandlePosition = handlePosition + delta; + var localDir = handleRotationOriginInverse * delta; + m_WorldSnapDirection = delta.normalized; + + if (!m_SnapInWorldCoordinates && (Math.IsCardinalAxis(delta) || !Math.IsCardinalAxis(localDir))) + m_SnapInWorldCoordinates = true; + + if (m_SnapInWorldCoordinates) + { + m_WorldSnapMask |= new Vector3Mask(m_WorldSnapDirection, k_CardinalAxisError); + m_HandlePosition = Snapping.SnapValue(m_HandlePosition, m_WorldSnapMask * snapValue); + delta = m_HandlePosition - handlePositionOrigin; + } + else + { + var travel = delta.magnitude; + delta = m_WorldSnapDirection * Snapping.SnapValue(travel, snapValue); + m_HandlePosition = handlePositionOrigin + delta; + } } switch (pivotPoint) diff --git a/com.unity.probuilder/Editor/EditorCore/UVEditor.cs b/com.unity.probuilder/Editor/EditorCore/UVEditor.cs index 27ddb5c82..4b701a080 100644 --- a/com.unity.probuilder/Editor/EditorCore/UVEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/UVEditor.cs @@ -1236,7 +1236,7 @@ void MoveTool() if (ControlKey) { - handlePosition = Snapping.SnapValue(t_handlePosition, (handlePosition - t_handlePosition).ToMask(Math.handleEpsilon) * s_GridSnapIncrement); + handlePosition = Snapping.SnapValue(t_handlePosition, (Vector3) new Vector3Mask((handlePosition - t_handlePosition), Math.handleEpsilon) * s_GridSnapIncrement); } else { @@ -1298,7 +1298,7 @@ void MoveTool() Vector2 newUVPosition = t_handlePosition; if (ControlKey) - newUVPosition = Snapping.SnapValue(newUVPosition, (handlePosition - t_handlePosition).ToMask(Math.handleEpsilon) * s_GridSnapIncrement); + newUVPosition = Snapping.SnapValue(newUVPosition, new Vector3Mask((handlePosition - t_handlePosition), Math.handleEpsilon) * s_GridSnapIncrement); for (int n = 0; n < selection.Length; n++) { @@ -1388,7 +1388,7 @@ internal void SceneMoveTool(Vector2 delta) handlePosition.y += delta.y; if (ControlKey) - handlePosition = Snapping.SnapValue(handlePosition, (handlePosition - handlePosition).ToMask(Math.handleEpsilon) * s_GridSnapIncrement); + handlePosition = Snapping.SnapValue(handlePosition, new Vector3Mask((handlePosition - handlePosition), Math.handleEpsilon) * s_GridSnapIncrement); for (int n = 0; n < selection.Length; n++) { diff --git a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs index a1074a3c8..80204b671 100644 --- a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs @@ -309,6 +309,9 @@ public void OnSceneGUI(Event evt) protected abstract void DoTool(Vector3 handlePosition, Quaternion handleRotation); + protected virtual void OnToolEngaged() { } + protected virtual void OnToolDisengaged() { } + protected void BeginEdit(string undoMessage) { if (m_IsEditing) @@ -347,6 +350,8 @@ protected void BeginEdit(string undoMessage) foreach (var mesh in MeshSelection.topInternal) m_Selection.Add(new MeshAndElementSelection(mesh, pivotPoint)); + + OnToolEngaged(); } protected void FinishEdit() @@ -371,6 +376,8 @@ protected void FinishEdit() afterMeshModification(selection); m_IsEditing = false; + + OnToolDisengaged(); } protected void Apply(Matrix4x4 delta) diff --git a/com.unity.probuilder/Runtime/Core/Math.cs b/com.unity.probuilder/Runtime/Core/Math.cs index f63f9abb5..025a6d22b 100644 --- a/com.unity.probuilder/Runtime/Core/Math.cs +++ b/com.unity.probuilder/Runtime/Core/Math.cs @@ -1238,23 +1238,6 @@ public static int Clamp(int value, int lowerBound, int upperBound) return value < lowerBound ? lowerBound : value > upperBound ? upperBound : value; } - internal static Vector2 ToMask(this Vector2 vec, float delta = floatEpsilon) - { - return new Vector2( - Mathf.Abs(vec.x) > delta ? 1f : 0f, - Mathf.Abs(vec.y) > delta ? 1f : 0f - ); - } - - internal static Vector3 ToMask(this Vector3 vec, float delta = floatEpsilon) - { - return new Vector3( - Mathf.Abs(vec.x) > delta ? 1f : 0f, - Mathf.Abs(vec.y) > delta ? 1f : 0f, - Mathf.Abs(vec.z) > delta ? 1f : 0f - ); - } - internal static Vector3 ToSignedMask(this Vector3 vec, float delta = floatEpsilon) { return new Vector3( diff --git a/com.unity.probuilder/Runtime/Core/VectorMask.cs b/com.unity.probuilder/Runtime/Core/VectorMask.cs new file mode 100644 index 000000000..ce59e8564 --- /dev/null +++ b/com.unity.probuilder/Runtime/Core/VectorMask.cs @@ -0,0 +1,155 @@ +namespace UnityEngine.ProBuilder +{ + struct Vector2Mask + { + const byte X = 1 << 0; + const byte Y = 1 << 1; + + public static readonly Vector2Mask XY = new Vector2Mask(X | Y); + + byte m_Mask; + + public float x + { + get { return (m_Mask & X) == X ? 1f : 0f; } + } + + public float y + { + get { return (m_Mask & Y) == Y ? 1f : 0f; } + } + + public Vector2Mask(Vector3 v, float epsilon = float.Epsilon) + { + m_Mask = 0x0; + + if (Mathf.Abs(v.x) > epsilon) + m_Mask |= X; + if (Mathf.Abs(v.y) > epsilon) + m_Mask |= Y; + } + + public Vector2Mask(byte mask) + { + m_Mask = mask; + } + + public static implicit operator Vector2(Vector2Mask mask) + { + return new Vector2(mask.x, mask.y); + } + + public static implicit operator Vector2Mask(Vector2 v) + { + return new Vector2Mask(v); + } + + public static Vector2Mask operator |(Vector2Mask left, Vector2Mask right) + { + return new Vector2Mask((byte)(left.m_Mask | right.m_Mask)); + } + + public static Vector2Mask operator &(Vector2Mask left, Vector2Mask right) + { + return new Vector2Mask((byte)(left.m_Mask & right.m_Mask)); + } + + public static Vector2Mask operator ^(Vector2Mask left, Vector2Mask right) + { + return new Vector2Mask((byte)(left.m_Mask ^ right.m_Mask)); + } + + public static Vector2 operator *(Vector2Mask mask, float value) + { + return new Vector2(mask.x * value, mask.y * value); + } + } + + struct Vector3Mask + { + const byte X = 1 << 0; + const byte Y = 1 << 1; + const byte Z = 1 << 2; + + public static readonly Vector3Mask XYZ = new Vector3Mask(X | Y | Z); + + byte m_Mask; + + public float x + { + get { return (m_Mask & X) == X ? 1f : 0f; } + } + + public float y + { + get { return (m_Mask & Y) == Y ? 1f : 0f; } + } + + public float z + { + get { return (m_Mask & Z) == Z ? 1f : 0f; } + } + + public Vector3Mask(Vector3 v, float epsilon = float.Epsilon) + { + m_Mask = 0x0; + + if (Mathf.Abs(v.x) > epsilon) + m_Mask |= X; + if (Mathf.Abs(v.y) > epsilon) + m_Mask |= Y; + if (Mathf.Abs(v.z) > epsilon) + m_Mask |= Z; + } + + public Vector3Mask(byte mask) + { + m_Mask = mask; + } + + public int active + { + get + { + int count = 0; + if ((m_Mask & X) > 0) + count++; + if ((m_Mask & Y) > 0) + count++; + if ((m_Mask & Z) > 0) + count++; + return count; + } + } + + public static implicit operator Vector3(Vector3Mask mask) + { + return new Vector3(mask.x, mask.y, mask.z); + } + + public static implicit operator Vector3Mask(Vector3 v) + { + return new Vector3Mask(v); + } + + public static Vector3Mask operator |(Vector3Mask left, Vector3Mask right) + { + return new Vector3Mask((byte)(left.m_Mask | right.m_Mask)); + } + + public static Vector3Mask operator &(Vector3Mask left, Vector3Mask right) + { + return new Vector3Mask((byte)(left.m_Mask & right.m_Mask)); + } + + public static Vector3Mask operator ^(Vector3Mask left, Vector3Mask right) + { + return new Vector3Mask((byte)(left.m_Mask ^ right.m_Mask)); + } + + public static Vector3 operator *(Vector3Mask mask, float value) + { + return new Vector3(mask.x * value, mask.y * value, mask.z * value); + } + } +} diff --git a/com.unity.probuilder/Runtime/Core/VectorMask.cs.meta b/com.unity.probuilder/Runtime/Core/VectorMask.cs.meta new file mode 100644 index 000000000..c7860a22b --- /dev/null +++ b/com.unity.probuilder/Runtime/Core/VectorMask.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: efd5cca1cb8dabd418d215e770d3fb01 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.probuilder/Runtime/Core/VertexPositioning.cs b/com.unity.probuilder/Runtime/Core/VertexPositioning.cs index 76b378bc3..0aa958658 100644 --- a/com.unity.probuilder/Runtime/Core/VertexPositioning.cs +++ b/com.unity.probuilder/Runtime/Core/VertexPositioning.cs @@ -83,12 +83,12 @@ internal static void TranslateVerticesInWorldSpace(this ProBuilderMesh mesh, if(Mathf.Abs(snapValue) > Mathf.Epsilon) { Matrix4x4 l2w = mesh.transform.localToWorldMatrix; - Vector3 mask = snapAxisOnly ? offset.ToMask(Math.handleEpsilon) : Vector3.one; + var mask = snapAxisOnly ? new Vector3Mask(offset, Math.handleEpsilon) : Vector3Mask.XYZ; for(i = 0; i < s_CoincidentVertices.Count; i++) { var v = l2w.MultiplyPoint3x4(verts[s_CoincidentVertices[i]] + localOffset); - verts[s_CoincidentVertices[i]] = w2l.MultiplyPoint3x4( Snapping.SnapValue(v, snapValue * mask) ); + verts[s_CoincidentVertices[i]] = w2l.MultiplyPoint3x4( Snapping.SnapValue(v, ((Vector3)mask) * snapValue) ); } } else From e952047cbba5d4bd85e5823f5aea1f91b463dcfe Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Fri, 26 Oct 2018 14:13:09 -0400 Subject: [PATCH 18/27] fix scene not moving handle to correct position after changing orientation --- .../Editor/EditorCore/MeshSelection.cs | 17 +++++++++++------ .../Editor/EditorCore/ProBuilderEditor.cs | 2 ++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs index 04f84a9ba..a06c41444 100644 --- a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs +++ b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs @@ -363,11 +363,16 @@ internal static Vector3 GetHandlePosition() { case PivotMode.Pivot: { - var mesh = activeMesh; - if (mesh == null) - return Vector3.zero; - var center = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal); - return mesh.transform.TransformPoint(center.center); + ProBuilderMesh mesh = activeMesh; + Face face; + Vector3 center = Vector3.zero; + + if (ProBuilderEditor.handleOrientation == HandleOrientation.Normal && GetActiveFace(out mesh, out face)) + center = Math.GetBounds(mesh.positionsInternal, face.distinctIndexesInternal).center; + else if(activeMesh != null) + center = Math.GetBounds(mesh.positionsInternal, mesh.selectedIndexesInternal).center; + + return mesh.transform.TransformPoint(center); } default: @@ -419,7 +424,7 @@ static bool GetActiveFace(out ProBuilderMesh mesh, out Face face) return true; } - mesh = null; + mesh = activeMesh; face = null; return false; } diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index 06ae7d166..d106edab9 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -101,6 +101,8 @@ internal static HandleOrientation handleOrientation value = HandleOrientation.Normal; s_HandleOrientation.SetValue(value, true); + + SceneView.RepaintAll(); } } From d9402064eda0fefca4fe524a82475872677cd85d Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Fri, 26 Oct 2018 14:22:38 -0400 Subject: [PATCH 19/27] Fix bug where selected face groups wouldn't gather correctly --- .../EditorCore/VertexManipulationTool.cs | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs index 80204b671..a71daad42 100644 --- a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs @@ -138,12 +138,10 @@ internal static List> GetFaceSelectionGroups(ProBuilderMesh mesh) foreach (var wing in wings) { - if (!filter.Add(wing.face)) - continue; - - var group = new List() { wing.face }; + var group = new List() { }; CollectAdjacentFaces(wing, filter, group); - groups.Add(group); + if(group.Count > 0) + groups.Add(group); } return groups; @@ -151,22 +149,19 @@ internal static List> GetFaceSelectionGroups(ProBuilderMesh mesh) static void CollectAdjacentFaces(WingedEdge wing, HashSet filter, List group) { + if (!filter.Add(wing.face)) + return; + + group.Add(wing.face); + var enumerator = new WingedEdgeEnumerator(wing); while (enumerator.MoveNext()) { - var cur = enumerator.Current.opposite; - - if (cur == null) + var opposite = enumerator.Current.opposite; + if (opposite == null) continue; - - var face = cur.face; - - if (!filter.Add(face)) - continue; - - group.Add(face); - CollectAdjacentFaces(enumerator.Current, filter, group); + CollectAdjacentFaces(opposite, filter, group); } } } From ae7db726cf9f3fd7b9161844437949a465ef9729 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Mon, 29 Oct 2018 12:18:18 -0400 Subject: [PATCH 20/27] wip - adding texture manipulation tools --- .../Editor/EditorCore/EditorHandleUtility.cs | 12 + .../Editor/EditorCore/MeshSelection.cs | 10 +- .../Editor/EditorCore/ProBuilderEditor.cs | 253 ++---------------- .../Editor/EditorCore/TextureMoveTool.cs | 57 ++++ ...leTool.cs.meta => TextureMoveTool.cs.meta} | 2 +- .../Editor/EditorCore/TextureRotateTool.cs | 34 +++ ...Tool.cs.meta => TextureRotateTool.cs.meta} | 2 +- .../Editor/EditorCore/TextureScaleTool.cs | 33 +++ ...eTool.cs.meta => TextureScaleTool.cs.meta} | 2 +- .../Editor/EditorCore/TextureTool.cs | 39 +++ .../Editor/EditorCore/TextureTool.cs.meta | 11 + .../EditorCore/VertexManipulationTool.cs | 84 +++--- .../{MoveTool.cs => VertexMoveTool.cs} | 6 +- .../Editor/EditorCore/VertexMoveTool.cs.meta | 11 + .../{RotateTool.cs => VertexRotateTool.cs} | 10 +- .../EditorCore/VertexRotateTool.cs.meta | 11 + .../{ScaleTool.cs => VertexScaleTool.cs} | 6 +- .../Editor/EditorCore/VertexScaleTool.cs.meta | 11 + .../Editor/EditorCore/VertexTool.cs | 66 +++++ .../Editor/EditorCore/VertexTool.cs.meta | 11 + 20 files changed, 366 insertions(+), 305 deletions(-) create mode 100644 com.unity.probuilder/Editor/EditorCore/TextureMoveTool.cs rename com.unity.probuilder/Editor/EditorCore/{ScaleTool.cs.meta => TextureMoveTool.cs.meta} (83%) create mode 100644 com.unity.probuilder/Editor/EditorCore/TextureRotateTool.cs rename com.unity.probuilder/Editor/EditorCore/{MoveTool.cs.meta => TextureRotateTool.cs.meta} (83%) create mode 100644 com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs rename com.unity.probuilder/Editor/EditorCore/{RotateTool.cs.meta => TextureScaleTool.cs.meta} (83%) create mode 100644 com.unity.probuilder/Editor/EditorCore/TextureTool.cs create mode 100644 com.unity.probuilder/Editor/EditorCore/TextureTool.cs.meta rename com.unity.probuilder/Editor/EditorCore/{MoveTool.cs => VertexMoveTool.cs} (96%) create mode 100644 com.unity.probuilder/Editor/EditorCore/VertexMoveTool.cs.meta rename com.unity.probuilder/Editor/EditorCore/{RotateTool.cs => VertexRotateTool.cs} (88%) create mode 100644 com.unity.probuilder/Editor/EditorCore/VertexRotateTool.cs.meta rename com.unity.probuilder/Editor/EditorCore/{ScaleTool.cs => VertexScaleTool.cs} (84%) create mode 100644 com.unity.probuilder/Editor/EditorCore/VertexScaleTool.cs.meta create mode 100644 com.unity.probuilder/Editor/EditorCore/VertexTool.cs create mode 100644 com.unity.probuilder/Editor/EditorCore/VertexTool.cs.meta diff --git a/com.unity.probuilder/Editor/EditorCore/EditorHandleUtility.cs b/com.unity.probuilder/Editor/EditorCore/EditorHandleUtility.cs index 38d9fc901..08d77d9c2 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorHandleUtility.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorHandleUtility.cs @@ -14,6 +14,8 @@ namespace UnityEditor.ProBuilder /// static class EditorHandleUtility { + static Stack s_HandleMatrix = new Stack(); + public static bool SceneViewInUse(Event e) { return e.alt @@ -556,5 +558,15 @@ internal static PivotPoint ProBuilderPivot(this PivotMode pivotMode) return PivotPoint.ModelBoundingBoxCenter; } + + internal static void PushMatrix() + { + s_HandleMatrix.Push(Handles.matrix); + } + + internal static void PopMatrix() + { + Handles.matrix = s_HandleMatrix.Pop(); + } } } diff --git a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs index a06c41444..72fb190e3 100644 --- a/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs +++ b/com.unity.probuilder/Editor/EditorCore/MeshSelection.cs @@ -383,8 +383,6 @@ internal static Vector3 GetHandlePosition() internal static Quaternion GetHandleRotation(HandleOrientation orientation) { - Quaternion localRotation = Selection.activeTransform == null ? Quaternion.identity : Selection.activeTransform.rotation; - switch (orientation) { case HandleOrientation.Normal: @@ -393,7 +391,7 @@ internal static Quaternion GetHandleRotation(HandleOrientation orientation) Face face; if(!GetActiveFace(out mesh, out face)) - goto default; + goto case HandleOrientation.Local; // use average normal, tangent, and bi-tangent to calculate rotation relative to local space var tup = Math.NormalTangentBitangent(mesh, face); @@ -405,10 +403,12 @@ internal static Quaternion GetHandleRotation(HandleOrientation orientation) bitan = Vector3.right; } - return localRotation * Quaternion.LookRotation(nrm, bitan); + return activeMesh.transform.rotation * Quaternion.LookRotation(nrm, bitan); case HandleOrientation.Local: - return localRotation; + if (activeMesh == null) + goto default; + return activeMesh.transform.rotation; default: return Quaternion.identity; diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index d106edab9..ebefe5890 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -145,6 +145,7 @@ internal bool backfaceSelectionEnabled bool m_WasDoubleClick; // vertex handles bool m_IsRightMouseDown; + static Dictionary s_EditorTools = new Dictionary(); Vector3[][] m_VertexPositions; Vector3[] m_VertexOffset; @@ -512,6 +513,18 @@ void SetIsUtilityWindow(bool isUtilityWindow) res.titleContent = windowTitle; } + + VertexManipulationTool GetTool() where T : VertexManipulationTool, new() + { + VertexManipulationTool tool; + + if (s_EditorTools.TryGetValue(typeof(T), out tool)) + return tool; + tool = new T(); + s_EditorTools.Add(typeof(T), tool); + return tool; + } + void OnSceneGUI(SceneView sceneView) { #if !UNITY_2018_2_OR_NEWER @@ -523,21 +536,6 @@ void OnSceneGUI(SceneView sceneView) m_CurrentEvent = Event.current; -// if(selectMode.ContainsFlag(SelectMode.Face | SelectMode.Edge | SelectMode.Vertex)) -// { -// if (m_CurrentEvent.Equals(Event.KeyboardEvent("v"))) -// m_DoSnapToVertex = true; -// else if (m_CurrentEvent.Equals(Event.KeyboardEvent("c"))) -// m_DoSnapToFace = true; -// } - - // Snap stuff -// if (m_CurrentEvent.type == EventType.KeyUp) -// { -// m_DoSnapToFace = false; -// m_DoSnapToVertex = false; -// } - if (m_CurrentEvent.type == EventType.MouseDown && m_CurrentEvent.button == 1) m_IsRightMouseDown = true; @@ -565,14 +563,6 @@ void OnSceneGUI(SceneView sceneView) if (selectMode == SelectMode.Object) return; -// -// // Finished moving vertices, scaling, or adjusting uvs -// if ((m_IsMovingElements || m_IsMovingTextures) && GUIUtility.hotControl < 1) -// { -// OnFinishVertexModification(); -// m_HandleRotation = MeshSelection.GetHandleRotation(s_HandleOrientation); -// UpdateTextureHandles(); -// } // Check mouse position in scene and determine if we should highlight something if (s_ShowHoverHighlight @@ -608,13 +598,13 @@ void OnSceneGUI(SceneView sceneView) switch (m_CurrentTool) { case Tool.Move: - TextureMoveTool(); + GetTool().OnSceneGUI(m_CurrentEvent); break; case Tool.Rotate: - TextureRotateTool(); +// GetTool().OnSceneGUI(m_CurrentEvent); break; case Tool.Scale: - TextureScaleTool(); +// GetTool().OnSceneGUI(m_CurrentEvent); break; } } @@ -623,13 +613,13 @@ void OnSceneGUI(SceneView sceneView) switch (m_CurrentTool) { case Tool.Move: - VertexMoveTool(); + GetTool().OnSceneGUI(m_CurrentEvent); break; case Tool.Scale: - VertexScaleTool(); + GetTool().OnSceneGUI(m_CurrentEvent); break; case Tool.Rotate: - VertexRotateTool(); + GetTool().OnSceneGUI(m_CurrentEvent); break; } } @@ -751,211 +741,6 @@ void DoubleClick(Event e) } } - static VertexManipulationTool s_MoveTool; - static VertexManipulationTool s_RotateTool; - static VertexManipulationTool m_ScaleTool; -#pragma warning disable 612 - void VertexMoveTool() - { - if(s_MoveTool == null) - s_MoveTool = new MoveTool(); - - s_MoveTool.OnSceneGUI(Event.current); - - return; -// -// if (!m_IsMovingElements) -// m_ElementHandlePosition = m_HandlePosition; -// -// m_ElementHandleCachedPosition = m_ElementHandlePosition; -// -// m_ElementHandlePosition = Handles.PositionHandle(m_ElementHandlePosition, m_HandleRotation); -// -// if (m_CurrentEvent.alt) -// return; -// -// if (m_ElementHandlePosition != m_ElementHandleCachedPosition) -// { -// Vector3 diff = m_ElementHandlePosition - m_ElementHandleCachedPosition; -// -// Vector3 mask = diff.ToMask(Math.handleEpsilon); -// -// if (m_DoSnapToVertex) -// { -// Vector3 v; -// -// if (FindNearestVertex(m_CurrentEvent.mousePosition, out v)) -// diff = Vector3.Scale(v - m_ElementHandleCachedPosition, mask); -// } -// else if (m_DoSnapToFace) -// { -// ProBuilderMesh obj = null; -// RaycastHit hit; -// Dictionary> ignore = new Dictionary>(); -// foreach (ProBuilderMesh pb in selection) -// ignore.Add(pb, new HashSet(pb.selectedFacesInternal)); -// -// if (EditorHandleUtility.FaceRaycast(m_CurrentEvent.mousePosition, out obj, out hit, ignore)) -// { -// if (mask.IntSum() == 1) -// { -// Ray r = new Ray(m_ElementHandleCachedPosition, -mask); -// Plane plane = new Plane(obj.transform.TransformDirection(hit.normal).normalized, -// obj.transform.TransformPoint(hit.point)); -// -// float forward, backward; -// plane.Raycast(r, out forward); -// plane.Raycast(r, out backward); -// float planeHit = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; -// r.direction = -r.direction; -// plane.Raycast(r, out forward); -// plane.Raycast(r, out backward); -// float rev = Mathf.Abs(forward) < Mathf.Abs(backward) ? forward : backward; -// if (Mathf.Abs(rev) > Mathf.Abs(planeHit)) -// planeHit = rev; -// -// if (Mathf.Abs(planeHit) > Mathf.Epsilon) -// diff = mask * -planeHit; -// } -// else -// { -// diff = Vector3.Scale(obj.transform.TransformPoint(hit.point) - m_ElementHandleCachedPosition, mask.Abs()); -// } -// } -// } -// -// if (!m_IsMovingElements) -// { -// m_IsMovingElements = true; -// m_TranslateOrigin = m_ElementHandleCachedPosition; -// m_RotateOrigin = m_HandleRotation.eulerAngles; -// m_ScaleOrigin = m_HandleScale; -// -// OnBeginVertexMovement(); -// -// ProGridsInterface.OnHandleMove(mask); -// } -// -// for (int i = 0; i < selection.Length; i++) -// { -// var mesh = selection[i]; -// -// mesh.TranslateVerticesInWorldSpace(mesh.selectedIndexesInternal, -// diff, -// m_SnapEnabled ? m_SnapValue : 0f, -// m_SnapAxisConstraint); -// -// mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); -// mesh.Refresh(RefreshMask.Normals); -// mesh.mesh.RecalculateBounds(); -// } -// -// UpdateMeshHandles(false); -// } - } - - void VertexScaleTool() - { - if (m_ScaleTool == null) - m_ScaleTool = new ScaleTool(); - - m_ScaleTool.OnSceneGUI(Event.current); - } - - void VertexRotateTool() - { - if (s_RotateTool == null) - s_RotateTool = new RotateTool(); - - s_RotateTool.OnSceneGUI(Event.current); - } - -#pragma warning restore 612 - - void TextureMoveTool() - { -// UVEditor uvEditor = UVEditor.instance; -// if (!uvEditor) return; -// -// Vector3 cached = m_TextureHandlePosition; -// -// m_TextureHandlePosition = Handles.PositionHandle(m_TextureHandlePosition, m_HandleRotation); -// -// if (m_CurrentEvent.alt) return; -// -// if (m_TextureHandlePosition != cached) -// { -// cached = Quaternion.Inverse(m_HandleRotation) * m_TextureHandlePosition; -// cached.y = -cached.y; -// -// Vector3 lossyScale = selection[0].transform.lossyScale; -// Vector3 pos = cached.DivideBy(lossyScale); -// -// if (!m_IsMovingTextures) -// { -// m_TextureHandlePositionPrevious = pos; -// m_IsMovingTextures = true; -// } -// -// uvEditor.SceneMoveTool(pos - m_TextureHandlePositionPrevious); -// m_TextureHandlePositionPrevious = pos; -// uvEditor.Repaint(); -// } - } - - void TextureRotateTool() - { -// UVEditor uvEditor = UVEditor.instance; -// if (!uvEditor) return; -// -// float size = HandleUtility.GetHandleSize(m_HandlePosition); -// -// if (m_CurrentEvent.alt) return; -// -// Matrix4x4 prev = Handles.matrix; -// Handles.matrix = handleMatrix; -// -// Quaternion cached = m_TextureRotation; -// -// m_TextureRotation = Handles.Disc(m_TextureRotation, Vector3.zero, Vector3.forward, size, false, 0f); -// -// if (m_TextureRotation != cached) -// { -// if (!m_IsMovingTextures) -// m_IsMovingTextures = true; -// -// uvEditor.SceneRotateTool(-m_TextureRotation.eulerAngles.z); -// } -// -// Handles.matrix = prev; - } - - void TextureScaleTool() - { -// UVEditor uvEditor = UVEditor.instance; -// if (!uvEditor) return; -// -// float size = HandleUtility.GetHandleSize(m_HandlePosition); -// -// Matrix4x4 prev = Handles.matrix; -// Handles.matrix = handleMatrix; -// -// Vector3 cached = m_TextureScale; -// m_TextureScale = Handles.ScaleHandle(m_TextureScale, Vector3.zero, Quaternion.identity, size); -// -// if (m_CurrentEvent.alt) return; -// -// if (cached != m_TextureScale) -// { -// if (!m_IsMovingTextures) -// m_IsMovingTextures = true; -// -// uvEditor.SceneScaleTool(m_TextureScale, cached); -// } -// -// Handles.matrix = prev; - } - void DrawHandleGUI(SceneView sceneView) { if (sceneView != SceneView.lastActiveSceneView) diff --git a/com.unity.probuilder/Editor/EditorCore/TextureMoveTool.cs b/com.unity.probuilder/Editor/EditorCore/TextureMoveTool.cs new file mode 100644 index 000000000..5303085df --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/TextureMoveTool.cs @@ -0,0 +1,57 @@ +using UnityEngine; + +namespace UnityEditor.ProBuilder +{ + class TextureMoveTool : TextureTool + { + Vector3 m_Position = Vector3.zero; + + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) + { + if (!isEditing) + m_Position = Vector3.zero; + + EditorHandleUtility.PushMatrix(); + + Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one); + + EditorGUI.BeginChangeCheck(); + + m_Position = Handles.Slider(m_Position, Vector3.up); + + if (EditorGUI.EndChangeCheck()) + { + } + + EditorHandleUtility.PopMatrix(); + } + } +} + +// UVEditor uvEditor = UVEditor.instance; +// if (!uvEditor) return; +// +// Vector3 cached = m_TextureHandlePosition; +// +// m_TextureHandlePosition = Handles.PositionHandle(m_TextureHandlePosition, m_HandleRotation); +// +// if (m_CurrentEvent.alt) return; +// +// if (m_TextureHandlePosition != cached) +// { +// cached = Quaternion.Inverse(m_HandleRotation) * m_TextureHandlePosition; +// cached.y = -cached.y; +// +// Vector3 lossyScale = selection[0].transform.lossyScale; +// Vector3 pos = cached.DivideBy(lossyScale); +// +// if (!m_IsMovingTextures) +// { +// m_TextureHandlePositionPrevious = pos; +// m_IsMovingTextures = true; +// } +// +// uvEditor.SceneMoveTool(pos - m_TextureHandlePositionPrevious); +// m_TextureHandlePositionPrevious = pos; +// uvEditor.Repaint(); +// } diff --git a/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs.meta b/com.unity.probuilder/Editor/EditorCore/TextureMoveTool.cs.meta similarity index 83% rename from com.unity.probuilder/Editor/EditorCore/ScaleTool.cs.meta rename to com.unity.probuilder/Editor/EditorCore/TextureMoveTool.cs.meta index e203b5340..0e63e5018 100644 --- a/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs.meta +++ b/com.unity.probuilder/Editor/EditorCore/TextureMoveTool.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 9902f16875bf9cd4f99701f6d2721272 +guid: 7ebc93f048090074f80a100718d5a585 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.probuilder/Editor/EditorCore/TextureRotateTool.cs b/com.unity.probuilder/Editor/EditorCore/TextureRotateTool.cs new file mode 100644 index 000000000..dde9d569a --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/TextureRotateTool.cs @@ -0,0 +1,34 @@ +using UnityEngine; + +namespace UnityEditor.ProBuilder +{ + class TextureRotateTool : TextureTool + { + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) + { +// UVEditor uvEditor = UVEditor.instance; +// if (!uvEditor) return; +// +// float size = HandleUtility.GetHandleSize(m_HandlePosition); +// +// if (m_CurrentEvent.alt) return; +// +// Matrix4x4 prev = Handles.matrix; +// Handles.matrix = handleMatrix; +// +// Quaternion cached = m_TextureRotation; +// +// m_TextureRotation = Handles.Disc(m_TextureRotation, Vector3.zero, Vector3.forward, size, false, 0f); +// +// if (m_TextureRotation != cached) +// { +// if (!m_IsMovingTextures) +// m_IsMovingTextures = true; +// +// uvEditor.SceneRotateTool(-m_TextureRotation.eulerAngles.z); +// } +// +// Handles.matrix = prev; + } + } +} diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs.meta b/com.unity.probuilder/Editor/EditorCore/TextureRotateTool.cs.meta similarity index 83% rename from com.unity.probuilder/Editor/EditorCore/MoveTool.cs.meta rename to com.unity.probuilder/Editor/EditorCore/TextureRotateTool.cs.meta index fd3dd9ffe..a9d6d37fb 100644 --- a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs.meta +++ b/com.unity.probuilder/Editor/EditorCore/TextureRotateTool.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: c8e151d527dfd9f42b7ecd605b9d42cc +guid: 85900fb5729b6db42a6e417ad0d4c0f2 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs b/com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs new file mode 100644 index 000000000..043401797 --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs @@ -0,0 +1,33 @@ +using UnityEngine; + +namespace UnityEditor.ProBuilder +{ + class TextureScaleTool : TextureTool + { + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) + { +// UVEditor uvEditor = UVEditor.instance; +// if (!uvEditor) return; +// +// float size = HandleUtility.GetHandleSize(m_HandlePosition); +// +// Matrix4x4 prev = Handles.matrix; +// Handles.matrix = handleMatrix; +// +// Vector3 cached = m_TextureScale; +// m_TextureScale = Handles.ScaleHandle(m_TextureScale, Vector3.zero, Quaternion.identity, size); +// +// if (m_CurrentEvent.alt) return; +// +// if (cached != m_TextureScale) +// { +// if (!m_IsMovingTextures) +// m_IsMovingTextures = true; +// +// uvEditor.SceneScaleTool(m_TextureScale, cached); +// } +// +// Handles.matrix = prev; + } + } +} diff --git a/com.unity.probuilder/Editor/EditorCore/RotateTool.cs.meta b/com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs.meta similarity index 83% rename from com.unity.probuilder/Editor/EditorCore/RotateTool.cs.meta rename to com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs.meta index 2d4474ff0..583b85f9f 100644 --- a/com.unity.probuilder/Editor/EditorCore/RotateTool.cs.meta +++ b/com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: ad47c69dfccd598478ddc2368ca5a5d6 +guid: ffea9638e10c9644aab23c2652f86279 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.probuilder/Editor/EditorCore/TextureTool.cs b/com.unity.probuilder/Editor/EditorCore/TextureTool.cs new file mode 100644 index 000000000..30a2aca52 --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/TextureTool.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.ProBuilder; + +namespace UnityEditor.ProBuilder +{ + class TextureTool : VertexManipulationTool + { + class MeshAndTextures : MeshAndElementGroupPair + { + List m_Textures; + + public MeshAndTextures(ProBuilderMesh mesh, PivotPoint pivot) + : base(mesh, pivot) + { + + } + } + + Matrix4x4 m_HandleMatrix; + + protected void PushMatrix() + { + m_HandleMatrix = Handles.matrix; + } + + protected void PopMatrix() + { + m_HandleMatrix = Handles.matrix; + } + + protected override MeshAndElementGroupPair GetMeshAndElementGroupPair(ProBuilderMesh mesh, PivotPoint pivot) + { + return new MeshAndTextures(mesh, pivot); + } + + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { } + } +} diff --git a/com.unity.probuilder/Editor/EditorCore/TextureTool.cs.meta b/com.unity.probuilder/Editor/EditorCore/TextureTool.cs.meta new file mode 100644 index 000000000..600f166bc --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/TextureTool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7fd9f5ac1b5cea54386d6497a518c29f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs index a71daad42..1f30c53fe 100644 --- a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs @@ -13,37 +13,25 @@ namespace UnityEditor.ProBuilder { - struct MeshAndElementSelection + abstract class MeshAndElementGroupPair { ProBuilderMesh m_Mesh; - Vector3[] m_Positions; - List m_Selection; + List m_ElementGroups; public ProBuilderMesh mesh { get { return m_Mesh; } } - public Vector3[] positions + public List elementGroups { - get { return m_Positions; } + get { return m_ElementGroups; } } - public List selection - { - get { return m_Selection; } - } - - public MeshAndElementSelection(ProBuilderMesh mesh, PivotPoint pivot) + public MeshAndElementGroupPair(ProBuilderMesh mesh, PivotPoint pivot) { m_Mesh = mesh; - m_Positions = mesh.positions.ToArray(); - var l2w = m_Mesh.transform.localToWorldMatrix; - for (int i = 0, c = m_Positions.Length; i < c; i++) - m_Positions[i] = l2w.MultiplyPoint3x4(m_Positions[i]); - var groups = new List(); - ElementGroup.GetElementGroups(mesh, pivot, groups); - m_Selection = groups; + m_ElementGroups = ElementGroup.GetElementGroups(mesh, pivot); } } @@ -68,6 +56,13 @@ public Matrix4x4 inverseMatrix get { return m_PostApplyPositionsMatrix; } } + public static List GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot) + { + var groups = new List(); + GetElementGroups(mesh, pivot, groups); + return groups; + } + public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List groups) { var trs = mesh.transform.localToWorldMatrix; @@ -130,7 +125,7 @@ public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List< } } - internal static List> GetFaceSelectionGroups(ProBuilderMesh mesh) + static List> GetFaceSelectionGroups(ProBuilderMesh mesh) { var wings = WingedEdge.GetWingedEdges(mesh, mesh.selectedFacesInternal, true); var filter = new HashSet(); @@ -185,6 +180,8 @@ abstract class VertexManipulationTool Quaternion m_HandleRotation; Vector3 m_HandlePositionOrigin; Quaternion m_HandleRotationOrigin; + List m_MeshAndElementGroupPairs = new List(); + bool m_IsEditing; float m_SnapValue = .25f; bool m_SnapAxisConstraint = true; @@ -194,6 +191,11 @@ abstract class VertexManipulationTool static MethodInfo s_FindNearestVertex; static object[] s_FindNearestVertexArguments = new object[] { null, null, null }; + protected IEnumerable meshAndElementGroupPairs + { + get { return m_MeshAndElementGroupPairs; } + } + protected static bool vertexDragging { get @@ -203,8 +205,10 @@ protected static bool vertexDragging } } - protected List m_Selection = new List(); - protected bool m_IsEditing; + protected bool isEditing + { + get { return m_IsEditing; } + } protected Event currentEvent { get; private set; } @@ -247,6 +251,8 @@ static void Init() BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance); } + protected abstract MeshAndElementGroupPair GetMeshAndElementGroupPair(ProBuilderMesh mesh, PivotPoint pivot); + public void OnSceneGUI(Event evt) { currentEvent = evt; @@ -270,9 +276,9 @@ public void OnSceneGUI(Event evt) { if (evt.type == EventType.Repaint) { - foreach (var key in m_Selection) + foreach (var key in m_MeshAndElementGroupPairs) { - foreach (var group in key.selection) + foreach (var group in key.elementGroups) { #if DEBUG_HANDLES using (var faceDrawer = new EditorMeshHandles.TriangleDrawingScope(Color.cyan, CompareFunction.Always)) @@ -305,6 +311,7 @@ public void OnSceneGUI(Event evt) protected abstract void DoTool(Vector3 handlePosition, Quaternion handleRotation); protected virtual void OnToolEngaged() { } + protected virtual void OnToolDisengaged() { } protected void BeginEdit(string undoMessage) @@ -341,10 +348,10 @@ protected void BeginEdit(string undoMessage) mesh.Refresh(); } - m_Selection.Clear(); + m_MeshAndElementGroupPairs.Clear(); foreach (var mesh in MeshSelection.topInternal) - m_Selection.Add(new MeshAndElementSelection(mesh, pivotPoint)); + m_MeshAndElementGroupPairs.Add(GetMeshAndElementGroupPair(mesh, pivotPoint)); OnToolEngaged(); } @@ -375,33 +382,6 @@ protected void FinishEdit() OnToolDisengaged(); } - protected void Apply(Matrix4x4 delta) - { - foreach (var key in m_Selection) - { - var mesh = key.mesh; - var worldToLocal = mesh.transform.worldToLocalMatrix; - var origins = key.positions; - var positions = mesh.positionsInternal; - - foreach (var group in key.selection) - { - foreach (var index in group.indices) - { - positions[index] = worldToLocal.MultiplyPoint3x4( - group.inverseMatrix.MultiplyPoint3x4( - delta.MultiplyPoint3x4(group.matrix.MultiplyPoint3x4(origins[index])))); - } - } - - mesh.mesh.vertices = positions; - mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); - mesh.Refresh(RefreshMask.Normals); - } - - ProBuilderEditor.UpdateMeshHandles(false); - } - static void Extrude() { int ef = 0; diff --git a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexMoveTool.cs similarity index 96% rename from com.unity.probuilder/Editor/EditorCore/MoveTool.cs rename to com.unity.probuilder/Editor/EditorCore/VertexMoveTool.cs index e24563367..742f1a309 100644 --- a/com.unity.probuilder/Editor/EditorCore/MoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexMoveTool.cs @@ -3,7 +3,7 @@ namespace UnityEditor.ProBuilder { - class MoveTool : VertexManipulationTool + class VertexMoveTool : VertexTool { const float k_CardinalAxisError = .001f; Vector3 m_HandlePosition; @@ -21,7 +21,7 @@ protected override void OnToolEngaged() protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { - if (!m_IsEditing) + if (!isEditing) m_HandlePosition = handlePosition; EditorGUI.BeginChangeCheck(); @@ -30,7 +30,7 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation if (EditorGUI.EndChangeCheck()) { - if (!m_IsEditing) + if (!isEditing) BeginEdit("Translate Selection"); var delta = m_HandlePosition - handlePositionOrigin; diff --git a/com.unity.probuilder/Editor/EditorCore/VertexMoveTool.cs.meta b/com.unity.probuilder/Editor/EditorCore/VertexMoveTool.cs.meta new file mode 100644 index 000000000..0afaadb7f --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/VertexMoveTool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7ac1a3f68899bd64391da168c4badfab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.probuilder/Editor/EditorCore/RotateTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexRotateTool.cs similarity index 88% rename from com.unity.probuilder/Editor/EditorCore/RotateTool.cs rename to com.unity.probuilder/Editor/EditorCore/VertexRotateTool.cs index 367f85dea..0a03c7f63 100644 --- a/com.unity.probuilder/Editor/EditorCore/RotateTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexRotateTool.cs @@ -3,7 +3,7 @@ namespace UnityEditor.ProBuilder { - class RotateTool : VertexManipulationTool + class VertexRotateTool : VertexTool { Quaternion m_Rotation; @@ -13,7 +13,7 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation { EditorGUI.BeginChangeCheck(); - if (!m_IsEditing) + if (!isEditing) m_Rotation = Quaternion.identity; var hm = Handles.matrix; @@ -23,7 +23,7 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation if (EditorGUI.EndChangeCheck()) { - if (!m_IsEditing) + if (!isEditing) BeginEdit("Rotate Selection"); Apply(Matrix4x4.Rotate(m_Rotation)); @@ -33,14 +33,14 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation { EditorGUI.BeginChangeCheck(); - if (!m_IsEditing) + if (!isEditing) m_Rotation = handleRotation; m_Rotation = Handles.RotationHandle(m_Rotation, handlePosition); if (EditorGUI.EndChangeCheck()) { - if (!m_IsEditing) + if (!isEditing) BeginEdit("Rotate Selection"); Apply(Matrix4x4.Rotate(m_Rotation * Quaternion.Inverse(handleRotationOrigin))); diff --git a/com.unity.probuilder/Editor/EditorCore/VertexRotateTool.cs.meta b/com.unity.probuilder/Editor/EditorCore/VertexRotateTool.cs.meta new file mode 100644 index 000000000..605e26831 --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/VertexRotateTool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 889d171485914ca429a6b43878cb11ba +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexScaleTool.cs similarity index 84% rename from com.unity.probuilder/Editor/EditorCore/ScaleTool.cs rename to com.unity.probuilder/Editor/EditorCore/VertexScaleTool.cs index 49177a0cf..afc597b6b 100644 --- a/com.unity.probuilder/Editor/EditorCore/ScaleTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexScaleTool.cs @@ -2,13 +2,13 @@ namespace UnityEditor.ProBuilder { - class ScaleTool : VertexManipulationTool + class VertexScaleTool : VertexTool { Vector3 m_Scale; protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { - if (!m_IsEditing) + if (!isEditing) m_Scale = Vector3.one; EditorGUI.BeginChangeCheck(); @@ -17,7 +17,7 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation if (EditorGUI.EndChangeCheck()) { - if (!m_IsEditing) + if (!isEditing) BeginEdit("Scale Selection"); Apply(Matrix4x4.Scale(m_Scale)); diff --git a/com.unity.probuilder/Editor/EditorCore/VertexScaleTool.cs.meta b/com.unity.probuilder/Editor/EditorCore/VertexScaleTool.cs.meta new file mode 100644 index 000000000..e3b8aa8b1 --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/VertexScaleTool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 927abaf88d2d91448bf4d9cd53201db3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.probuilder/Editor/EditorCore/VertexTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexTool.cs new file mode 100644 index 000000000..53fbcbe4c --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/VertexTool.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.ProBuilder; + +namespace UnityEditor.ProBuilder +{ + abstract class VertexTool : VertexManipulationTool + { + class MeshAndPositions : MeshAndElementGroupPair + { + Vector3[] m_Positions; + + public Vector3[] positions + { + get { return m_Positions; } + } + + public MeshAndPositions(ProBuilderMesh mesh, PivotPoint pivot) : base(mesh, pivot) + { + m_Positions = mesh.positions.ToArray(); + + var l2w = mesh.transform.localToWorldMatrix; + + for (int i = 0, c = m_Positions.Length; i < c; i++) + m_Positions[i] = l2w.MultiplyPoint3x4(m_Positions[i]); + } + } + + protected override MeshAndElementGroupPair GetMeshAndElementGroupPair (ProBuilderMesh mesh, PivotPoint pivot) + { + return new MeshAndPositions(mesh, pivot); + } + + protected void Apply(Matrix4x4 delta) + { + foreach (var key in meshAndElementGroupPairs) + { + if (!(key is MeshAndPositions)) + continue; + + var kvp = (MeshAndPositions)key; + var mesh = kvp.mesh; + var worldToLocal = mesh.transform.worldToLocalMatrix; + var origins = kvp.positions; + var positions = mesh.positionsInternal; + + foreach (var group in kvp.elementGroups) + { + foreach (var index in group.indices) + { + positions[index] = worldToLocal.MultiplyPoint3x4( + group.inverseMatrix.MultiplyPoint3x4( + delta.MultiplyPoint3x4(group.matrix.MultiplyPoint3x4(origins[index])))); + } + } + + mesh.mesh.vertices = positions; + mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]); + mesh.Refresh(RefreshMask.Normals); + } + + ProBuilderEditor.UpdateMeshHandles(false); + } + } +} diff --git a/com.unity.probuilder/Editor/EditorCore/VertexTool.cs.meta b/com.unity.probuilder/Editor/EditorCore/VertexTool.cs.meta new file mode 100644 index 000000000..cac286e0e --- /dev/null +++ b/com.unity.probuilder/Editor/EditorCore/VertexTool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 17514a8c8f75b3d4bb1d7a05d557b5c2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 54680eb86284ccba136a907344dd66601e969d01 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Tue, 30 Oct 2018 16:38:22 -0400 Subject: [PATCH 21/27] implement texture tools --- .../Editor/EditorCore/EditorGUIUtility.cs | 86 +++++++++++++++ .../Editor/EditorCore/EditorMeshHandles.cs | 9 ++ .../EditorCore/EditorSceneViewPicker.cs | 10 +- .../Editor/EditorCore/EditorToolbarLoader.cs | 2 +- .../EditorCore/EditorToolbarMenuItems.cs | 4 +- .../Editor/EditorCore/EditorUtility.cs | 65 ++++++++++- .../Editor/EditorCore/ProBuilderEditor.cs | 95 +++++----------- .../Editor/EditorCore/TextureMoveTool.cs | 83 +++++++++----- .../Editor/EditorCore/TextureRotateTool.cs | 77 +++++++++---- .../Editor/EditorCore/TextureScaleTool.cs | 86 +++++++++++---- .../Editor/EditorCore/TextureTool.cs | 101 +++++++++++++++--- .../Editor/EditorCore/UVEditor.cs | 71 ++++-------- .../EditorCore/VertexManipulationTool.cs | 99 ++++++++--------- .../Editor/EditorCore/VertexMoveTool.cs | 8 +- .../Editor/EditorCore/VertexRotateTool.cs | 2 + .../Editor/EditorCore/VertexScaleTool.cs | 2 + .../Editor/EditorCore/VertexTool.cs | 36 ++++++- ...lignment.cs => ToggleHandleOrientation.cs} | 9 +- ...s.meta => ToggleHandleOrientation.cs.meta} | 5 +- com.unity.probuilder/Runtime/Core/Bounds2D.cs | 33 +++++- .../Runtime/Core/ProBuilderEnum.cs | 12 ++- 21 files changed, 611 insertions(+), 284 deletions(-) rename com.unity.probuilder/Editor/MenuActions/Interaction/{ToggleHandleAlignment.cs => ToggleHandleOrientation.cs} (94%) rename com.unity.probuilder/Editor/MenuActions/Interaction/{ToggleHandleAlignment.cs.meta => ToggleHandleOrientation.cs.meta} (69%) diff --git a/com.unity.probuilder/Editor/EditorCore/EditorGUIUtility.cs b/com.unity.probuilder/Editor/EditorCore/EditorGUIUtility.cs index fcca88f47..accec5f26 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorGUIUtility.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorGUIUtility.cs @@ -13,6 +13,43 @@ namespace UnityEditor.ProBuilder.UI /// static class EditorGUIUtility { + static class Styles + { + static bool s_Initialized; + + public static GUIStyle command = "command"; + public static GUIContent[] selectModeIcons; + + public static void Init() + { + if (s_Initialized) + return; + + s_Initialized = true; + + var object_Graphic_off = IconUtility.GetIcon("Modes/Mode_Object"); + var face_Graphic_off = IconUtility.GetIcon("Modes/Mode_Face"); + var vertex_Graphic_off = IconUtility.GetIcon("Modes/Mode_Vertex"); + var edge_Graphic_off = IconUtility.GetIcon("Modes/Mode_Edge"); + + selectModeIcons = new GUIContent[] + { + object_Graphic_off != null + ? new GUIContent(object_Graphic_off, "Object Selection") + : new GUIContent("OBJ", "Object Selection"), + vertex_Graphic_off != null + ? new GUIContent(vertex_Graphic_off, "Vertex Selection") + : new GUIContent("VRT", "Vertex Selection"), + edge_Graphic_off != null + ? new GUIContent(edge_Graphic_off, "Edge Selection") + : new GUIContent("EDG", "Edge Selection"), + face_Graphic_off != null + ? new GUIContent(face_Graphic_off, "Face Selection") + : new GUIContent("FCE", "Face Selection"), + }; + } + } + static readonly Color TOOL_SETTINGS_COLOR = UnityEditor.EditorGUIUtility.isProSkin ? Color.green : new Color(.2f, .2f, .2f, .2f); @@ -379,5 +416,54 @@ public static void SceneLabel(string text, Vector2 position) GUI.Label(sceneLabelRect, gc, sceneBoldLabel); } + + public static SelectMode DoElementModeToolbar(Rect rect, SelectMode mode) + { + Styles.Init(); + + EditorGUI.BeginChangeCheck(); + + var textureMode = mode.ContainsFlag(SelectMode.TextureVertex | SelectMode.TextureEdge | SelectMode.TextureFace); + + int currentSelectionMode = -1; + + switch (mode) + { + case SelectMode.Object: + currentSelectionMode = 0; + break; + case SelectMode.Vertex: + case SelectMode.TextureVertex: + currentSelectionMode = 1; + break; + case SelectMode.Edge: + case SelectMode.TextureEdge: + currentSelectionMode = 2; + break; + case SelectMode.Face: + case SelectMode.TextureFace: + currentSelectionMode = 3; + break; + default: + currentSelectionMode = -1; + break; + } + + currentSelectionMode = GUI.Toolbar(rect, currentSelectionMode, Styles.selectModeIcons, Styles.command); + + if (EditorGUI.EndChangeCheck()) + { + if (currentSelectionMode == 0) + mode = SelectMode.Object; + else if (currentSelectionMode == 1) + mode = textureMode ? SelectMode.TextureVertex : SelectMode.Vertex; + else if (currentSelectionMode == 2) + mode = textureMode ? SelectMode.TextureEdge : SelectMode.Edge; + else if (currentSelectionMode == 3) + mode = textureMode ? SelectMode.TextureFace : SelectMode.Face; + } + + return mode; + } } } diff --git a/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs b/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs index ca17d9120..fbe65ba4f 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorMeshHandles.cs @@ -310,6 +310,7 @@ public void DrawSceneHandles(SelectMode mode) switch (mode) { case SelectMode.Edge: + case SelectMode.TextureEdge: { // render wireframe with edge material in edge mode so that the size change is reflected RenderWithColor(m_WireHandles, m_EdgeMaterial, s_EdgeUnselectedColor); @@ -317,12 +318,14 @@ public void DrawSceneHandles(SelectMode mode) break; } case SelectMode.Face: + case SelectMode.TextureFace: { RenderWithColor(m_WireHandles, m_WireMaterial, s_WireframeColor); RenderWithColor(m_SelectedFaceHandles, s_FaceMaterial, s_FaceSelectedColor); break; } case SelectMode.Vertex: + case SelectMode.TextureVertex: { RenderWithColor(m_WireHandles, m_WireMaterial, s_WireframeColor); RenderWithColor(m_VertexHandles, m_VertMaterial, s_VertexUnselectedColor); @@ -367,6 +370,7 @@ public void RebuildSelectedHandles(IEnumerable meshes, SelectMod switch (selectionMode) { case SelectMode.Vertex: + case SelectMode.TextureVertex: { foreach (var handle in m_VertexHandles) handle.Value.mesh.vertices = handle.Key.positionsInternal; @@ -376,6 +380,7 @@ public void RebuildSelectedHandles(IEnumerable meshes, SelectMod } case SelectMode.Edge: + case SelectMode.TextureEdge: { foreach (var handle in m_SelectedEdgeHandles) handle.Value.mesh.vertices = handle.Key.positionsInternal; @@ -383,6 +388,7 @@ public void RebuildSelectedHandles(IEnumerable meshes, SelectMod } case SelectMode.Face: + case SelectMode.TextureFace: { foreach (var handle in m_SelectedFaceHandles) handle.Value.mesh.vertices = handle.Key.positionsInternal; @@ -403,6 +409,7 @@ public void RebuildSelectedHandles(IEnumerable meshes, SelectMod switch (selectionMode) { case SelectMode.Vertex: + case SelectMode.TextureVertex: { RebuildMeshHandle(mesh, m_VertexHandles, MeshHandles.CreateVertexMesh); @@ -414,6 +421,7 @@ public void RebuildSelectedHandles(IEnumerable meshes, SelectMod } case SelectMode.Edge: + case SelectMode.TextureEdge: { RebuildMeshHandle(mesh, m_SelectedEdgeHandles, (x, y) => { @@ -423,6 +431,7 @@ public void RebuildSelectedHandles(IEnumerable meshes, SelectMod } case SelectMode.Face: + case SelectMode.TextureFace: { RebuildMeshHandle(mesh, m_SelectedFaceHandles, MeshHandles.CreateFaceMesh); break; diff --git a/com.unity.probuilder/Editor/EditorCore/EditorSceneViewPicker.cs b/com.unity.probuilder/Editor/EditorCore/EditorSceneViewPicker.cs index 7d5649c26..7100a42be 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorSceneViewPicker.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorSceneViewPicker.cs @@ -160,9 +160,9 @@ public static ProBuilderMesh DoMouseClick(Event evt, SelectMode selectionMode, S float pickedElementDistance = Mathf.Infinity; - if (selectionMode == SelectMode.Edge) + if (selectionMode.ContainsFlag(SelectMode.Edge | SelectMode.TextureEdge)) pickedElementDistance = EdgeRaycast(evt.mousePosition, pickerPreferences, true, s_Selection); - else if (selectionMode == SelectMode.Vertex) + else if (selectionMode.ContainsFlag(SelectMode.Vertex | SelectMode.TextureVertex)) pickedElementDistance = VertexRaycast(evt.mousePosition, pickerPreferences, true, s_Selection); else pickedElementDistance = FaceRaycast(evt.mousePosition, pickerPreferences, true, s_Selection, evt.clickCount > 1 ? -1 : 0, false); @@ -257,6 +257,7 @@ public static void DoMouseDrag(Rect mouseDragRect, SelectMode selectionMode, Sce switch (selectionMode) { case SelectMode.Vertex: + case SelectMode.TextureVertex: { Dictionary> selected = Picking.PickVerticesInRect( SceneView.lastActiveSceneView.camera, @@ -332,6 +333,7 @@ public static void DoMouseDrag(Rect mouseDragRect, SelectMode selectionMode, Sce } case SelectMode.Edge: + case SelectMode.TextureEdge: { var selected = Picking.PickEdgesInRect( SceneView.lastActiveSceneView.camera, @@ -389,10 +391,10 @@ internal static float MouseRayHitTest( SceneSelection selection, bool allowUnselected = false) { - if (selectionMode == SelectMode.Edge) + if (selectionMode.ContainsFlag(SelectMode.Edge | SelectMode.TextureEdge)) return EdgeRaycast(mousePosition, pickerOptions, allowUnselected, selection); - if (selectionMode == SelectMode.Vertex) + if (selectionMode.ContainsFlag(SelectMode.Vertex | SelectMode.TextureVertex)) return VertexRaycast(mousePosition, pickerOptions, allowUnselected, selection); return FaceRaycast(mousePosition, pickerOptions, allowUnselected, selection, 0, true); diff --git a/com.unity.probuilder/Editor/EditorCore/EditorToolbarLoader.cs b/com.unity.probuilder/Editor/EditorCore/EditorToolbarLoader.cs index abb10bf6c..60c78ca42 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorToolbarLoader.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorToolbarLoader.cs @@ -48,7 +48,7 @@ internal static List GetActions(bool forceReload = false) new Actions.OpenSmoothingEditor(), new Actions.ToggleSelectBackFaces(), - new Actions.ToggleHandleAlignment(), + new Actions.ToggleHandleOrientation(), new Actions.ToggleDragSelectionMode(), new Actions.ToggleDragRectMode(), diff --git a/com.unity.probuilder/Editor/EditorCore/EditorToolbarMenuItems.cs b/com.unity.probuilder/Editor/EditorCore/EditorToolbarMenuItems.cs index 3f11c3e20..a5f3ba2fb 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorToolbarMenuItems.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorToolbarMenuItems.cs @@ -606,7 +606,7 @@ static void MenuDoToggleDragSelectionMode() [MenuItem(k_MenuPrefix + "Interaction/Toggle Handle Alignment [p]", true)] static bool MenuVerifyToggleHandleAlignment() { - ToggleHandleAlignment instance = EditorToolbarLoader.GetInstance(); + ToggleHandleOrientation instance = EditorToolbarLoader.GetInstance(); return instance != null && instance.enabled; @@ -615,7 +615,7 @@ static bool MenuVerifyToggleHandleAlignment() [MenuItem(k_MenuPrefix + "Interaction/Toggle Handle Alignment [p]", false, PreferenceKeys.menuSelection + 1)] static void MenuDoToggleHandleAlignment() { - ToggleHandleAlignment instance = EditorToolbarLoader.GetInstance(); + ToggleHandleOrientation instance = EditorToolbarLoader.GetInstance(); if(instance != null) UnityEditor.ProBuilder.EditorUtility.ShowNotification(instance.DoAction().notification); } diff --git a/com.unity.probuilder/Editor/EditorCore/EditorUtility.cs b/com.unity.probuilder/Editor/EditorCore/EditorUtility.cs index 3604db851..40e76cf42 100644 --- a/com.unity.probuilder/Editor/EditorCore/EditorUtility.cs +++ b/com.unity.probuilder/Editor/EditorCore/EditorUtility.cs @@ -480,10 +480,71 @@ internal static void CreateCachedEditor(UnityEngine.Object[] targetObjects, r /// internal static bool IsMeshElementMode(this SelectMode mode) { - return mode.ContainsFlag(SelectMode.Vertex | SelectMode.Edge | SelectMode.Face | SelectMode.TextureFace); + return mode.ContainsFlag( + SelectMode.Vertex + | SelectMode.Edge + | SelectMode.Face + | SelectMode.TextureEdge + | SelectMode.TextureFace + | SelectMode.TextureVertex + ); } - // HasFlag doesn't exist in .NET 3.5 + internal static bool IsTextureMode(this SelectMode mode) + { + return mode.ContainsFlag( + SelectMode.TextureEdge + | SelectMode.TextureFace + | SelectMode.TextureVertex + ); + } + + internal static bool IsPositionMode(this SelectMode mode) + { + return mode.ContainsFlag( + SelectMode.TextureEdge + | SelectMode.TextureFace + | SelectMode.TextureVertex + ); + } + + internal static SelectMode GetPositionMode(this SelectMode mode) + { + if (mode.ContainsFlag(SelectMode.TextureFace)) + mode = (mode & ~SelectMode.TextureFace) | SelectMode.Face; + + if (mode.ContainsFlag(SelectMode.TextureEdge)) + mode = (mode & ~SelectMode.TextureEdge) | SelectMode.Edge; + + if (mode.ContainsFlag(SelectMode.TextureVertex)) + mode = (mode & ~SelectMode.TextureVertex) | SelectMode.Vertex; + + return mode; + } + + internal static SelectMode GetTextureMode(this SelectMode mode) + { + if (mode.ContainsFlag(SelectMode.Face)) + mode = (mode & ~SelectMode.Face) | SelectMode.TextureFace; + + if (mode.ContainsFlag(SelectMode.Edge)) + mode = (mode & ~SelectMode.Edge) | SelectMode.TextureEdge; + + if (mode.ContainsFlag(SelectMode.Vertex)) + mode = (mode & ~SelectMode.Vertex) | SelectMode.TextureVertex; + + return mode; + } + + /// + /// Test if SelectMode contains any of the value bits. + /// + /// + /// HasFlag doesn't exist in .NET 3.5 + /// + /// + /// + /// internal static bool ContainsFlag(this SelectMode target, SelectMode value) { return (target & value) != SelectMode.None; diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index ebefe5890..69f6dacc9 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -123,6 +123,7 @@ internal bool backfaceSelectionEnabled // used for 'g' key shortcut to swap between object/vef modes SelectMode m_LastComponentMode; HandleOrientation m_PreviousHandleOrientation; + PivotMode m_PreviousHandlePivot; [UserSetting] static internal Pref s_Shortcuts = new Pref("editor.sceneViewShortcuts", Shortcut.DefaultShortcuts().ToArray()); GUIStyle m_CommandStyle; @@ -208,6 +209,9 @@ public static SelectMode selectMode if (previous == value) return; + var wasTextureMode = previous.ContainsFlag(SelectMode.TextureEdge | SelectMode.TextureVertex | SelectMode.TextureFace); + var isTextureMode = value.ContainsFlag(SelectMode.TextureEdge | SelectMode.TextureVertex | SelectMode.TextureFace); + s_Instance.m_SelectMode.SetValue(value, true); if (previous == SelectMode.Edge || previous == SelectMode.Vertex || previous == SelectMode.Face) @@ -216,11 +220,23 @@ public static SelectMode selectMode if (value == SelectMode.Object) Tools.current = s_Instance.m_CurrentTool; - if (value == SelectMode.TextureFace) + if (!wasTextureMode && isTextureMode) + { + s_Instance.m_PreviousHandlePivot = Tools.pivotMode; s_Instance.m_PreviousHandleOrientation = s_HandleOrientation; - if (previous == SelectMode.TextureFace) - handleOrientation = s_Instance.m_PreviousHandleOrientation; + Tools.pivotMode = PivotMode.Pivot; + handleOrientation = HandleOrientation.Normal; + } + else if(wasTextureMode && !isTextureMode) + { + if (Tools.pivotMode == PivotMode.Pivot + && handleOrientation == HandleOrientation.Normal) + { + Tools.pivotMode = s_Instance.m_PreviousHandlePivot; + handleOrientation = s_Instance.m_PreviousHandleOrientation; + } + } if (selectModeChanged != null) selectModeChanged(value); @@ -406,27 +422,6 @@ void InitGUI() VertexTranslationInfoStyle.normal.background = EditorGUIUtility.whiteTexture; VertexTranslationInfoStyle.normal.textColor = new Color(1f, 1f, 1f, .6f); VertexTranslationInfoStyle.padding = new RectOffset(3, 3, 3, 0); - - var object_Graphic_off = IconUtility.GetIcon("Modes/Mode_Object"); - var face_Graphic_off = IconUtility.GetIcon("Modes/Mode_Face"); - var vertex_Graphic_off = IconUtility.GetIcon("Modes/Mode_Vertex"); - var edge_Graphic_off = IconUtility.GetIcon("Modes/Mode_Edge"); - - m_EditModeIcons = new GUIContent[] - { - object_Graphic_off != null - ? new GUIContent(object_Graphic_off, "Object Selection") - : new GUIContent("OBJ", "Object Selection"), - vertex_Graphic_off != null - ? new GUIContent(vertex_Graphic_off, "Vertex Selection") - : new GUIContent("VRT", "Vertex Selection"), - edge_Graphic_off != null - ? new GUIContent(edge_Graphic_off, "Edge Selection") - : new GUIContent("EDG", "Edge Selection"), - face_Graphic_off != null - ? new GUIContent(face_Graphic_off, "Face Selection") - : new GUIContent("FCE", "Face Selection"), - }; } /// @@ -567,7 +562,7 @@ void OnSceneGUI(SceneView sceneView) // Check mouse position in scene and determine if we should highlight something if (s_ShowHoverHighlight && m_CurrentEvent.type == EventType.MouseMove - && selectMode.ContainsFlag(SelectMode.Face | SelectMode.Edge | SelectMode.Vertex | SelectMode.TextureFace)) + && selectMode.IsMeshElementMode()) { m_Hovering.CopyTo(m_HoveringPrevious); @@ -589,11 +584,11 @@ void OnSceneGUI(SceneView sceneView) Tools.current = Tool.None; - if (selectMode.ContainsFlag(SelectMode.Vertex | SelectMode.Edge | SelectMode.Face | SelectMode.TextureFace)) + if (selectMode.IsMeshElementMode()) { if (MeshSelection.selectedVertexCount > 0) { - if (selectMode == SelectMode.TextureFace) + if (selectMode.IsTextureMode()) { switch (m_CurrentTool) { @@ -601,10 +596,10 @@ void OnSceneGUI(SceneView sceneView) GetTool().OnSceneGUI(m_CurrentEvent); break; case Tool.Rotate: -// GetTool().OnSceneGUI(m_CurrentEvent); + GetTool().OnSceneGUI(m_CurrentEvent); break; case Tool.Scale: -// GetTool().OnSceneGUI(m_CurrentEvent); + GetTool().OnSceneGUI(m_CurrentEvent); break; } } @@ -711,14 +706,14 @@ void DoubleClick(Event e) if (mesh != null) { - if (selectMode == SelectMode.Edge) + if (selectMode.ContainsFlag(SelectMode.Edge | SelectMode.TextureEdge)) { if (e.shift) EditorUtility.ShowNotification(EditorToolbarLoader.GetInstance().DoAction()); else EditorUtility.ShowNotification(EditorToolbarLoader.GetInstance().DoAction()); } - else if (selectMode == SelectMode.Face) + else if (selectMode.ContainsFlag(SelectMode.Face | SelectMode.TextureFace)) { if ((e.modifiers & (EventModifiers.Control | EventModifiers.Shift)) == (EventModifiers.Control | EventModifiers.Shift)) @@ -768,27 +763,6 @@ void DrawHandleGUI(SceneView sceneView) int screenWidth = (int) sceneView.position.width; int screenHeight = (int) sceneView.position.height; - int currentSelectionMode = -1; - - switch (m_SelectMode.value) - { - case SelectMode.Object: - currentSelectionMode = 0; - break; - case SelectMode.Vertex: - currentSelectionMode = 1; - break; - case SelectMode.Edge: - currentSelectionMode = 2; - break; - case SelectMode.Face: - currentSelectionMode = 3; - break; - default: - currentSelectionMode = -1; - break; - } - switch ((SceneToolbarLocation) s_SceneToolbarLocation) { case SceneToolbarLocation.BottomCenter: @@ -823,22 +797,7 @@ void DrawHandleGUI(SceneView sceneView) break; } - EditorGUI.BeginChangeCheck(); - - currentSelectionMode = - GUI.Toolbar(m_ElementModeToolbarRect, (int) currentSelectionMode, m_EditModeIcons, m_CommandStyle); - - if (EditorGUI.EndChangeCheck()) - { - if (currentSelectionMode == 0) - selectMode = SelectMode.Object; - else if (currentSelectionMode == 1) - selectMode = SelectMode.Vertex; - else if (currentSelectionMode == 2) - selectMode = SelectMode.Edge; - else if (currentSelectionMode == 3) - selectMode = SelectMode.Face; - } + m_SelectMode.value = UI.EditorGUIUtility.DoElementModeToolbar(m_ElementModeToolbarRect, m_SelectMode); // todo Move to VertexManipulationTool // if (m_IsMovingElements && s_ShowSceneInfo) diff --git a/com.unity.probuilder/Editor/EditorCore/TextureMoveTool.cs b/com.unity.probuilder/Editor/EditorCore/TextureMoveTool.cs index 5303085df..61c8329c6 100644 --- a/com.unity.probuilder/Editor/EditorCore/TextureMoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/TextureMoveTool.cs @@ -1,4 +1,5 @@ using UnityEngine; +using UnityEngine.ProBuilder; namespace UnityEditor.ProBuilder { @@ -17,41 +18,67 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation EditorGUI.BeginChangeCheck(); + Handles.color = Color.blue; + + m_Position = Handles.Slider2D(m_Position, + Vector3.forward, + Vector3.right, + Vector3.up, + HandleUtility.GetHandleSize(m_Position) * .2f, + Handles.RectangleHandleCap, + 0f, + false); + + Handles.color = Color.green; + m_Position = Handles.Slider(m_Position, Vector3.up); + Handles.color = Color.red; + + m_Position = Handles.Slider(m_Position, Vector3.right); + + Handles.color = Color.white; + if (EditorGUI.EndChangeCheck()) { + if(!isEditing) + BeginEdit("Translate Textures"); + + if (relativeSnapEnabled) + { + m_Position.x = Snapping.SnapValue(m_Position.x, relativeSnapX); + m_Position.y = Snapping.SnapValue(m_Position.y, relativeSnapY); + } + else if (progridsSnapEnabled) + { + m_Position.x = Snapping.SnapValue(m_Position.x, progridsSnapValue); + m_Position.y = Snapping.SnapValue(m_Position.y, progridsSnapValue); + } + + // invert `y` because to users it's confusing that "up" in UV space visually moves the texture down + var delta = new Vector4(m_Position.x, -m_Position.y, 0f, 0f); + + foreach (var mesh in meshAndElementGroupPairs) + { + if (!(mesh is MeshAndTextures)) + continue; + + delta *= 1f / mesh.mesh.transform.lossyScale.magnitude; + + var origins = ((MeshAndTextures)mesh).origins; + var positions = ((MeshAndTextures)mesh).textures; + + foreach (var group in mesh.elementGroups) + { + foreach(var index in group.indices) + positions[index] = origins[index] + delta; + } + + mesh.mesh.mesh.SetUVs(k_TextureChannel, positions); + } } EditorHandleUtility.PopMatrix(); } } } - -// UVEditor uvEditor = UVEditor.instance; -// if (!uvEditor) return; -// -// Vector3 cached = m_TextureHandlePosition; -// -// m_TextureHandlePosition = Handles.PositionHandle(m_TextureHandlePosition, m_HandleRotation); -// -// if (m_CurrentEvent.alt) return; -// -// if (m_TextureHandlePosition != cached) -// { -// cached = Quaternion.Inverse(m_HandleRotation) * m_TextureHandlePosition; -// cached.y = -cached.y; -// -// Vector3 lossyScale = selection[0].transform.lossyScale; -// Vector3 pos = cached.DivideBy(lossyScale); -// -// if (!m_IsMovingTextures) -// { -// m_TextureHandlePositionPrevious = pos; -// m_IsMovingTextures = true; -// } -// -// uvEditor.SceneMoveTool(pos - m_TextureHandlePositionPrevious); -// m_TextureHandlePositionPrevious = pos; -// uvEditor.Repaint(); -// } diff --git a/com.unity.probuilder/Editor/EditorCore/TextureRotateTool.cs b/com.unity.probuilder/Editor/EditorCore/TextureRotateTool.cs index dde9d569a..fb0100aab 100644 --- a/com.unity.probuilder/Editor/EditorCore/TextureRotateTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/TextureRotateTool.cs @@ -1,34 +1,65 @@ using UnityEngine; +using UnityEngine.ProBuilder; namespace UnityEditor.ProBuilder { class TextureRotateTool : TextureTool { + float m_Rotation; + Vector3 m_Euler; + Quaternion m_Quaternion; + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { -// UVEditor uvEditor = UVEditor.instance; -// if (!uvEditor) return; -// -// float size = HandleUtility.GetHandleSize(m_HandlePosition); -// -// if (m_CurrentEvent.alt) return; -// -// Matrix4x4 prev = Handles.matrix; -// Handles.matrix = handleMatrix; -// -// Quaternion cached = m_TextureRotation; -// -// m_TextureRotation = Handles.Disc(m_TextureRotation, Vector3.zero, Vector3.forward, size, false, 0f); -// -// if (m_TextureRotation != cached) -// { -// if (!m_IsMovingTextures) -// m_IsMovingTextures = true; -// -// uvEditor.SceneRotateTool(-m_TextureRotation.eulerAngles.z); -// } -// -// Handles.matrix = prev; + if (!isEditing) + m_Rotation = 0f; + + EditorGUI.BeginChangeCheck(); + + var size = HandleUtility.GetHandleSize(handlePosition); + + EditorHandleUtility.PushMatrix(); + + Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one); + + Handles.color = Color.blue; + m_Euler.z = m_Rotation; + m_Quaternion = Quaternion.Euler(m_Euler); + m_Quaternion = Handles.Disc(m_Quaternion, Vector3.zero, Vector3.forward, size, relativeSnapEnabled, relativeSnapRotation); + m_Euler = m_Quaternion.eulerAngles; + m_Rotation = m_Euler.z; + + EditorHandleUtility.PopMatrix(); + + if (EditorGUI.EndChangeCheck()) + { + if(!isEditing) + BeginEdit("Rotate Textures"); + + if (relativeSnapEnabled) + m_Rotation = Snapping.SnapValue(m_Rotation, relativeSnapX); + else if (progridsSnapEnabled) + m_Rotation = Snapping.SnapValue(m_Rotation, progridsSnapValue); + + foreach (var mesh in meshAndElementGroupPairs) + { + if (!(mesh is MeshAndTextures)) + continue; + + var origins = ((MeshAndTextures)mesh).origins; + var positions = ((MeshAndTextures)mesh).textures; + + foreach (var group in mesh.elementGroups) + { + foreach(var index in group.indices) + positions[index] = group.inverseMatrix.MultiplyPoint( + Math.RotateAroundPoint( + group.matrix.MultiplyPoint3x4(origins[index]), Vector2.zero, -m_Rotation)); + } + + mesh.mesh.mesh.SetUVs(k_TextureChannel, positions); + } + } } } } diff --git a/com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs b/com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs index 043401797..69c34e4a9 100644 --- a/com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs @@ -1,33 +1,75 @@ using UnityEngine; +using UnityEngine.ProBuilder; namespace UnityEditor.ProBuilder { class TextureScaleTool : TextureTool { + Vector2 m_Scale; + float m_UniformScale; + protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { -// UVEditor uvEditor = UVEditor.instance; -// if (!uvEditor) return; -// -// float size = HandleUtility.GetHandleSize(m_HandlePosition); -// -// Matrix4x4 prev = Handles.matrix; -// Handles.matrix = handleMatrix; -// -// Vector3 cached = m_TextureScale; -// m_TextureScale = Handles.ScaleHandle(m_TextureScale, Vector3.zero, Quaternion.identity, size); -// -// if (m_CurrentEvent.alt) return; -// -// if (cached != m_TextureScale) -// { -// if (!m_IsMovingTextures) -// m_IsMovingTextures = true; -// -// uvEditor.SceneScaleTool(m_TextureScale, cached); -// } -// -// Handles.matrix = prev; + if (!isEditing) + { + m_Scale.x = 1f; + m_Scale.y = 1f; + m_UniformScale = 1f; + } + + EditorGUI.BeginChangeCheck(); + + var size = HandleUtility.GetHandleSize(handlePosition); + + EditorHandleUtility.PushMatrix(); + + Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one); + + var snap = relativeSnapEnabled + ? relativeSnapScale + : progridsSnapEnabled + ? progridsSnapValue + : 0f; + + Handles.color = Color.red; + m_Scale.x = Handles.ScaleAxisHandle(m_Scale.x, Vector3.zero, Quaternion.identity, Vector3.right, size, snap); + + Handles.color = Color.green; + m_Scale.y = Handles.ScaleAxisHandle(m_Scale.y, Vector3.zero, Quaternion.identity, Vector3.up, size, snap); + + Handles.color = Color.blue; + m_UniformScale = Handles.ScaleValueHandle(m_UniformScale, Vector3.zero, Quaternion.identity, size, Handles.CubeHandleCap, snap); + + EditorHandleUtility.PopMatrix(); + + if (EditorGUI.EndChangeCheck()) + { + if(!isEditing) + BeginEdit("Scale Textures"); + + var delta = m_Scale * m_UniformScale; + + delta.x = 1f / delta.x; + delta.y = 1f / delta.y; + + foreach (var mesh in meshAndElementGroupPairs) + { + if (!(mesh is MeshAndTextures)) + continue; + + var origins = ((MeshAndTextures)mesh).origins; + var positions = ((MeshAndTextures)mesh).textures; + + foreach (var group in mesh.elementGroups) + { + foreach(var index in group.indices) + positions[index] = group.inverseMatrix.MultiplyPoint( + Vector2.Scale(group.matrix.MultiplyPoint3x4(origins[index]), delta)); + } + + mesh.mesh.mesh.SetUVs(k_TextureChannel, positions); + } + } } } } diff --git a/com.unity.probuilder/Editor/EditorCore/TextureTool.cs b/com.unity.probuilder/Editor/EditorCore/TextureTool.cs index 30a2aca52..e37de43b6 100644 --- a/com.unity.probuilder/Editor/EditorCore/TextureTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/TextureTool.cs @@ -1,39 +1,114 @@ using System.Collections.Generic; +using System.Linq; using UnityEngine; using UnityEngine.ProBuilder; namespace UnityEditor.ProBuilder { - class TextureTool : VertexManipulationTool + abstract class TextureTool : VertexManipulationTool { - class MeshAndTextures : MeshAndElementGroupPair + const bool k_CollectCoincidentVertices = false; + protected const int k_TextureChannel = 0; + + const string UnityMoveSnapX = "MoveSnapX"; + const string UnityMoveSnapY = "MoveSnapY"; + const string UnityMoveSnapZ = "MoveSnapZ"; + const string UnityScaleSnap = "ScaleSnap"; + const string UnityRotateSnap = "RotationSnap"; + + protected static float relativeSnapX + { + get { return EditorPrefs.GetFloat(UnityMoveSnapX, 1f); } + } + + protected static float relativeSnapY + { + get { return EditorPrefs.GetFloat(UnityMoveSnapY, 1f); } + } + + protected static float relativeSnapZ + { + get { return EditorPrefs.GetFloat(UnityMoveSnapZ, 1f); } + } + + protected static float relativeSnapScale + { + get { return EditorPrefs.GetFloat(UnityScaleSnap, .1f); } + } + + protected static float relativeSnapRotation + { + get { return EditorPrefs.GetFloat(UnityRotateSnap, 15f); } + } + + protected class MeshAndTextures : MeshAndElementGroupPair { + List m_Origins; List m_Textures; - public MeshAndTextures(ProBuilderMesh mesh, PivotPoint pivot) - : base(mesh, pivot) + public List textures { + get { return m_Textures; } + } + public List origins + { + get { return m_Origins; } } - } - Matrix4x4 m_HandleMatrix; + public MeshAndTextures(ProBuilderMesh mesh, PivotPoint pivot) : base(mesh, pivot, k_CollectCoincidentVertices) + { + m_Textures = new List(); + mesh.GetUVs(k_TextureChannel, m_Textures); + m_Origins = new List(m_Textures); - protected void PushMatrix() - { - m_HandleMatrix = Handles.matrix; + foreach (var group in elementGroups) + { + var bounds = Bounds2D.Center(m_Origins, group.indices); + group.matrix = Matrix4x4.Translate(-bounds); + } + } } - protected void PopMatrix() + protected override void OnToolDisengaged() { - m_HandleMatrix = Handles.matrix; + var isFaceMode = ProBuilderEditor.selectMode.ContainsFlag(SelectMode.TextureFace | SelectMode.Face); + + foreach (var mesh in meshAndElementGroupPairs) + { + if (!(mesh is MeshAndTextures)) + continue; + + if (isFaceMode) + { + foreach (var face in mesh.mesh.selectedFacesInternal) + face.manualUV = true; + } + else + { + var indices = new HashSet(mesh.elementGroups.SelectMany(x => x.indices)); + + foreach (var face in mesh.mesh.facesInternal) + { + foreach (var index in face.distinctIndexesInternal) + { + if (indices.Contains(index)) + { + face.manualUV = true; + break; + } + } + } + } + + var textures = ((MeshAndTextures)mesh).textures; + mesh.mesh.SetUVs(k_TextureChannel, textures); + } } protected override MeshAndElementGroupPair GetMeshAndElementGroupPair(ProBuilderMesh mesh, PivotPoint pivot) { return new MeshAndTextures(mesh, pivot); } - - protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { } } } diff --git a/com.unity.probuilder/Editor/EditorCore/UVEditor.cs b/com.unity.probuilder/Editor/EditorCore/UVEditor.cs index 4b701a080..beed6e46d 100644 --- a/com.unity.probuilder/Editor/EditorCore/UVEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/UVEditor.cs @@ -158,7 +158,6 @@ enum UVMode Tool tool = Tool.Move; GUIContent[] ToolIcons; - GUIContent[] SelectionIcons; struct ObjectElementIndex { @@ -308,13 +307,6 @@ void InitGUI() new GUIContent(rotateIcon, "Rotate Tool"), new GUIContent(scaleIcon, "Scale Tool") }; - - SelectionIcons = new GUIContent[3] - { - new GUIContent(vertex_Graphic_off, "Vertex Selection"), - new GUIContent(edge_Graphic_off, "Edge Selection"), - new GUIContent(face_Graphic_off, "Face Selection") - }; } #endregion #region GUI Loop @@ -1017,6 +1009,7 @@ bool UpdateNearestElement(Vector2 mousePosition) switch (ProBuilderEditor.selectMode) { case SelectMode.Edge: + case SelectMode.TextureEdge: float dist, best = 100f; try @@ -1052,6 +1045,7 @@ bool UpdateNearestElement(Vector2 mousePosition) break; case SelectMode.Face: + case SelectMode.TextureFace: try { @@ -1123,6 +1117,7 @@ void OnMouseClick(Vector2 mousePosition) switch (ProBuilderEditor.selectMode) { case SelectMode.Edge: + case SelectMode.TextureEdge: if (nearestElement.valid) { ProBuilderMesh mesh = selection[nearestElement.objectIndex]; @@ -1139,6 +1134,7 @@ void OnMouseClick(Vector2 mousePosition) break; case SelectMode.Face: + case SelectMode.TextureFace: Vector2 mpos = GUIToUVPoint(mousePosition); bool superBreak = false; @@ -1170,6 +1166,7 @@ void OnMouseClick(Vector2 mousePosition) break; case SelectMode.Vertex: + case SelectMode.TextureVertex: RefreshUVCoordinates(new Rect(mousePosition.x - 8, mousePosition.y - 8, 16, 16), true); break; } @@ -1824,7 +1821,7 @@ private void DrawUVGraph(Rect rect) r.height = DOT_SIZE; // Draw all vertices if in vertex mode - if (ProBuilderEditor.selectMode == SelectMode.Vertex && screenshotStatus == ScreenshotStatus.Done) + if (ProBuilderEditor.selectMode.ContainsFlag(SelectMode.Vertex | SelectMode.TextureVertex) && screenshotStatus == ScreenshotStatus.Done) { for (int i = 0; i < selection.Length; i++) { @@ -1882,7 +1879,7 @@ private void DrawUVGraph(Rect rect) } Handles.EndGUI(); } - #endif +#endif GUI.color = Color.white; @@ -2000,7 +1997,7 @@ private void DrawUVGraph(Rect rect) if (pb.selectedEdgeCount > 0) { - foreach (Edge edge in pb.selectedEdges) + foreach (Edge edge in pb.selectedEdgesInternal) { x = UVToGUIPoint(uv[edge.a]); y = UVToGUIPoint(uv[edge.b]); @@ -2021,6 +2018,7 @@ private void DrawUVGraph(Rect rect) switch (ProBuilderEditor.selectMode) { case SelectMode.Edge: + case SelectMode.TextureEdge: GL.Begin(GL.LINES); GL.Color(Color.red); @@ -2036,6 +2034,7 @@ private void DrawUVGraph(Rect rect) break; case SelectMode.Face: + case SelectMode.TextureFace: { Vector3 v = Vector3.zero; @@ -2331,6 +2330,7 @@ void RefreshUVCoordinates(Rect? dragRect, bool isClick) switch (ProBuilderEditor.selectMode) { case SelectMode.Vertex: + case SelectMode.TextureVertex: List selectedTris = new List(pb.selectedIndexesInternal); for (int j = 0; j < len; j++) @@ -2354,6 +2354,7 @@ void RefreshUVCoordinates(Rect? dragRect, bool isClick) break; case SelectMode.Edge: + case SelectMode.TextureEdge: List selectedEdges = new List(pb.selectedEdges); for (int n = 0; n < pb.facesInternal.Length; n++) @@ -2379,6 +2380,7 @@ void RefreshUVCoordinates(Rect? dragRect, bool isClick) * Check if any of the faces intersect with the mousedrag rect. */ case SelectMode.Face: + case SelectMode.TextureFace: HashSet selectedFaces = new HashSet(selection[i].selectedFacesInternal); @@ -2399,16 +2401,6 @@ void RefreshUVCoordinates(Rect? dragRect, bool isClick) } } - // // if(dragBounds.Intersects(faceBounds)) - // for(int t = 0; t < uvs.Length; t++) - // { - // if(!dragBounds.ContainsPoint(uvs[t])) - // { - // allPointsContained = false; - // break; - // } - // } - if (allPointsContained) { if (selectedFaces.Contains(face)) @@ -2473,9 +2465,6 @@ void DrawUVTools(Rect rect) if (commandStyle == null) commandStyle = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).FindStyle("Command"); - /** - * Handle toggles and SelectionMode toggles. - */ EditorGUI.BeginChangeCheck(); tool = (Tool)GUI.Toolbar(toolbarRect_tool, (int)tool < 0 ? 0 : (int)tool, ToolIcons, "Command"); @@ -2486,41 +2475,23 @@ void DrawUVTools(Rect rect) SceneView.RepaintAll(); } - var mode = ProBuilderEditor.selectMode; - - int currentSelectionMode = mode == SelectMode.Vertex ? 0 - : mode == SelectMode.Edge ? 1 - : mode == SelectMode.Face ? 2 : -1; - - GUI.enabled = channel == 0; - - EditorGUI.BeginChangeCheck(); - currentSelectionMode = GUI.Toolbar(toolbarRect_select, currentSelectionMode, SelectionIcons, "Command"); - if (EditorGUI.EndChangeCheck()) - { - if (currentSelectionMode == 0) - ProBuilderEditor.selectMode = SelectMode.Vertex; - else if (currentSelectionMode == 1) - ProBuilderEditor.selectMode = SelectMode.Edge; - else if (currentSelectionMode == 2) - ProBuilderEditor.selectMode = SelectMode.Face; - } - + ProBuilderEditor.selectMode = UI.EditorGUIUtility.DoElementModeToolbar(toolbarRect_select, ProBuilderEditor.selectMode); // begin Editor pref toggles (Show Texture, Lock UV sceneview handle, etc) - - Rect editor_toggles_rect = new Rect(toolbarRect_select.x + 130, PAD - 1, 36f, 22f); + Rect editor_toggles_rect = new Rect(toolbarRect_select.x + 140, PAD - 1, 36f, 22f); if (editor) { - gc_SceneViewUVHandles.image = ProBuilderEditor.selectMode == SelectMode.TextureFace ? icon_sceneUV_on : icon_sceneUV_off; + gc_SceneViewUVHandles.image = ProBuilderEditor.selectMode.IsTextureMode() ? icon_sceneUV_on : icon_sceneUV_off; if (GUI.Button(editor_toggles_rect, gc_SceneViewUVHandles)) { - if (ProBuilderEditor.selectMode == SelectMode.TextureFace) - ProBuilderEditor.ResetToLastSelectMode(); + if (ProBuilderEditor.selectMode.IsTextureMode()) + ProBuilderEditor.selectMode = ProBuilderEditor.selectMode.GetPositionMode(); else - ProBuilderEditor.selectMode = SelectMode.TextureFace; + ProBuilderEditor.selectMode = ProBuilderEditor.selectMode.GetTextureMode(); + + SceneView.RepaintAll(); } } diff --git a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs index 1f30c53fe..8199d33f7 100644 --- a/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexManipulationTool.cs @@ -28,14 +28,14 @@ public List elementGroups get { return m_ElementGroups; } } - public MeshAndElementGroupPair(ProBuilderMesh mesh, PivotPoint pivot) + public MeshAndElementGroupPair(ProBuilderMesh mesh, PivotPoint pivot, bool collectCoincidentIndices) { m_Mesh = mesh; - m_ElementGroups = ElementGroup.GetElementGroups(mesh, pivot); + m_ElementGroups = ElementGroup.GetElementGroups(mesh, pivot, collectCoincidentIndices); } } - struct ElementGroup + class ElementGroup { List m_Indices; Matrix4x4 m_PreApplyPositionsMatrix; @@ -49,6 +49,11 @@ public List indices public Matrix4x4 matrix { get { return m_PreApplyPositionsMatrix; } + set + { + m_PreApplyPositionsMatrix = value; + m_PostApplyPositionsMatrix = m_PreApplyPositionsMatrix.inverse; + } } public Matrix4x4 inverseMatrix @@ -56,15 +61,9 @@ public Matrix4x4 inverseMatrix get { return m_PostApplyPositionsMatrix; } } - public static List GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot) + public static List GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, bool collectCoincident) { var groups = new List(); - GetElementGroups(mesh, pivot, groups); - return groups; - } - - public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List groups) - { var trs = mesh.transform.localToWorldMatrix; switch (pivot) @@ -76,7 +75,9 @@ public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List< groups.Add(new ElementGroup() { - m_Indices = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal), + m_Indices = collectCoincident + ? mesh.GetCoincidentVertices(mesh.selectedIndexesInternal) + : new List(mesh.selectedIndexesInternal), m_PostApplyPositionsMatrix = post, m_PreApplyPositionsMatrix = post.inverse }); @@ -96,8 +97,17 @@ public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List< var rot = mesh.transform.rotation * Quaternion.LookRotation(ntb.normal, ntb.bitangent); var post = Matrix4x4.TRS(trs.MultiplyPoint3x4(bounds.center), rot, Vector3.one); - var indices = new List(); - mesh.GetCoincidentVertices(list, indices); + List indices; + + if (collectCoincident) + { + indices = new List(); + mesh.GetCoincidentVertices(list, indices); + } + else + { + indices = list.SelectMany(x => x.distinctIndexesInternal).ToList(); + } groups.Add(new ElementGroup() { @@ -115,7 +125,9 @@ public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List< groups.Add(new ElementGroup() { - m_Indices = mesh.GetCoincidentVertices(mesh.selectedIndexesInternal), + m_Indices = collectCoincident + ? mesh.GetCoincidentVertices(mesh.selectedIndexesInternal) + : new List(mesh.selectedIndexesInternal), m_PostApplyPositionsMatrix = Matrix4x4.Translate(MeshSelection.GetHandlePosition()), m_PreApplyPositionsMatrix = post.inverse }); @@ -123,6 +135,8 @@ public static void GetElementGroups(ProBuilderMesh mesh, PivotPoint pivot, List< break; } } + + return groups; } static List> GetFaceSelectionGroups(ProBuilderMesh mesh) @@ -183,9 +197,9 @@ abstract class VertexManipulationTool List m_MeshAndElementGroupPairs = new List(); bool m_IsEditing; - float m_SnapValue = .25f; + float m_ProgridsSnapValue = .25f; bool m_SnapAxisConstraint = true; - bool m_SnapEnabled; + bool m_ProgridsSnapEnabled; static bool s_Initialized; static FieldInfo s_VertexDragging; static MethodInfo s_FindNearestVertex; @@ -226,9 +240,9 @@ protected Quaternion handleRotationOrigin get { return m_HandleRotationOrigin; } } - protected float snapValue + protected float progridsSnapValue { - get { return m_SnapValue; } + get { return m_ProgridsSnapValue; } } protected bool snapAxisConstraint @@ -236,9 +250,14 @@ protected bool snapAxisConstraint get { return m_SnapAxisConstraint; } } - protected bool snapEnabled + protected bool progridsSnapEnabled + { + get { return m_ProgridsSnapEnabled; } + } + + protected bool relativeSnapEnabled { - get { return m_SnapEnabled; } + get { return currentEvent.control; } } static void Init() @@ -272,38 +291,6 @@ public void OnSceneGUI(Event evt) m_HandlePosition = MeshSelection.GetHandlePosition(); m_HandleRotation = MeshSelection.GetHandleRotation(ProBuilderEditor.handleOrientation); } - else - { - if (evt.type == EventType.Repaint) - { - foreach (var key in m_MeshAndElementGroupPairs) - { - foreach (var group in key.elementGroups) - { -#if DEBUG_HANDLES - using (var faceDrawer = new EditorMeshHandles.TriangleDrawingScope(Color.cyan, CompareFunction.Always)) - { - foreach (var face in key.mesh.GetSelectedFaces()) - { - var indices = face.indexesInternal; - - for (int i = 0, c = indices.Length; i < c; i += 3) - { - faceDrawer.Draw( - group.matrix.MultiplyPoint3x4(key.positions[indices[i]]), - group.matrix.MultiplyPoint3x4(key.positions[indices[i + 1]]), - group.matrix.MultiplyPoint3x4(key.positions[indices[i + 2]]) - ); - } - } - } -#endif - EditorMeshHandles.DrawGizmo(Vector3.zero, group.matrix.inverse); - } - } - } - } - DoTool(m_HandlePosition, m_HandleRotation); } @@ -338,8 +325,8 @@ protected void BeginEdit(string undoMessage) m_HandleRotationOrigin = m_HandleRotation; handleRotationOriginInverse = Quaternion.Inverse(m_HandleRotation); - m_SnapEnabled = ProGridsInterface.SnapEnabled(); - m_SnapValue = ProGridsInterface.SnapValue(); + m_ProgridsSnapEnabled = ProGridsInterface.SnapEnabled(); + m_ProgridsSnapValue = ProGridsInterface.SnapValue(); m_SnapAxisConstraint = ProGridsInterface.UseAxisConstraints(); foreach (var mesh in selection) @@ -363,6 +350,8 @@ protected void FinishEdit() Lightmapping.PopGIWorkflowMode(); + OnToolDisengaged(); + var selection = MeshSelection.topInternal.ToArray(); foreach (var mesh in selection) @@ -378,8 +367,6 @@ protected void FinishEdit() afterMeshModification(selection); m_IsEditing = false; - - OnToolDisengaged(); } static void Extrude() diff --git a/com.unity.probuilder/Editor/EditorCore/VertexMoveTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexMoveTool.cs index 742f1a309..f699b9926 100644 --- a/com.unity.probuilder/Editor/EditorCore/VertexMoveTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexMoveTool.cs @@ -21,6 +21,8 @@ protected override void OnToolEngaged() protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { + base.DoTool(handlePosition, handleRotation); + if (!isEditing) m_HandlePosition = handlePosition; @@ -56,7 +58,7 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation } } } - else if (snapEnabled) + else if (progridsSnapEnabled) { var localDir = handleRotationOriginInverse * delta; m_WorldSnapDirection = delta.normalized; @@ -67,13 +69,13 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation if (m_SnapInWorldCoordinates) { m_WorldSnapMask |= new Vector3Mask(m_WorldSnapDirection, k_CardinalAxisError); - m_HandlePosition = Snapping.SnapValue(m_HandlePosition, m_WorldSnapMask * snapValue); + m_HandlePosition = Snapping.SnapValue(m_HandlePosition, m_WorldSnapMask * progridsSnapValue); delta = m_HandlePosition - handlePositionOrigin; } else { var travel = delta.magnitude; - delta = m_WorldSnapDirection * Snapping.SnapValue(travel, snapValue); + delta = m_WorldSnapDirection * Snapping.SnapValue(travel, progridsSnapValue); m_HandlePosition = handlePositionOrigin + delta; } } diff --git a/com.unity.probuilder/Editor/EditorCore/VertexRotateTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexRotateTool.cs index 0a03c7f63..4ba3c908d 100644 --- a/com.unity.probuilder/Editor/EditorCore/VertexRotateTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexRotateTool.cs @@ -9,6 +9,8 @@ class VertexRotateTool : VertexTool protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { + base.DoTool(handlePosition, handleRotation); + if (Tools.pivotMode == PivotMode.Pivot) { EditorGUI.BeginChangeCheck(); diff --git a/com.unity.probuilder/Editor/EditorCore/VertexScaleTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexScaleTool.cs index afc597b6b..9fa191e5d 100644 --- a/com.unity.probuilder/Editor/EditorCore/VertexScaleTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexScaleTool.cs @@ -8,6 +8,8 @@ class VertexScaleTool : VertexTool protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation) { + base.DoTool(handlePosition, handleRotation); + if (!isEditing) m_Scale = Vector3.one; diff --git a/com.unity.probuilder/Editor/EditorCore/VertexTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexTool.cs index 53fbcbe4c..690d6833a 100644 --- a/com.unity.probuilder/Editor/EditorCore/VertexTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexTool.cs @@ -7,6 +7,8 @@ namespace UnityEditor.ProBuilder { abstract class VertexTool : VertexManipulationTool { + const bool k_CollectCoincidentVertices = true; + class MeshAndPositions : MeshAndElementGroupPair { Vector3[] m_Positions; @@ -16,7 +18,7 @@ public Vector3[] positions get { return m_Positions; } } - public MeshAndPositions(ProBuilderMesh mesh, PivotPoint pivot) : base(mesh, pivot) + public MeshAndPositions(ProBuilderMesh mesh, PivotPoint pivot) : base(mesh, pivot, k_CollectCoincidentVertices) { m_Positions = mesh.positions.ToArray(); @@ -32,6 +34,38 @@ protected override MeshAndElementGroupPair GetMeshAndElementGroupPair (ProBuilde return new MeshAndPositions(mesh, pivot); } + protected override void DoTool(Vector3 position, Quaternion rotation) + { + if (isEditing && currentEvent.type == EventType.Repaint) + { + foreach (var key in meshAndElementGroupPairs) + { + foreach (var group in key.elementGroups) + { +#if DEBUG_HANDLES + using (var faceDrawer = new EditorMeshHandles.TriangleDrawingScope(Color.cyan, CompareFunction.Always)) + { + foreach (var face in key.mesh.GetSelectedFaces()) + { + var indices = face.indexesInternal; + + for (int i = 0, c = indices.Length; i < c; i += 3) + { + faceDrawer.Draw( + group.matrix.MultiplyPoint3x4(key.positions[indices[i]]), + group.matrix.MultiplyPoint3x4(key.positions[indices[i + 1]]), + group.matrix.MultiplyPoint3x4(key.positions[indices[i + 2]]) + ); + } + } + } +#endif + EditorMeshHandles.DrawGizmo(Vector3.zero, group.matrix.inverse); + } + } + } + } + protected void Apply(Matrix4x4 delta) { foreach (var key in meshAndElementGroupPairs) diff --git a/com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleAlignment.cs b/com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleOrientation.cs similarity index 94% rename from com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleAlignment.cs rename to com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleOrientation.cs index fa9c02105..1290ca24b 100644 --- a/com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleAlignment.cs +++ b/com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleOrientation.cs @@ -7,7 +7,7 @@ namespace UnityEditor.ProBuilder.Actions { - sealed class ToggleHandleAlignment : MenuAction + sealed class ToggleHandleOrientation : MenuAction { Texture2D[] m_Icons; @@ -70,7 +70,12 @@ public override SelectMode validSelectModes get { return SelectMode.Vertex | SelectMode.Edge | SelectMode.Face; } } - public ToggleHandleAlignment() + public override bool hidden + { + get { return false; } + } + + public ToggleHandleOrientation() { m_Icons = new Texture2D[] { diff --git a/com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleAlignment.cs.meta b/com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleOrientation.cs.meta similarity index 69% rename from com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleAlignment.cs.meta rename to com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleOrientation.cs.meta index 0c7d3719f..1645609f9 100644 --- a/com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleAlignment.cs.meta +++ b/com.unity.probuilder/Editor/MenuActions/Interaction/ToggleHandleOrientation.cs.meta @@ -1,8 +1,7 @@ fileFormatVersion: 2 -guid: 1252cef8e85b4b55917bf9b538a8289c -timeCreated: 1457453191 -licenseType: Pro +guid: 53d27af1247a7d547aa00100fae732a0 MonoImporter: + externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 diff --git a/com.unity.probuilder/Runtime/Core/Bounds2D.cs b/com.unity.probuilder/Runtime/Core/Bounds2D.cs index 1a7627e2e..82841a86d 100644 --- a/com.unity.probuilder/Runtime/Core/Bounds2D.cs +++ b/com.unity.probuilder/Runtime/Core/Bounds2D.cs @@ -366,14 +366,43 @@ public static Vector2 Center(Vector2[] points, int length = -1) /// /// /// - public static Vector2 Center(Vector2[] points, int[] indexes) + public static Vector2 Center(IList points, IList indexes) { float xMin = 0f, xMax = 0f, yMin = 0f, yMax = 0f; - int size = indexes.Length; + int size = indexes.Count; + + xMin = points[indexes[0]].x; + yMin = points[indexes[0]].y; + xMax = xMin; + yMax = yMin; + + for(int i = 1; i < size; i++) + { + float x = points[indexes[i]].x; + float y = points[indexes[i]].y; + + if(x < xMin) xMin = x; + if(x > xMax) xMax = x; + + if(y < yMin) yMin = y; + if(y > yMax) yMax = y; + } + + return new Vector2( (xMin + xMax) / 2f, (yMin + yMax) / 2f ); + } + + internal static Vector2 Center(IList points, IList indexes) + { + float xMin = 0f, + xMax = 0f, + yMin = 0f, + yMax = 0f; + + int size = indexes.Count; xMin = points[indexes[0]].x; yMin = points[indexes[0]].y; diff --git a/com.unity.probuilder/Runtime/Core/ProBuilderEnum.cs b/com.unity.probuilder/Runtime/Core/ProBuilderEnum.cs index f583a855f..3337cf42a 100644 --- a/com.unity.probuilder/Runtime/Core/ProBuilderEnum.cs +++ b/com.unity.probuilder/Runtime/Core/ProBuilderEnum.cs @@ -39,11 +39,15 @@ public enum SelectMode /// TextureFace = 1 << 4, - // TextureEdge = 1 << 5, - Reserved0 = 1 << 5, + /// + /// Texture coordinates are selectable. + /// + TextureEdge = 1 << 5, - // TextureVertex = 1 << 6, - Reserved1 = 1 << 6, + /// + /// Texture coordinates are selectable. + /// + TextureVertex = 1 << 6, /// /// Other input tool (Poly Shape editor, Bezier editor, etc) From d0781dca1c3966788f73d82809b22313e548bc2f Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Sat, 3 Nov 2018 15:13:43 -0400 Subject: [PATCH 22/27] fix minor compile errors after trunk merge --- com.unity.probuilder/Editor/EditorCore/MenuItems.cs | 1 + com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs | 6 +++--- .../Settings/Editor/UserSettingsProvider.cs | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/MenuItems.cs b/com.unity.probuilder/Editor/EditorCore/MenuItems.cs index b0ac9404e..9e7827343 100644 --- a/com.unity.probuilder/Editor/EditorCore/MenuItems.cs +++ b/com.unity.probuilder/Editor/EditorCore/MenuItems.cs @@ -17,6 +17,7 @@ public static void MenuInitAbout() { AboutWindow.Init(); } + [MenuItem("Tools/" + PreferenceKeys.pluginTitle + "/" + PreferenceKeys.pluginTitle + " Window", false, PreferenceKeys.menuEditor)] public static void OpenEditorWindow() diff --git a/com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs b/com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs index 69c34e4a9..91fa348f9 100644 --- a/com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/TextureScaleTool.cs @@ -32,10 +32,10 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation : 0f; Handles.color = Color.red; - m_Scale.x = Handles.ScaleAxisHandle(m_Scale.x, Vector3.zero, Quaternion.identity, Vector3.right, size, snap); + m_Scale.x = Handles.ScaleSlider(m_Scale.x, Vector3.zero, Vector3.right, Quaternion.identity, size, snap); Handles.color = Color.green; - m_Scale.y = Handles.ScaleAxisHandle(m_Scale.y, Vector3.zero, Quaternion.identity, Vector3.up, size, snap); + m_Scale.y = Handles.ScaleSlider(m_Scale.y, Vector3.zero, Vector3.up, Quaternion.identity, size, snap); Handles.color = Color.blue; m_UniformScale = Handles.ScaleValueHandle(m_UniformScale, Vector3.zero, Quaternion.identity, size, Handles.CubeHandleCap, snap); @@ -48,7 +48,7 @@ protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation BeginEdit("Scale Textures"); var delta = m_Scale * m_UniformScale; - + delta.x = 1f / delta.x; delta.y = 1f / delta.y; diff --git a/com.unity.probuilder/Settings/Editor/UserSettingsProvider.cs b/com.unity.probuilder/Settings/Editor/UserSettingsProvider.cs index c6f46a8f2..ab2f43f23 100644 --- a/com.unity.probuilder/Settings/Editor/UserSettingsProvider.cs +++ b/com.unity.probuilder/Settings/Editor/UserSettingsProvider.cs @@ -8,7 +8,7 @@ using System.Linq; using System.Reflection; using UnityEngine; -using UnityEngine.Experimental.UIElements; +using UnityEngine.UIElements; namespace UnityEditor.SettingsManagement { From beead4971b89b5c5b8a507118efffc8124bfcbc1 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Sat, 3 Nov 2018 15:57:38 -0400 Subject: [PATCH 23/27] fix tests sometimes not creating temporary directories --- com.unity.probuilder.tests/Tests/Framework/TestUtility.cs | 4 +++- com.unity.probuilder/Settings/Editor/UserSettingsProvider.cs | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/com.unity.probuilder.tests/Tests/Framework/TestUtility.cs b/com.unity.probuilder.tests/Tests/Framework/TestUtility.cs index 1c6008367..e032ea717 100644 --- a/com.unity.probuilder.tests/Tests/Framework/TestUtility.cs +++ b/com.unity.probuilder.tests/Tests/Framework/TestUtility.cs @@ -12,14 +12,16 @@ namespace UnityEngine.ProBuilder.Tests.Framework { - abstract class TemporaryAssetTest : IPrebuildSetup, IPostBuildCleanup + abstract class TemporaryAssetTest { + [SetUp] public void Setup() { if (!Directory.Exists(TestUtility.TemporarySavedAssetsDirectory)) Directory.CreateDirectory(TestUtility.TemporarySavedAssetsDirectory); } + [TearDown] public void Cleanup() { if (Directory.Exists(TestUtility.TemporarySavedAssetsDirectory)) diff --git a/com.unity.probuilder/Settings/Editor/UserSettingsProvider.cs b/com.unity.probuilder/Settings/Editor/UserSettingsProvider.cs index ab2f43f23..a2fc6c070 100644 --- a/com.unity.probuilder/Settings/Editor/UserSettingsProvider.cs +++ b/com.unity.probuilder/Settings/Editor/UserSettingsProvider.cs @@ -8,7 +8,9 @@ using System.Linq; using System.Reflection; using UnityEngine; +#if SETTINGS_PROVIDER_ENABLED using UnityEngine.UIElements; +#endif namespace UnityEditor.SettingsManagement { From c02cf5d44915b4bf4d1b83ee001116d9e2f63155 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Sat, 3 Nov 2018 21:25:50 -0400 Subject: [PATCH 24/27] fix null ref in cases where window layout is reloaded --- com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs | 3 ++- com.unity.probuilder/Editor/EditorCore/UVEditor.cs | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index 69f6dacc9..3219acf91 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -362,7 +362,8 @@ void OnDisable() UpdateSelection(); - m_EditorMeshHandles.Dispose(); + if(m_EditorMeshHandles != null) + m_EditorMeshHandles.Dispose(); if (selectionUpdated != null) selectionUpdated(null); diff --git a/com.unity.probuilder/Editor/EditorCore/UVEditor.cs b/com.unity.probuilder/Editor/EditorCore/UVEditor.cs index beed6e46d..9c86e897a 100644 --- a/com.unity.probuilder/Editor/EditorCore/UVEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/UVEditor.cs @@ -288,10 +288,6 @@ void InitGUI() Texture2D scaleIcon = (Texture2D)loadIconMethod.Invoke(null, new object[] { "ScaleTool" }); Texture2D viewIcon = (Texture2D)loadIconMethod.Invoke(null, new object[] { "ViewToolMove" }); - Texture2D face_Graphic_off = IconUtility.GetIcon("Modes/Mode_Face"); - Texture2D vertex_Graphic_off = IconUtility.GetIcon("Modes/Mode_Vertex"); - Texture2D edge_Graphic_off = IconUtility.GetIcon("Modes/Mode_Edge"); - icon_textureMode_on = IconUtility.GetIcon("UVEditor/ProBuilderGUI_UV_ShowTexture_On", IconSkin.Pro); icon_textureMode_off = IconUtility.GetIcon("UVEditor/ProBuilderGUI_UV_ShowTexture_Off", IconSkin.Pro); From f954a1e9dfe037f73546a2e5066ff587c76ac135 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Sun, 4 Nov 2018 15:44:19 -0500 Subject: [PATCH 25/27] Fix mesh element gizmos not repainting when changing selectmode --- .../Editor/EditorCore/ProBuilderEditor.cs | 114 ++++++------------ 1 file changed, 34 insertions(+), 80 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs index 3219acf91..743fedefd 100644 --- a/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs +++ b/com.unity.probuilder/Editor/EditorCore/ProBuilderEditor.cs @@ -509,7 +509,6 @@ void SetIsUtilityWindow(bool isUtilityWindow) res.titleContent = windowTitle; } - VertexManipulationTool GetTool() where T : VertexManipulationTool, new() { VertexManipulationTool tool; @@ -521,6 +520,27 @@ void SetIsUtilityWindow(bool isUtilityWindow) return tool; } + VertexManipulationTool GetToolForSelectMode(Tool tool, SelectMode mode) + { + switch (tool) + { + case Tool.Move: + return mode.IsTextureMode() + ? GetTool() + : GetTool(); + case Tool.Rotate: + return mode.IsTextureMode() + ? GetTool() + : GetTool(); + case Tool.Scale: + return mode.IsTextureMode() + ? GetTool() + : GetTool(); + default: + return null; + } + } + void OnSceneGUI(SceneView sceneView) { #if !UNITY_2018_2_OR_NEWER @@ -585,42 +605,12 @@ void OnSceneGUI(SceneView sceneView) Tools.current = Tool.None; - if (selectMode.IsMeshElementMode()) + if (selectMode.IsMeshElementMode() && MeshSelection.selectedVertexCount > 0) { - if (MeshSelection.selectedVertexCount > 0) - { - if (selectMode.IsTextureMode()) - { - switch (m_CurrentTool) - { - case Tool.Move: - GetTool().OnSceneGUI(m_CurrentEvent); - break; - case Tool.Rotate: - GetTool().OnSceneGUI(m_CurrentEvent); - break; - case Tool.Scale: - GetTool().OnSceneGUI(m_CurrentEvent); - break; - } - } - else - { - switch (m_CurrentTool) - { - case Tool.Move: - GetTool().OnSceneGUI(m_CurrentEvent); - break; - case Tool.Scale: - GetTool().OnSceneGUI(m_CurrentEvent); - break; - case Tool.Rotate: - GetTool().OnSceneGUI(m_CurrentEvent); - break; - } - } + var tool = GetToolForSelectMode(m_CurrentTool, m_SelectMode); - } + if(tool != null) + tool.OnSceneGUI(m_CurrentEvent); } if (EditorHandleUtility.SceneViewInUse(m_CurrentEvent) || m_CurrentEvent.isKey) @@ -798,7 +788,7 @@ void DrawHandleGUI(SceneView sceneView) break; } - m_SelectMode.value = UI.EditorGUIUtility.DoElementModeToolbar(m_ElementModeToolbarRect, m_SelectMode); + selectMode = UI.EditorGUIUtility.DoElementModeToolbar(m_ElementModeToolbarRect, selectMode); // todo Move to VertexManipulationTool // if (m_IsMovingElements && s_ShowSceneInfo) @@ -1035,10 +1025,6 @@ void UpdateSelection(bool selectionChanged = true) // todo remove selection property selection = MeshSelection.topInternal.ToArray(); -// m_HandlePosition = MeshSelection.GetHandlePosition(); -// m_HandleRotation = MeshSelection.GetHandleRotation(s_HandleOrientation); - - UpdateTextureHandles(); UpdateMeshHandles(selectionChanged); if (selectionChanged) @@ -1074,14 +1060,14 @@ void UpdateSceneInfo() { m_SceneInfo.text = string.Format( "Faces: {0}\nTriangles: {1}\nVertices: {2} ({3})\n\nSelected Faces: {4}\nSelected Edges: {5}\nSelected Vertices: {6} ({7})", - MeshSelection.totalFaceCount, - MeshSelection.totalTriangleCountCompiled, - MeshSelection.totalCommonVertexCount, - MeshSelection.totalVertexCountOptimized, - MeshSelection.selectedFaceCount, - MeshSelection.selectedEdgeCount, - MeshSelection.selectedSharedVertexCount, - MeshSelection.selectedVertexCount); + MeshSelection.totalFaceCount.ToString(), + MeshSelection.totalTriangleCountCompiled.ToString(), + MeshSelection.totalCommonVertexCount.ToString(), + MeshSelection.totalVertexCountOptimized.ToString(), + MeshSelection.selectedFaceCount.ToString(), + MeshSelection.selectedEdgeCount.ToString(), + MeshSelection.selectedSharedVertexCount.ToString(), + MeshSelection.selectedVertexCount.ToString()); } internal void ClearElementSelection() @@ -1092,38 +1078,6 @@ internal void ClearElementSelection() m_Hovering.Clear(); } - void UpdateTextureHandles() - { -// if (!selectMode.ContainsFlag(SelectMode.TextureFace) || !selection.Any()) -// return; -// -// // Reset temp vars -// m_TextureHandlePosition = m_HandlePosition; -// m_TextureScale = Vector3.one; -// m_TextureRotation = Quaternion.identity; -// -// ProBuilderMesh pb; -// Face face; -// -// handleMatrix = selection[0].transform.localToWorldMatrix; -// -// if (GetFirstSelectedFace(out pb, out face)) -// { -// var normals = Math.NormalTangentBitangent(pb, face); -// var nrm = normals.normal; -// var bitan = normals.bitangent; -// -// if (nrm == Vector3.zero || bitan == Vector3.zero) -// { -// nrm = Vector3.up; -// bitan = Vector3.right; -// } -// -// handleMatrix *= Matrix4x4.TRS(Math.GetBounds(pb.positionsInternal.ValuesWithIndexes(face.distinctIndexesInternal)).center, -// Quaternion.LookRotation(nrm, bitan), Vector3.one); -// } - } - /// /// If dragging a texture aroudn, this method ensures that if it's a member of a texture group it's cronies are also selected /// From 9e7b60d485a1ac577027e5854622be5c4e5f66b9 Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Mon, 5 Nov 2018 14:18:59 -0500 Subject: [PATCH 26/27] fix compile error on 2018.3 --- .../Editor/EditorCore/StaticEditorMeshHandles.cs | 3 +-- .../Editor/EditorCore/VertexTool.cs | 14 +++++++++++++- .../Settings/Editor/UserSettingsProvider.cs | 4 ++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs index d2776abad..3f583654d 100644 --- a/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs +++ b/com.unity.probuilder/Editor/EditorCore/StaticEditorMeshHandles.cs @@ -11,7 +11,6 @@ namespace UnityEditor.ProBuilder partial class EditorMeshHandles { static bool s_Initialized; - static Material s_LineMaterial; static Material s_FaceMaterial; @@ -51,7 +50,7 @@ internal static void DrawGizmo(Vector3 position, Quaternion rotation, float size internal static void DrawGizmo(Vector3 position, Matrix4x4 matrix, float size = -1f) { var p = matrix.MultiplyPoint3x4(position); - size = HandleUtility.GetHandleSize(p) * size < 0f ? .25f : size; + size = HandleUtility.GetHandleSize(p) * size < 0f ? .2f : size; using (var lineDrawer = new LineDrawingScope(Color.green, -1f, CompareFunction.Always)) { diff --git a/com.unity.probuilder/Editor/EditorCore/VertexTool.cs b/com.unity.probuilder/Editor/EditorCore/VertexTool.cs index 690d6833a..86ca71112 100644 --- a/com.unity.probuilder/Editor/EditorCore/VertexTool.cs +++ b/com.unity.probuilder/Editor/EditorCore/VertexTool.cs @@ -8,6 +8,9 @@ namespace UnityEditor.ProBuilder abstract class VertexTool : VertexManipulationTool { const bool k_CollectCoincidentVertices = true; +#if APPLY_POSITION_TO_SPACE_GIZMO + Matrix4x4 m_CurrentDelta = Matrix4x4.identity; +#endif class MeshAndPositions : MeshAndElementGroupPair { @@ -36,7 +39,7 @@ protected override MeshAndElementGroupPair GetMeshAndElementGroupPair (ProBuilde protected override void DoTool(Vector3 position, Quaternion rotation) { - if (isEditing && currentEvent.type == EventType.Repaint) + if ( isEditing && currentEvent.type == EventType.Repaint) { foreach (var key in meshAndElementGroupPairs) { @@ -60,7 +63,12 @@ protected override void DoTool(Vector3 position, Quaternion rotation) } } #endif + +#if APPLY_POSITION_TO_SPACE_GIZMO + EditorMeshHandles.DrawGizmo(Vector3.zero, group.matrix.inverse * m_CurrentDelta); +#else EditorMeshHandles.DrawGizmo(Vector3.zero, group.matrix.inverse); +#endif } } } @@ -68,6 +76,10 @@ protected override void DoTool(Vector3 position, Quaternion rotation) protected void Apply(Matrix4x4 delta) { +#if APPLY_POSITION_TO_SPACE_GIZMO + m_CurrentDelta.SetColumn(3, delta.GetColumn(3)); +#endif + foreach (var key in meshAndElementGroupPairs) { if (!(key is MeshAndPositions)) diff --git a/com.unity.probuilder/Settings/Editor/UserSettingsProvider.cs b/com.unity.probuilder/Settings/Editor/UserSettingsProvider.cs index a2fc6c070..b2564b4f8 100644 --- a/com.unity.probuilder/Settings/Editor/UserSettingsProvider.cs +++ b/com.unity.probuilder/Settings/Editor/UserSettingsProvider.cs @@ -9,8 +9,12 @@ using System.Reflection; using UnityEngine; #if SETTINGS_PROVIDER_ENABLED +#if UNITY_2018_3 +using UnityEngine.Experimental.UIElements; +#else using UnityEngine.UIElements; #endif +#endif namespace UnityEditor.SettingsManagement { From 820cea2ba9fe35005ac1ddbbb241739e455904ec Mon Sep 17 00:00:00 2001 From: Karl Henkel Date: Mon, 5 Nov 2018 14:29:58 -0500 Subject: [PATCH 27/27] bump changelog 4.0.0-preview.28 --- com.unity.probuilder/CHANGELOG.md | 15 ++++++++++----- com.unity.probuilder/Runtime/Core/Version.cs | 2 +- com.unity.probuilder/package.json | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/com.unity.probuilder/CHANGELOG.md b/com.unity.probuilder/CHANGELOG.md index 6eea85945..d49cc792e 100644 --- a/com.unity.probuilder/CHANGELOG.md +++ b/com.unity.probuilder/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [4.0.0-preview.27] - 2018-10-09 +## [4.0.0-preview.28] - 2018-11-05 ### Features @@ -70,11 +70,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Include third party dependencies as source code with assembly definitions instead of pre-compiled DLLs. - Performance optimization for selection changes in editor. -### Changes since 4.0.0-preview.26 +### Changes since 4.0.0-preview.27 -- Fix lightmap unit test instabilities. -- Refactor settings code to be more modular. -- Remove hard-coded `#define PROGRIDS_ENABLED` from ProGrids unit tests. +- Add support for `Pivot` and `Center` handle position toggle. +- Handles now support operating in selection space (Position: Pivot + Orientation: Normal). +- Texture scene tool now supports vertices and edges. +- Improve performance of mesh rebuild functions. +- Improve performance of vertex, edge, and face gizmos. +- Make auto-resizing colliders opt-in instead of on by default. +- Fix tests sometimes not creating temporary directories. +- Fix occasional null reference error in cases where window layout is reloaded. ## [3.0.8] - 2018-05-07 diff --git a/com.unity.probuilder/Runtime/Core/Version.cs b/com.unity.probuilder/Runtime/Core/Version.cs index 3c6b03116..5eee823df 100644 --- a/com.unity.probuilder/Runtime/Core/Version.cs +++ b/com.unity.probuilder/Runtime/Core/Version.cs @@ -5,7 +5,7 @@ namespace UnityEngine.ProBuilder /// static class Version { - internal static readonly SemVer currentInfo = new SemVer("4.0.0-preview.27", "2018/10/09"); + internal static readonly SemVer currentInfo = new SemVer("4.0.0-preview.28", "2018/11/05"); /// /// Get the current version. diff --git a/com.unity.probuilder/package.json b/com.unity.probuilder/package.json index 2f7b49ca5..2af121271 100644 --- a/com.unity.probuilder/package.json +++ b/com.unity.probuilder/package.json @@ -1,7 +1,7 @@ { "name": "com.unity.probuilder", "displayName":"ProBuilder", - "version": "4.0.0-preview.27", + "version": "4.0.0-preview.28", "unity": "2018.1", "description": "Build, edit, and texture custom geometry in Unity. Use ProBuilder for in-scene level design, prototyping, collision meshes, all with on-the-fly play-testing.\n\nAdvanced features include UV editing, vertex colors, parametric shapes, and texture blending. With ProBuilder's model export feature it's easy to tweak your levels in any external 3D modelling suite.\n\nDisclaimer: The ProBuilder API is currently in beta and will change before final release.", "keywords": ["3d", "model", "mesh", "modeling", "geometry", "shape", "cube", "blender", "max", "maya", "fbx", "obj", "level", "design", "block", "greybox", "graybox", "whitebox", "prototype", "probuilder"],