protected override void DoToolGUI()
        {
            if (showHandleInfo && isEditing)
            {
                DrawDeltaInfo("Scale: " + m_Scale.ToString("0.00"));
            }

            if (!isEditing)
            {
                m_Scale = Vector3.one;
            }

            EditorGUI.BeginChangeCheck();

            var size = HandleUtility.GetHandleSize(m_HandlePosition);

            EditorHandleUtility.PushMatrix();
            Handles.matrix = Matrix4x4.TRS(m_HandlePosition, m_HandleRotation, Vector3.one);
            m_Scale        = Handles.ScaleHandle(m_Scale, Vector3.zero, Quaternion.identity, size);
            EditorHandleUtility.PopMatrix();

            if (EditorGUI.EndChangeCheck())
            {
                if (!isEditing)
                {
                    BeginEdit("Scale Selection");
                }

                Apply(Matrix4x4.Scale(m_Scale));
            }
        }
Beispiel #2
0
        void SetupInputPlane(Vector2 mousePosition)
        {
            plane = EditorHandleUtility.FindBestPlane(mousePosition);

            var planeNormal = plane.normal;
            var planeCenter = plane.normal * -plane.distance;

            // if hit point on plane is cardinal axis and on grid, snap to grid.
            if (Math.IsCardinalAxis(planeNormal))
            {
                const float epsilon = .00001f;
                bool        offGrid = false;
                Vector3     snapVal = EditorSnapping.activeMoveSnapValue;
                Vector3     center  = Vector3.Scale(ProBuilderSnapping.GetSnappingMaskBasedOnNormalVector(planeNormal), planeCenter);
                for (int i = 0; i < 3; i++)
                {
                    offGrid |= Mathf.Abs(snapVal[i] % center[i]) > epsilon;
                }
                polygon.isOnGrid = !offGrid;
            }
            else
            {
                polygon.isOnGrid = false;
            }
        }
Beispiel #3
0
        protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation)
        {
            base.DoTool(handlePosition, handleRotation);

            if (!isEditing)
            {
                m_Scale = Vector3.one;
            }

            EditorGUI.BeginChangeCheck();

            var size = HandleUtility.GetHandleSize(handlePosition);

            EditorHandleUtility.PushMatrix();
            Handles.matrix = Matrix4x4.TRS(handlePosition, handleRotation, Vector3.one);
            m_Scale        = Handles.ScaleHandle(m_Scale, Vector3.zero, Quaternion.identity, size);
            EditorHandleUtility.PopMatrix();

            if (EditorGUI.EndChangeCheck())
            {
                if (!isEditing)
                {
                    BeginEdit("Scale Selection");
                }

                Apply(Matrix4x4.Scale(m_Scale));
            }
        }
Beispiel #4
0
        void SetupInputPlane(Vector2 mousePosition)
        {
            m_Plane = EditorHandleUtility.FindBestPlane(mousePosition);

            if (ProGridsInterface.SnapEnabled())
            {
                m_Plane.SetNormalAndPosition(
                    m_Plane.normal,
                    ProGridsInterface.ProGridsSnap(m_Plane.normal * -m_Plane.distance));
            }

            var planeNormal = m_Plane.normal;
            var planeCenter = m_Plane.normal * -m_Plane.distance;

            // if hit point on plane is cardinal axis and on grid, snap to grid.
            if (Math.IsCardinalAxis(planeNormal))
            {
                const float epsilon = .00001f;
                float       snapVal = Mathf.Abs(ProGridsInterface.SnapValue());
                float       rem     = Mathf.Abs(snapVal - (Vector3.Scale(planeNormal, planeCenter).magnitude % snapVal));
                polygon.isOnGrid = (rem < epsilon || Mathf.Abs(snapVal - rem) < epsilon);
            }
            else
            {
                polygon.isOnGrid = false;
            }
        }
        public override void OnToolGUI(EditorWindow window)
        {
            SceneViewOverlay.Window(k_ShapeTitle, OnOverlayGUI, 0, SceneViewOverlay.WindowDisplayOption.OneWindowPerTitle);

            var evt = Event.current;

            if (EditorHandleUtility.SceneViewInUse(evt))
            {
                return;
            }

            m_ControlID = GUIUtility.GetControlID(FocusType.Passive);
            HandleUtility.AddDefaultControl(m_ControlID);

            m_CurrentState = m_CurrentState.DoState(evt);
        }
Beispiel #6
0
        public override void OnToolGUI(EditorWindow window)
        {
            SceneViewOverlay.Window(k_ShapeTitle, OnOverlayGUI, 0, SceneViewOverlay.WindowDisplayOption.OneWindowPerTitle);

            var evt = Event.current;

            if (EditorHandleUtility.SceneViewInUse(evt))
            {
                return;
            }

            m_ControlID = GUIUtility.GetControlID(FocusType.Passive);
            HandleUtility.AddDefaultControl(m_ControlID);

            if (GUIUtility.hotControl == 0)
            {
                EditorGUIUtility.AddCursorRect(new Rect(0, 0, Screen.width, Screen.height), MouseCursor.ArrowPlus);
            }

            m_CurrentState = m_CurrentState.DoState(evt);
        }
Beispiel #7
0
        void DoPointPlacement()
        {
            Event     evt       = Event.current;
            EventType eventType = evt.type;

            if (m_PlacingPoint)
            {
                Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition);

                if (eventType == EventType.MouseDrag)
                {
                    float hitDistance = Mathf.Infinity;

                    if (plane.Raycast(ray, out hitDistance))
                    {
                        evt.Use();
                        polygon.m_Points[m_SelectedIndex] = GetPointInLocalSpace(ray.GetPoint(hitDistance));
                        RebuildPolyShapeMesh(false);
                        SceneView.RepaintAll();
                    }
                }

                if (eventType == EventType.MouseUp ||
                    eventType == EventType.Ignore ||
                    eventType == EventType.KeyDown ||
                    eventType == EventType.KeyUp)
                {
                    evt.Use();
                    m_PlacingPoint  = false;
                    m_SelectedIndex = -1;
                    SceneView.RepaintAll();
                }
            }
            else if (polygon.polyEditMode == PolyShape.PolyEditMode.Path)
            {
                if (eventType == EventType.MouseDown && HandleUtility.nearestControl == m_ControlId)
                {
                    if (polygon.m_Points.Count < 1)
                    {
                        SetupInputPlane(evt.mousePosition);
                    }

                    float hitDistance = Mathf.Infinity;

                    Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition);

                    if (plane.Raycast(ray, out hitDistance))
                    {
                        UndoUtility.RecordObject(polygon, "Add Polygon Shape Point");

                        Vector3 hit = ray.GetPoint(hitDistance);

                        if (polygon.m_Points.Count < 1)
                        {
                            // this monstrosity exists so that grid and incremental snap work when possible, and
                            // incremental is enabled when grid is not available.
                            polygon.transform.position = m_Polygon.isOnGrid
                                ? EditorSnapping.MoveSnap(hit)
                                : EditorSnapping.snapMode == SnapMode.Relative
                                    ? ProBuilderSnapping.Snap(hit, EditorSnapping.incrementalSnapMoveValue)
                                    : hit;

                            Vector3 cameraFacingPlaneNormal = plane.normal;
                            if (Vector3.Dot(cameraFacingPlaneNormal, SceneView.lastActiveSceneView.camera.transform.forward) > 0f)
                            {
                                cameraFacingPlaneNormal *= -1;
                            }

                            polygon.transform.rotation = Quaternion.LookRotation(cameraFacingPlaneNormal) * Quaternion.Euler(new Vector3(90f, 0f, 0f));
                        }

                        Vector3 point = GetPointInLocalSpace(hit);

                        if (polygon.m_Points.Count > 2 && Math.Approx3(polygon.m_Points[0], point))
                        {
                            m_NextMouseUpAdvancesMode = true;
                            return;
                        }

                        polygon.m_Points.Add(point);

                        m_PlacingPoint  = true;
                        m_SelectedIndex = polygon.m_Points.Count - 1;
                        RebuildPolyShapeMesh(polygon);

                        evt.Use();
                    }
                }
                else
                {
                    float hitDistance = Mathf.Infinity;
                    Ray   ray         = HandleUtility.GUIPointToWorldRay(evt.mousePosition);

                    if (plane.Raycast(ray, out hitDistance))
                    {
                        Vector3 hit = ray.GetPoint(hitDistance);
                        m_CurrentPosition = GetPointInLocalSpace(hit);
                    }
                }
            }
            else if (polygon.polyEditMode == PolyShape.PolyEditMode.Edit)
            {
                if (polygon.m_Points.Count < 3)
                {
                    SetPolyEditMode(PolyShape.PolyEditMode.Path);
                    return;
                }

                if (m_DistanceFromHeightHandle > PreferenceKeys.k_MaxPointDistanceFromControl)
                {
                    // point insertion
                    Vector2 mouse       = evt.mousePosition;
                    Ray     ray         = HandleUtility.GUIPointToWorldRay(mouse);
                    float   hitDistance = Mathf.Infinity;
                    if (plane.Raycast(ray, out hitDistance))
                    {
                        Vector3 hit   = ray.GetPoint(hitDistance);
                        Vector3 point = GetPointInLocalSpace(hit);

                        int polyCount = polygon.m_Points.Count;

                        float   distToLineInGUI;
                        int     index;
                        Vector3 pInGUI = EditorHandleUtility.ClosestPointToPolyLine(polygon.m_Points, out index, out distToLineInGUI, true, polygon.transform);

                        Vector3 aToPoint = point - polygon.m_Points[index - 1];
                        Vector3 aToB     = polygon.m_Points[index % polyCount] - polygon.m_Points[index - 1];

                        float   ratio = Vector3.Dot(aToPoint, aToB.normalized) / aToB.magnitude;
                        Vector3 wp    = Vector3.Lerp(polygon.m_Points[index - 1], polygon.m_Points[index % polyCount], ratio);
                        wp = polygon.transform.TransformPoint(wp);

                        Vector2 aInGUI           = HandleUtility.WorldToGUIPoint(polygon.transform.TransformPoint(polygon.m_Points[index - 1]));
                        Vector2 bInGUI           = HandleUtility.WorldToGUIPoint(polygon.transform.TransformPoint(polygon.m_Points[index % polyCount]));
                        float   distanceToVertex = Mathf.Min(Vector2.Distance(mouse, aInGUI), Vector2.Distance(mouse, bInGUI));

                        if (distanceToVertex > PreferenceKeys.k_MaxPointDistanceFromControl && distToLineInGUI < PreferenceKeys.k_MaxPointDistanceFromControl)
                        {
                            m_MouseCursor = MouseCursor.ArrowPlus;

                            if (evt.type == EventType.Repaint)
                            {
                                Handles.color = Color.green;
                                Handles.DotHandleCap(-1, wp, Quaternion.identity,
                                                     HandleUtility.GetHandleSize(wp) * k_HandleSize, evt.type);
                            }

                            if (evt.type == EventType.MouseDown && HandleUtility.nearestControl == m_ControlId)
                            {
                                evt.Use();

                                UndoUtility.RecordObject(polygon, "Insert Point");
                                polygon.m_Points.Insert(index, point);
                                m_SelectedIndex = index;
                                m_PlacingPoint  = true;
                                RebuildPolyShapeMesh(true);
                                OnBeginVertexMovement();
                            }

                            Handles.color = Color.white;
                        }

                        if (evt.type != EventType.Repaint)
                        {
                            SceneView.RepaintAll();
                        }
                    }
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// Main GUI update for the tool, calls every secondary methods to place points, update lines and compute the cut
        /// </summary>
        /// <param name="window">current window calling the tool : SceneView</param>
        public override void OnToolGUI(EditorWindow window)
        {
            Event evt = Event.current;

            SceneViewOverlay.Window(m_OverlayTitle, OnOverlayGUI, 0, SceneViewOverlay.WindowDisplayOption.OneWindowPerTitle);

            if (polygon == null)
            {
                return;
            }

            if (polygon.polyEditMode == PolyShape.PolyEditMode.None)
            {
                return;
            }

            // used when finishing a loop by clicking the first created point
            if (m_NextMouseUpAdvancesMode && evt.type == EventType.MouseUp)
            {
                evt.Use();

                m_NextMouseUpAdvancesMode = false;

                if (SceneCameraIsAlignedWithPolyUp())
                {
                    SetPolyEditMode(PolyShape.PolyEditMode.Edit);
                }
                else
                {
                    SetPolyEditMode(PolyShape.PolyEditMode.Height);
                }
            }

            if (m_IsModifyingVertices && (
                    evt.type == EventType.MouseUp ||
                    evt.type == EventType.Ignore ||
                    evt.type == EventType.KeyDown ||
                    evt.type == EventType.KeyUp))
            {
                OnFinishVertexMovement();
            }

            if (evt.type == EventType.KeyDown)
            {
                HandleKeyEvent(evt);
            }

            //The user can press a key to exit editing mode,
            //leading to null polygon at this point
            if (polygon == null)
            {
                return;
            }

            if (EditorHandleUtility.SceneViewInUse(evt))
            {
                return;
            }

            m_ControlId = GUIUtility.GetControlID(FocusType.Passive);

            if (evt.type == EventType.Layout)
            {
                HandleUtility.AddDefaultControl(m_ControlId);
            }

            if (polygon.polyEditMode == PolyShape.PolyEditMode.Path && !m_PlacingPoint)
            {
                m_MouseCursor = MouseCursor.ArrowPlus;
            }
            else if ((GUIUtility.hotControl != 0) || m_PlacingPoint)
            {
                m_MouseCursor = MouseCursor.MoveArrow;
            }
            else
            {
                m_MouseCursor = MouseCursor.Arrow;
            }

            if (evt.type == EventType.MouseMove)
            {
                SceneView.RepaintAll();
            }

            DoPointPlacement();
            DoExistingPointsGUI();

            if (evt.type == EventType.Repaint)
            {
                DoExistingLinesGUI();
                Rect sceneViewRect = window.position;
                sceneViewRect.x = 0;
                sceneViewRect.y = 0;
                SceneView.AddCursorRect(sceneViewRect, m_MouseCursor);
            }
        }
        static float FaceRaycast(Vector3 mousePosition,
                                 ScenePickerPreferences pickerOptions,
                                 bool allowUnselected,
                                 SceneSelection selection,
                                 int deepClickOffset = 0,
                                 bool isPreview      = true)
        {
            GameObject     pickedGo   = null;
            ProBuilderMesh pickedPb   = null;
            Face           pickedFace = null;

            int newHash = 0;

            // If any event modifiers are engaged don't cycle the deep click
            EventModifiers em = Event.current.modifiers;

            if (isPreview || em != EventModifiers.None)
            {
                EditorHandleUtility.GetHovered(mousePosition, s_OverlappingGameObjects);
            }
            else
            {
                EditorHandleUtility.GetAllOverlapping(mousePosition, s_OverlappingGameObjects);
            }

            selection.Clear();

            float distance = Mathf.Infinity;

            for (int i = 0, next = 0, pickedCount = s_OverlappingGameObjects.Count; i < pickedCount; i++)
            {
                var  go   = s_OverlappingGameObjects[i];
                var  mesh = go.GetComponent <ProBuilderMesh>();
                Face face = null;

                if (mesh != null && (allowUnselected || MeshSelection.topInternal.Contains(mesh)))
                {
                    Ray        ray = UHandleUtility.GUIPointToWorldRay(mousePosition);
                    RaycastHit hit;

                    if (UnityEngine.ProBuilder.HandleUtility.FaceRaycast(ray,
                                                                         mesh,
                                                                         out hit,
                                                                         Mathf.Infinity,
                                                                         pickerOptions.cullMode))
                    {
                        face     = mesh.facesInternal[hit.face];
                        distance = Vector2.SqrMagnitude(((Vector2)mousePosition) - HandleUtility.WorldToGUIPoint(mesh.transform.TransformPoint(hit.point)));
                    }
                }

                // pb_Face doesn't define GetHashCode, meaning it falls to object.GetHashCode (reference comparison)
                int hash = face == null?go.GetHashCode() : face.GetHashCode();

                if (s_DeepSelectionPrevious == hash)
                {
                    next = (i + (1 + deepClickOffset)) % pickedCount;
                }

                if (next == i)
                {
                    pickedGo   = go;
                    pickedPb   = mesh;
                    pickedFace = face;

                    newHash = hash;

                    // a prior hash was matched, this is the next. if
                    // it's just the first iteration don't break (but do
                    // set the default).
                    if (next != 0)
                    {
                        break;
                    }
                }
            }

            if (!isPreview)
            {
                s_DeepSelectionPrevious = newHash;
            }

            if (pickedGo != null)
            {
                Event.current.Use();

                if (pickedPb != null)
                {
                    if (pickedPb.selectable)
                    {
                        selection.gameObject = pickedGo;
                        selection.mesh       = pickedPb;
                        selection.face       = pickedFace;

                        return(Mathf.Sqrt(distance));
                    }
                }

                // If clicked off a pb_Object but onto another gameobject, set the selection
                // and dip out.
                selection.gameObject = pickedGo;
                return(Mathf.Sqrt(distance));
            }

            return(distance);
        }
        public static ProBuilderMesh DoMouseClick(Event evt, SelectMode selectionMode, ScenePickerPreferences pickerPreferences)
        {
            bool appendModifier = EditorHandleUtility.IsAppendModifier(evt.modifiers);

            if (!appendModifier)
            {
                MeshSelection.SetSelection((GameObject)null);
            }

            float pickedElementDistance = Mathf.Infinity;

            if (selectionMode.ContainsFlag(SelectMode.Edge | SelectMode.TextureEdge))
            {
                pickedElementDistance = EdgeRaycast(evt.mousePosition, pickerPreferences, true, s_Selection);
            }
            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);
            }

            evt.Use();

            if (pickedElementDistance > pickerPreferences.maxPointerDistance)
            {
                if (appendModifier && Selection.gameObjects.Contains(s_Selection.gameObject))
                {
                    MeshSelection.RemoveFromSelection(s_Selection.gameObject);
                }
                else
                {
                    MeshSelection.AddToSelection(s_Selection.gameObject);
                }

                return(null);
            }

            MeshSelection.AddToSelection(s_Selection.gameObject);

            if (s_Selection.mesh != null)
            {
                var mesh = s_Selection.mesh;

                if (s_Selection.face != null)
                {
                    // Check for other editor mouse shortcuts first (todo proper event handling for mouse shortcuts)
                    MaterialEditor matEditor = MaterialEditor.instance;

                    if (matEditor != null && matEditor.ClickShortcutCheck(Event.current.modifiers, mesh, s_Selection.face))
                    {
                        return(null);
                    }

                    UVEditor uvEditor = UVEditor.instance;

                    if (uvEditor != null && uvEditor.ClickShortcutCheck(mesh, s_Selection.face))
                    {
                        return(null);
                    }

                    var faces = mesh.faces as Face[] ?? mesh.faces.ToArray();
                    var ind   = Array.IndexOf <Face>(faces, s_Selection.face);
                    var sel   = mesh.selectedFaceIndexes.IndexOf(ind);

                    UndoUtility.RecordSelection(mesh, "Select Face");

                    if (sel > -1)
                    {
                        mesh.RemoveFromFaceSelectionAtIndex(sel);
                    }
                    else
                    {
                        mesh.AddToFaceSelection(ind);
                    }
                }
                else if (s_Selection.edge != Edge.Empty)
                {
                    int ind = mesh.IndexOf(mesh.selectedEdges, s_Selection.edge);

                    UndoUtility.RecordSelection(mesh, "Select Edge");

                    if (ind > -1)
                    {
                        mesh.SetSelectedEdges(mesh.selectedEdges.ToArray().RemoveAt(ind));
                    }
                    else
                    {
                        mesh.SetSelectedEdges(mesh.selectedEdges.ToArray().Add(s_Selection.edge));
                    }
                }
                else if (s_Selection.vertex > -1)
                {
                    int ind = Array.IndexOf(mesh.selectedIndexesInternal, s_Selection.vertex);

                    UndoUtility.RecordSelection(mesh, "Select Vertex");

                    if (ind > -1)
                    {
                        mesh.SetSelectedVertices(mesh.selectedIndexesInternal.RemoveAt(ind));
                    }
                    else
                    {
                        mesh.SetSelectedVertices(mesh.selectedIndexesInternal.Add(s_Selection.vertex));
                    }
                }

                return(mesh);
            }

            return(null);
        }
Beispiel #11
0
        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();

            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 elementSelection)
                {
                    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();
        }
Beispiel #12
0
        void OnSceneGUI()
        {
            if (polygon.polyEditMode == PolyShape.PolyEditMode.None)
            {
                return;
            }

            if (polygon == null || Tools.current != Tool.None)
            {
                SetPolyEditMode(PolyShape.PolyEditMode.None);
                return;
            }

            if (m_LineMaterial != null)
            {
                m_LineMaterial.SetPass(0);
                Graphics.DrawMeshNow(m_LineMesh, polygon.transform.localToWorldMatrix, 0);
            }

            Event evt = Event.current;

            // used when finishing a loop by clicking the first created point
            if (m_NextMouseUpAdvancesMode && evt.type == EventType.MouseUp)
            {
                evt.Use();

                m_NextMouseUpAdvancesMode = false;

                if (SceneCameraIsAlignedWithPolyUp())
                {
                    SetPolyEditMode(PolyShape.PolyEditMode.Edit);
                }
                else
                {
                    SetPolyEditMode(PolyShape.PolyEditMode.Height);
                }
            }

            if (m_IsModifyingVertices && (
                    evt.type == EventType.MouseUp ||
                    evt.type == EventType.Ignore ||
                    evt.type == EventType.KeyDown ||
                    evt.type == EventType.KeyUp))
            {
                OnFinishVertexMovement();
            }

            DoExistingPointsGUI();

            if (evt.type == EventType.KeyDown)
            {
                HandleKeyEvent(evt);
            }

            if (EditorHandleUtility.SceneViewInUse(evt))
            {
                return;
            }

            int controlID = GUIUtility.GetControlID(FocusType.Passive);

            HandleUtility.AddDefaultControl(controlID);

            DoPointPlacement();
        }
        protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation)
        {
            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.ScaleSlider(m_Scale.x, Vector3.zero, Vector3.right, Quaternion.identity, size, snap);

            Handles.color = Color.green;
            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);

            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 elementSelection)
                {
                    if (!(mesh is MeshAndTextures))
                    {
                        continue;
                    }

                    var mat       = (MeshAndTextures)mesh;
                    var origins   = mat.origins;
                    var positions = mat.textures;

                    foreach (var group in mesh.elementGroups)
                    {
                        foreach (var index in group.indices)
                        {
                            positions[index] = mat.postApplyMatrix.MultiplyPoint(
                                Vector2.Scale(mat.preApplyMatrix.MultiplyPoint3x4(origins[index]), delta));
                        }
                    }

                    mesh.mesh.mesh.SetUVs(k_TextureChannel, positions);
                }
            }
        }
        void OnSceneGUI()
        {
            Event e = Event.current;

            bool eventHasBeenUsed = false;

            if (m_IsMoving)
            {
                if (e.type == EventType.Ignore ||
                    e.type == EventType.MouseUp)
                {
                    eventHasBeenUsed = true;
                    OnFinishVertexModification();
                }
            }

            bool sceneViewInUse = EditorHandleUtility.SceneViewInUse(e);

            if (e.type == EventType.KeyDown)
            {
                if (e.keyCode == KeyCode.Backspace && m_currentHandle > -1 && m_currentHandle < m_Points.Count)
                {
                    UndoUtility.RecordObject(m_Target, "Delete Bezier Point");
                    m_Points.RemoveAt(m_currentHandle);
                    UpdateMesh(true);
                }
                else if (e.keyCode == KeyCode.Escape)
                {
                    SetIsEditing(false);
                }
            }

            int count = m_Points.Count;

            Matrix4x4 handleMatrix = Handles.matrix;

            Handles.matrix = m_Target.transform.localToWorldMatrix;

            EditorGUI.BeginChangeCheck();

            for (int index = 0; index < count; index++)
            {
                if (index < count - 1 || m_CloseLoop)
                {
                    Handles.DrawBezier(m_Points[index].position,
                                       m_Points[(index + 1) % count].position,
                                       m_Points[index].tangentOut,
                                       m_Points[(index + 1) % count].tangentIn,
                                       Color.green,
                                       EditorGUIUtility.whiteTexture,
                                       1f);
                }

                if (!m_IsEditing)
                {
                    continue;
                }

                // If the index is selected show the full transform gizmo, otherwise use free move handles
                if (m_currentHandle == index)
                {
                    BezierPoint point = m_Points[index];

                    if (!m_currentHandle.isTangent)
                    {
                        Vector3 prev = point.position;

                        prev = Handles.PositionHandle(prev, Quaternion.identity);

                        if (!Math.Approx3(prev, point.position))
                        {
                            if (!m_IsMoving)
                            {
                                OnBeginVertexModification();
                            }

                            prev = EditorSnapping.MoveSnap(prev);

                            Vector3 dir = prev - point.position;
                            point.position    = prev;
                            point.tangentIn  += dir;
                            point.tangentOut += dir;
                        }

                        // rotation
                        int     prev_index = index > 0 ? index - 1 : (m_CloseLoop ? count - 1 : -1);
                        int     next_index = index < count - 1 ? index + 1 : (m_CloseLoop ? 0 : -1);
                        Vector3 rd         = BezierPoint.GetLookDirection(m_Points, index, prev_index, next_index);

                        Quaternion look = Quaternion.LookRotation(rd);
                        float      size = HandleUtility.GetHandleSize(point.position);
                        Matrix4x4  pm   = Handles.matrix;
                        Handles.matrix = pm * Matrix4x4.TRS(point.position, look, Vector3.one);
                        point.rotation = Handles.Disc(point.rotation, Vector3.zero, Vector3.forward, size, false, 0f);
                        Handles.matrix = pm;
                    }
                    else
                    {
                        Handles.color = bezierTangentHandleColor;

                        if (m_currentHandle.tangent == BezierTangentDirection.In && (m_CloseLoop || index > 0))
                        {
                            EditorGUI.BeginChangeCheck();
                            point.tangentIn = Handles.PositionHandle(point.tangentIn, Quaternion.identity);
                            if (EditorGUI.EndChangeCheck())
                            {
                                if (!m_IsMoving)
                                {
                                    OnBeginVertexModification();
                                }

                                point.tangentIn = EditorSnapping.MoveSnap(point.tangentIn);
                                point.EnforceTangentMode(BezierTangentDirection.In, m_TangentMode);
                            }
                            Handles.color = Color.blue;
                            Handles.DrawLine(m_Points[index].position, m_Points[index].tangentIn);
                        }

                        if (m_currentHandle.tangent == BezierTangentDirection.Out && (m_CloseLoop || index < count - 1))
                        {
                            EditorGUI.BeginChangeCheck();
                            point.tangentOut = Handles.PositionHandle(point.tangentOut, Quaternion.identity);
                            if (EditorGUI.EndChangeCheck())
                            {
                                if (!m_IsMoving)
                                {
                                    OnBeginVertexModification();
                                }

                                point.tangentOut = EditorSnapping.MoveSnap(point.tangentOut);
                                point.EnforceTangentMode(BezierTangentDirection.Out, m_TangentMode);
                            }
                            Handles.color = Color.red;
                            Handles.DrawLine(m_Points[index].position, m_Points[index].tangentOut);
                        }
                    }

                    m_Points[index] = point;
                }
            }

            if (!m_IsEditing)
            {
                return;
            }

            EventType eventType = e.type;

            if (!eventHasBeenUsed)
            {
                eventHasBeenUsed = eventType == EventType.Used;
            }

            for (int index = 0; index < count; index++)
            {
                Vector3     prev;
                BezierPoint point = m_Points[index];

                // Position Handle
                float size = HandleUtility.GetHandleSize(point.position) * k_HandleSize;
                Handles.color = bezierPositionHandleColor;

                if (m_currentHandle == index && !m_currentHandle.isTangent)
                {
                    Handles.DotHandleCap(0, point.position, Quaternion.identity, size, e.type);
                }
                else
                {
                    prev = point.position;
                    prev = Handles.FreeMoveHandle(prev, Quaternion.identity, size, Vector3.zero, Handles.DotHandleCap);
                    if (!eventHasBeenUsed && eventType == EventType.MouseUp && e.type == EventType.Used)
                    {
                        eventHasBeenUsed = true;
                        m_currentHandle  = (BezierHandle)index;
                        Repaint();
                        SceneView.RepaintAll();
                    }
                    else if (!Math.Approx3(prev, point.position))
                    {
                        if (!m_IsMoving)
                        {
                            OnBeginVertexModification();
                        }

                        point.SetPosition(EditorSnapping.MoveSnap(prev));
                    }
                }

                // Tangent handles
                Handles.color = bezierTangentHandleColor;

                // Tangent In Handle
                if (m_CloseLoop || index > 0)
                {
                    size = HandleUtility.GetHandleSize(point.tangentIn) * k_HandleSize;
                    Handles.DrawLine(point.position, point.tangentIn);

                    if (index == m_currentHandle && m_currentHandle.isTangent && m_currentHandle.tangent == BezierTangentDirection.In)
                    {
                        Handles.DotHandleCap(0, point.tangentIn, Quaternion.identity, size, e.type);
                    }
                    else
                    {
                        prev = point.tangentIn;
                        prev = Handles.FreeMoveHandle(prev, Quaternion.identity, size, Vector3.zero, Handles.DotHandleCap);

                        if (!eventHasBeenUsed && eventType == EventType.MouseUp && e.type == EventType.Used)
                        {
                            eventHasBeenUsed = true;
                            m_currentHandle.SetIndexAndTangent(index, BezierTangentDirection.In);
                            Repaint();
                            SceneView.RepaintAll();
                        }
                        else if (!Math.Approx3(prev, point.tangentIn))
                        {
                            if (!m_IsMoving)
                            {
                                OnBeginVertexModification();
                            }
                            point.tangentIn = EditorSnapping.MoveSnap(prev);
                            point.EnforceTangentMode(BezierTangentDirection.In, m_TangentMode);
                        }
                    }
                }

                // Tangent Out
                if (m_CloseLoop || index < count - 1)
                {
                    size = HandleUtility.GetHandleSize(point.tangentOut) * k_HandleSize;
                    Handles.DrawLine(point.position, point.tangentOut);

                    if (index == m_currentHandle && m_currentHandle.isTangent && m_currentHandle.tangent == BezierTangentDirection.Out)
                    {
                        Handles.DotHandleCap(0, point.tangentOut, Quaternion.identity, size, e.type);
                    }
                    else
                    {
                        prev = point.tangentOut;
                        prev = Handles.FreeMoveHandle(prev, Quaternion.identity, size, Vector3.zero, Handles.DotHandleCap);

                        if (!eventHasBeenUsed && eventType == EventType.MouseUp && e.type == EventType.Used)
                        {
                            eventHasBeenUsed = true;
                            m_currentHandle.SetIndexAndTangent(index, BezierTangentDirection.Out);
                            Repaint();
                            SceneView.RepaintAll();
                        }
                        else if (!Math.Approx3(prev, point.tangentOut))
                        {
                            if (!m_IsMoving)
                            {
                                OnBeginVertexModification();
                            }
                            point.tangentOut = EditorSnapping.MoveSnap(prev);
                            point.EnforceTangentMode(BezierTangentDirection.Out, m_TangentMode);
                        }
                    }
                }

                m_Points[index] = point;
            }

            // Do control point insertion
            if (!eventHasBeenUsed && m_ControlPoints != null && m_ControlPoints.Count > 1)
            {
                int   index = -1;
                float distanceToLine;

                Vector3 p = EditorHandleUtility.ClosestPointToPolyLine(m_ControlPoints, out index, out distanceToLine, false, null);

                if (!IsHoveringHandlePoint(e.mousePosition) && distanceToLine < PreferenceKeys.k_MaxPointDistanceFromControl)
                {
                    Handles.color = Color.green;
                    Handles.DotHandleCap(-1, p, Quaternion.identity, HandleUtility.GetHandleSize(p) * .05f, e.type);
                    Handles.color = Color.white;

                    if (!eventHasBeenUsed && eventType == EventType.MouseDown && e.button == 0)
                    {
                        UndoUtility.RecordObject(m_Target, "Add Point");
                        Vector3 dir = m_ControlPoints[(index + 1) % m_ControlPoints.Count] - m_ControlPoints[index];
                        m_Points.Insert((index / m_Columns) + 1, new BezierPoint(p, p - dir, p + dir, Quaternion.identity));
                        UpdateMesh(true);
                        e.Use();
                    }

                    SceneView.RepaintAll();
                }
            }

            if (e.type == EventType.MouseUp && !sceneViewInUse)
            {
                m_currentHandle.SetIndex(-1);
            }

            Handles.matrix = handleMatrix;

            if (EditorGUI.EndChangeCheck())
            {
                UpdateMesh(false);
            }
        }
        public override ShapeState DoState(Event evt)
        {
            if (evt.type == EventType.KeyDown)
            {
                switch (evt.keyCode)
                {
                case KeyCode.Escape:
                    ToolManager.RestorePreviousTool();
                    break;
                }
            }

            if (tool.m_LastShapeCreated != null)
            {
                EditShapeTool.DoEditingHandles(tool.m_LastShapeCreated, true);
            }

            if (evt.isMouse && HandleUtility.nearestControl == tool.controlID)
            {
                var res = EditorHandleUtility.FindBestPlaneAndBitangent(evt.mousePosition);

                Ray   ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition);
                float hit;

                if (res.item1.Raycast(ray, out hit))
                {
                    //Plane init
                    tool.m_Plane        = res.item1;
                    tool.m_PlaneForward = res.item2;
                    tool.m_PlaneRight   = Vector3.Cross(tool.m_Plane.normal, tool.m_PlaneForward);

                    var planeNormal = tool.m_Plane.normal;
                    var planeCenter = tool.m_Plane.normal * -tool.m_Plane.distance;
                    // if hit point on plane is cardinal axis and on grid, snap to grid.
                    if (Math.IsCardinalAxis(planeNormal))
                    {
                        const float epsilon = .00001f;
                        bool        offGrid = false;
                        Vector3     snapVal = EditorSnapping.activeMoveSnapValue;
                        Vector3     center  =
                            Vector3.Scale(ProBuilderSnapping.GetSnappingMaskBasedOnNormalVector(planeNormal),
                                          planeCenter);
                        for (int i = 0; i < 3; i++)
                        {
                            offGrid |= Mathf.Abs(snapVal[i] % center[i]) > epsilon;
                        }
                        tool.m_IsOnGrid = !offGrid;
                    }
                    else
                    {
                        tool.m_IsOnGrid = false;
                    }

                    m_HitPosition = tool.GetPoint(ray.GetPoint(hit));

                    //Click has been done => Define a plane for the tool
                    if (evt.type == EventType.MouseDown)
                    {
                        //BB init
                        tool.m_BB_Origin         = m_HitPosition;
                        tool.m_BB_HeightCorner   = tool.m_BB_Origin;
                        tool.m_BB_OppositeCorner = tool.m_BB_Origin;

                        return(NextState());
                    }
                }
                else
                {
                    m_HitPosition = Vector3.negativeInfinity;
                }
            }

            if (GUIUtility.hotControl == 0 && evt.shift && !(evt.control || evt.command))
            {
                tool.DuplicatePreview(m_HitPosition);
            }
            else if (tool.m_DuplicateGO != null)
            {
                Object.DestroyImmediate(tool.m_DuplicateGO);
            }

            // Repaint to visualize the placement preview dot
            if (evt.type == EventType.MouseMove && HandleUtility.nearestControl == tool.controlID)
            {
                HandleUtility.Repaint();
            }

            if (evt.type == EventType.Repaint)
            {
                if (GUIUtility.hotControl == 0 && HandleUtility.nearestControl == tool.controlID)
                {
                    using (new Handles.DrawingScope(EditorHandleDrawing.vertexSelectedColor))
                    {
                        Handles.DotHandleCap(-1, m_HitPosition, Quaternion.identity,
                                             HandleUtility.GetHandleSize(m_HitPosition) * 0.05f, EventType.Repaint);
                    }
                }

                if (GUIUtility.hotControl == 0 && evt.shift && !(evt.control || evt.command))
                {
                    tool.DrawBoundingBox(false);
                }
            }

            return(this);
        }
Beispiel #16
0
        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();

            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 = ProGridsSnapping.SnapValue(m_Position.x, relativeSnapX);
                    m_Position.y = ProGridsSnapping.SnapValue(m_Position.y, relativeSnapY);
                }
                else if (progridsSnapEnabled)
                {
                    m_Position.x = ProGridsSnapping.SnapValue(m_Position.x, progridsSnapValue);
                    m_Position.y = ProGridsSnapping.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 value in elementSelection)
                {
                    var selection = value as TranslateTextureSelection;

                    if (selection == null)
                    {
                        continue;
                    }

                    // Account for object scale
                    delta *= k_Vector3Magnitude / selection.mesh.transform.lossyScale.magnitude;

                    var origins   = selection.origins;
                    var positions = selection.textures;

                    // Translating faces is treated as a special case because we want the textures in scene to visually
                    // match the movement of the translation handle. When UVs are scaled, they have the appearance of
                    // moving faster or slower (even though they are translating the correct distances). To avoid this,
                    // we cache the UV scale of each face and modify the translation delta accordingly. This isn't perfect,
                    // as it will not be able to find the scale for sheared or otherwise distorted face UVs. However, for
                    // most cases it maps quite well.
                    if (ProBuilderEditor.selectMode == SelectMode.TextureFace)
                    {
                        foreach (var face in selection.faceAndScale)
                        {
                            var faceDelta = new Vector4(delta.x / face.item2.x, delta.y / face.item2.y, 0f, 0f);

                            foreach (var index in face.item1.distinctIndexes)
                            {
                                positions[index] = origins[index] + faceDelta;
                            }
                        }
                    }
                    else
                    {
                        foreach (var group in value.elementGroups)
                        {
                            foreach (var index in group.indices)
                            {
                                positions[index] = origins[index] + delta;
                            }
                        }
                    }

                    selection.mesh.mesh.SetUVs(k_TextureChannel, positions);
                }
            }

            EditorHandleUtility.PopMatrix();
        }
        void OnSceneGUI(SceneView sceneView)
        {
            SceneStyles.Init();

            m_CurrentEvent = Event.current;

            EditorHandleDrawing.DrawSceneHandles(SceneDragAndDropListener.isDragging ? SelectMode.None : selectMode);

            DrawHandleGUI(sceneView);

            if (m_CurrentEvent.type == EventType.KeyDown)
            {
                // Escape isn't assignable as a shortcut
                if (m_CurrentEvent.keyCode == KeyCode.Escape && selectMode != SelectMode.Object)
                {
                    selectMode = SelectMode.Object;

                    m_IsDragging          = false;
                    m_IsReadyForMouseDrag = false;

                    m_CurrentEvent.Use();
                }
            }

            if (selectMode == SelectMode.Object)
            {
                return;
            }

            bool pathSelectionModifier = EditorHandleUtility.IsSelectionPathModifier(m_CurrentEvent.modifiers);

            // Check mouse position in scene and determine if we should highlight something
            if (s_ShowHoverHighlight &&
                selectMode.IsMeshElementMode() &&
                (m_CurrentEvent.type == EventType.MouseMove ||
                 (m_wasSelectingPath != pathSelectionModifier && m_CurrentEvent.isKey)))
            {
                m_Hovering.CopyTo(m_HoveringPrevious);
                if (GUIUtility.hotControl != 0 ||
                    EditorSceneViewPicker.MouseRayHitTest(m_CurrentEvent.mousePosition, selectMode, m_ScenePickerPreferences, m_Hovering) > ScenePickerPreferences.maxPointerDistance)
                {
                    m_Hovering.Clear();
                }

                if (!m_Hovering.Equals(m_HoveringPrevious))
                {
                    if (pathSelectionModifier)
                    {
                        EditorSceneViewPicker.DoMouseHover(m_Hovering);
                    }

                    SceneView.RepaintAll();
                }
            }

            m_wasSelectingPath = pathSelectionModifier;

            if (Tools.current == Tool.View)
            {
                return;
            }

            switch (m_CurrentEvent.type)
            {
            case EventType.ValidateCommand:
            case EventType.ExecuteCommand:
                bool execute = m_CurrentEvent.type == EventType.ExecuteCommand;
                switch (m_CurrentEvent.commandName)
                {
                case "SelectAll":
                    if (execute)
                    {
                        SelectAll();
                    }
                    m_CurrentEvent.Use();
                    break;

                case "DeselectAll":
                    if (execute)
                    {
                        DeselectAll();
                    }
                    m_CurrentEvent.Use();
                    break;

                case "InvertSelection":
                    if (execute)
                    {
                        InvertSelection();
                    }
                    m_CurrentEvent.Use();
                    break;
                }
                break;
            }

            if (EditorHandleUtility.SceneViewInUse(m_CurrentEvent))
            {
                if (m_IsDragging)
                {
                    m_IsDragging = false;
                }

                if (GUIUtility.hotControl == m_DefaultControl)
                {
                    GUIUtility.hotControl = 0;
                }

                return;
            }

            // This prevents us from selecting other objects in the scene,
            // and allows for the selection of faces / vertices.
            m_DefaultControl = GUIUtility.GetControlID(FocusType.Passive);
            if (Event.current.type == EventType.Layout)
            {
                HandleUtility.AddDefaultControl(m_DefaultControl);
            }

            if (m_CurrentEvent.type == EventType.MouseDown && HandleUtility.nearestControl == m_DefaultControl)
            {
                // double clicking object
                if (m_CurrentEvent.clickCount > 1)
                {
                    DoubleClick(m_CurrentEvent);
                }

                m_InitialMousePosition = m_CurrentEvent.mousePosition;
                // readyForMouseDrag prevents a bug wherein after ending a drag an errant
                // MouseDrag event is sent with no corresponding MouseDown/MouseUp event.
                m_IsReadyForMouseDrag = true;

                GUIUtility.hotControl = m_DefaultControl;
            }

            if (m_CurrentEvent.type == EventType.MouseDrag && m_IsReadyForMouseDrag && GUIUtility.hotControl == m_DefaultControl)
            {
                if (!m_IsDragging && Vector2.Distance(m_CurrentEvent.mousePosition, m_InitialMousePosition) > k_MouseDragThreshold)
                {
                    sceneView.Repaint();
                    m_IsDragging = true;
                }
            }

            if (m_CurrentEvent.type == EventType.Ignore)
            {
                if (m_IsDragging)
                {
                    m_IsReadyForMouseDrag = false;
                    m_IsDragging          = false;
                    EditorSceneViewPicker.DoMouseDrag(m_MouseDragRect, selectMode, m_ScenePickerPreferences);
                }

                if (m_WasDoubleClick)
                {
                    m_WasDoubleClick = false;
                }

                if (GUIUtility.hotControl == m_DefaultControl)
                {
                    GUIUtility.hotControl = 0;
                }
            }

            if (m_CurrentEvent.type == EventType.MouseUp && GUIUtility.hotControl == m_DefaultControl)
            {
                GUIUtility.hotControl = 0;

                if (m_WasDoubleClick)
                {
                    m_WasDoubleClick = false;
                }
                else
                {
                    if (!m_IsDragging)
                    {
                        if (UVEditor.instance)
                        {
                            UVEditor.instance.ResetUserPivot();
                        }

                        EditorSceneViewPicker.DoMouseClick(m_CurrentEvent, selectMode, m_ScenePickerPreferences);
                        UpdateSelection();
                    }
                    else
                    {
                        m_IsDragging          = false;
                        m_IsReadyForMouseDrag = false;

                        if (UVEditor.instance)
                        {
                            UVEditor.instance.ResetUserPivot();
                        }

                        EditorSceneViewPicker.DoMouseDrag(m_MouseDragRect, selectMode, m_ScenePickerPreferences);

                        if (GUIUtility.hotControl == m_DefaultControl)
                        {
                            GUIUtility.hotControl = 0;
                        }
                    }
                }
            }
        }
        void OnSceneGUI(SceneView sceneView)
        {
            SceneStyles.Init();

            m_CurrentEvent = Event.current;

            EditorHandleDrawing.DrawSceneHandles(SceneDragAndDropListener.isDragging ? SelectMode.None : selectMode);

            DrawHandleGUI(sceneView);

            if (m_CurrentEvent.type == EventType.KeyDown)
            {
                // Escape isn't assignable as a shortcut
                if (m_CurrentEvent.keyCode == KeyCode.Escape && selectMode != SelectMode.Object)
                {
                    selectMode = SelectMode.Object;

                    m_IsDragging          = false;
                    m_IsReadyForMouseDrag = false;

                    m_CurrentEvent.Use();
                }
            }

            if (selectMode == SelectMode.Object)
            {
                return;
            }

            bool pathSelectionModifier = EditorHandleUtility.IsSelectionPathModifier(m_CurrentEvent.modifiers);

            // Check mouse position in scene and determine if we should highlight something
            if (s_ShowHoverHighlight &&
                selectMode.IsMeshElementMode() &&
                (m_CurrentEvent.type == EventType.MouseMove ||
                 (m_wasSelectingPath != pathSelectionModifier && m_CurrentEvent.isKey)))
            {
                m_Hovering.CopyTo(m_HoveringPrevious);
                if (GUIUtility.hotControl != 0 ||
                    EditorSceneViewPicker.MouseRayHitTest(m_CurrentEvent.mousePosition, selectMode, m_ScenePickerPreferences, m_Hovering) > ScenePickerPreferences.maxPointerDistance)
                {
                    m_Hovering.Clear();
                }

                if (!m_Hovering.Equals(m_HoveringPrevious))
                {
                    if (pathSelectionModifier)
                    {
                        EditorSceneViewPicker.DoMouseHover(m_Hovering);
                    }

                    SceneView.RepaintAll();
                }
            }

            m_wasSelectingPath = pathSelectionModifier;

            if (Tools.current == Tool.View)
            {
                return;
            }

            switch (m_CurrentEvent.type)
            {
            case EventType.ValidateCommand:
            case EventType.ExecuteCommand:
                bool execute = m_CurrentEvent.type == EventType.ExecuteCommand;
                switch (m_CurrentEvent.commandName)
                {
                case "SelectAll":
                    if (execute)
                    {
                        SelectAll();
                    }
                    m_CurrentEvent.Use();
                    break;

                case "DeselectAll":
                    if (execute)
                    {
                        DeselectAll();
                    }
                    m_CurrentEvent.Use();
                    break;

                case "InvertSelection":
                    if (execute)
                    {
                        InvertSelection();
                    }
                    m_CurrentEvent.Use();
                    break;
                }
                break;
            }

            if (EditorHandleUtility.SceneViewInUse(m_CurrentEvent))
            {
                if (m_IsDragging)
                {
                    m_IsDragging = false;
                }

                if (GUIUtility.hotControl == m_DefaultControl)
                {
                    GUIUtility.hotControl = 0;
                }

                return;
            }

            // This prevents us from selecting other objects in the scene,
            // and allows for the selection of faces / vertices.
            m_DefaultControl = GUIUtility.GetControlID(FocusType.Passive);
            if (Event.current.type == EventType.Layout)
            {
                HandleUtility.AddDefaultControl(m_DefaultControl);
            }

            HandleMouseEvent(sceneView, m_DefaultControl);
        }
Beispiel #19
0
        protected override void DoTool(Vector3 handlePosition, Quaternion handleRotation)
        {
            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 elementSelection)
                {
                    if (!(mesh is MeshAndTextures))
                    {
                        continue;
                    }
                    var mat = (MeshAndTextures)mesh;

                    var origins   = mat.origins;
                    var positions = mat.textures;

                    foreach (var group in mat.elementGroups)
                    {
                        foreach (var index in group.indices)
                        {
                            positions[index] = mat.postApplyMatrix.MultiplyPoint(
                                Math.RotateAroundPoint(
                                    mat.preApplyMatrix.MultiplyPoint3x4(origins[index]), Vector2.zero, -m_Rotation));
                        }
                    }

                    mesh.mesh.mesh.SetUVs(k_TextureChannel, positions);
                }
            }
        }
        public static ProBuilderMesh DoMouseClick(Event evt, SelectMode selectionMode, ScenePickerPreferences pickerPreferences)
        {
            bool appendModifier         = EditorHandleUtility.IsAppendModifier(evt.modifiers);
            bool addToSelectionModifier = EditorHandleUtility.IsSelectionAddModifier(evt.modifiers);
            bool addOrRemoveIfPresentFromSelectionModifier = EditorHandleUtility.IsSelectionAppendOrRemoveIfPresentModifier(evt.modifiers);
            bool pathSelectionModifier = EditorHandleUtility.IsSelectionPathModifier(evt.modifiers);

            float pickedElementDistance;

            if (selectionMode.ContainsFlag(SelectMode.Edge | SelectMode.TextureEdge))
            {
                pickedElementDistance = EdgeRaycast(evt.mousePosition, pickerPreferences, k_AllowUnselected, s_Selection);
            }
            else if (selectionMode.ContainsFlag(SelectMode.Vertex | SelectMode.TextureVertex))
            {
                pickedElementDistance = VertexRaycast(evt.mousePosition, pickerPreferences, k_AllowUnselected, s_Selection);
            }
            else
            {
                pickedElementDistance = FaceRaycast(evt.mousePosition, pickerPreferences, k_AllowUnselected, s_Selection, evt.clickCount > 1 ? -1 : 0, false);
            }

            evt.Use();

            if (!appendModifier)
            {
                if (s_Selection.mesh != null)
                {
                    s_Selection.mesh.ClearSelection();
                }
                MeshSelection.SetSelection((GameObject)null);
            }

            if (pickedElementDistance > ScenePickerPreferences.maxPointerDistance)
            {
                if (appendModifier && Selection.gameObjects.Contains(s_Selection.gameObject))
                {
                    MeshSelection.RemoveFromSelection(s_Selection.gameObject);
                }
                else
                {
                    MeshSelection.AddToSelection(s_Selection.gameObject);
                }

                return(null);
            }

            GameObject candidateNewActiveObject     = s_Selection.gameObject;
            bool       activeObjectSelectionChanged = Selection.gameObjects.Contains(s_Selection.gameObject) && s_Selection.gameObject != Selection.activeGameObject;

            if (s_Selection.mesh != null)
            {
                var mesh = s_Selection.mesh;

                foreach (var face in s_Selection.faces)
                {
                    // Check for other editor mouse shortcuts first (todo proper event handling for mouse shortcuts)
                    MaterialEditor matEditor = MaterialEditor.instance;

                    if (matEditor != null && matEditor.ClickShortcutCheck(Event.current.modifiers, mesh, face))
                    {
                        return(null);
                    }

                    UVEditor uvEditor = UVEditor.instance;

                    if (uvEditor != null && uvEditor.ClickShortcutCheck(mesh, face))
                    {
                        return(null);
                    }

                    var faces = mesh.faces as Face[] ?? mesh.faces.ToArray();
                    var ind   = Array.IndexOf <Face>(faces, face);
                    var sel   = mesh.selectedFaceIndexes.IndexOf(ind);

                    UndoUtility.RecordSelection(mesh, "Select Face");

                    if (sel > -1)
                    {
                        if (!appendModifier || addOrRemoveIfPresentFromSelectionModifier ||
                            (addToSelectionModifier && face == mesh.GetActiveFace() && !activeObjectSelectionChanged))
                        {
                            mesh.RemoveFromFaceSelectionAtIndex(sel);

                            if (addOrRemoveIfPresentFromSelectionModifier && activeObjectSelectionChanged)
                            {
                                candidateNewActiveObject = Selection.activeGameObject;
                            }
                            else if (mesh.selectedFaceCount == 0)
                            {
                                for (var i = MeshSelection.topInternal.Count - 1; i >= 0; i--)
                                {
                                    if (MeshSelection.topInternal[i].selectedFaceCount > 0)
                                    {
                                        candidateNewActiveObject     = MeshSelection.topInternal[i].gameObject;
                                        activeObjectSelectionChanged = true;
                                        break;
                                    }
                                }
                            }
                        }
                        else
                        {
                            mesh.selectedFaceIndicesInternal = mesh.selectedFaceIndicesInternal.Remove(ind);
                            mesh.SetSelectedFaces(mesh.selectedFaceIndicesInternal.Add(ind));
                        }
                    }
                    else if (pathSelectionModifier && mesh.GetActiveFace() != null)
                    {
                        var pathFaces = SelectPathFaces.GetPath(mesh, Array.IndexOf <Face>(faces, mesh.GetActiveFace()),
                                                                Array.IndexOf <Face>(faces, face));
                        foreach (var pathFace in pathFaces)
                        {
                            mesh.AddToFaceSelection(pathFace);
                        }
                    }
                    else
                    {
                        mesh.AddToFaceSelection(ind);
                    }
                }

                foreach (var edge in s_Selection.edges)
                {
                    int ind = mesh.IndexOf(mesh.selectedEdges, edge);

                    UndoUtility.RecordSelection(mesh, "Select Edge");

                    if (ind > -1)
                    {
                        if (!appendModifier || addOrRemoveIfPresentFromSelectionModifier ||
                            (addToSelectionModifier && edge == mesh.GetActiveEdge() && !activeObjectSelectionChanged))
                        {
                            mesh.SetSelectedEdges(mesh.selectedEdges.ToArray().RemoveAt(ind));

                            if (addOrRemoveIfPresentFromSelectionModifier && activeObjectSelectionChanged)
                            {
                                candidateNewActiveObject = Selection.activeGameObject;
                            }
                            else if (mesh.selectedEdgeCount == 0)
                            {
                                for (var i = MeshSelection.topInternal.Count - 1; i >= 0; i--)
                                {
                                    if (MeshSelection.topInternal[i].selectedEdgeCount > 0)
                                    {
                                        candidateNewActiveObject     = MeshSelection.topInternal[i].gameObject;
                                        activeObjectSelectionChanged = true;
                                        break;
                                    }
                                }
                            }
                        }
                        else
                        {
                            mesh.selectedEdgesInternal = mesh.selectedEdgesInternal.Remove(edge);
                            mesh.SetSelectedEdges(mesh.selectedEdgesInternal.Add(edge));
                        }
                    }
                    else
                    {
                        mesh.SetSelectedEdges(mesh.selectedEdges.ToArray().Add(edge));
                    }
                }
                foreach (var vertex in s_Selection.vertexes)
                {
                    int ind = Array.IndexOf(mesh.selectedIndexesInternal, vertex);

                    UndoUtility.RecordSelection(mesh, "Select Vertex");

                    if (ind > -1)
                    {
                        var sharedIndex  = mesh.sharedVertexLookup[vertex];
                        var sharedVertex = mesh.sharedVerticesInternal[sharedIndex];
                        s_IndexBuffer.Clear();
                        foreach (var sVertex in sharedVertex)
                        {
                            var index = Array.IndexOf(mesh.selectedIndexesInternal, sVertex);
                            if (index < 0)
                            {
                                continue;
                            }

                            s_IndexBuffer.Add(index);
                        }
                        s_IndexBuffer.Sort();

                        if (!appendModifier || addOrRemoveIfPresentFromSelectionModifier ||
                            (addToSelectionModifier && vertex == mesh.GetActiveVertex() && !activeObjectSelectionChanged))
                        {
                            mesh.selectedIndexesInternal = mesh.selectedIndexesInternal.SortedRemoveAt(s_IndexBuffer);
                            mesh.SetSelectedVertices(mesh.selectedIndexesInternal);

                            if (addOrRemoveIfPresentFromSelectionModifier && activeObjectSelectionChanged)
                            {
                                candidateNewActiveObject = Selection.activeGameObject;
                            }
                            else if (mesh.selectedIndexesInternal.Length == 0)
                            {
                                for (var i = MeshSelection.topInternal.Count - 1; i >= 0; i--)
                                {
                                    if (MeshSelection.topInternal[i].selectedIndexesInternal.Length > 0)
                                    {
                                        candidateNewActiveObject     = MeshSelection.topInternal[i].gameObject;
                                        activeObjectSelectionChanged = true;
                                        break;
                                    }
                                }
                            }
                        }
                        else
                        {
                            mesh.selectedIndexesInternal = mesh.selectedIndexesInternal.SortedRemoveAt(s_IndexBuffer);
                            mesh.SetSelectedVertices(mesh.selectedIndexesInternal.Add(vertex));
                        }
                    }
                    else
                    {
                        mesh.SetSelectedVertices(mesh.selectedIndexesInternal.Add(vertex));
                    }
                }

                if (activeObjectSelectionChanged)
                {
                    MeshSelection.MakeActiveObject(candidateNewActiveObject);
                }
                else
                {
                    MeshSelection.AddToSelection(candidateNewActiveObject);
                }

                return(mesh);
            }

            return(null);
        }
Beispiel #21
0
        void DoPointPlacement()
        {
            Event     evt       = Event.current;
            EventType eventType = evt.type;

            if (m_PlacingPoint)
            {
                Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition);

                if (eventType == EventType.MouseDrag)
                {
                    float hitDistance = Mathf.Infinity;

                    if (m_Plane.Raycast(ray, out hitDistance))
                    {
                        evt.Use();

                        polygon.m_Points[m_SelectedIndex] = ProGridsInterface.ProGridsSnap(polygon.transform.InverseTransformPoint(ray.GetPoint(hitDistance)), Vector3.one);
                        RebuildPolyShapeMesh(false);
                        SceneView.RepaintAll();
                    }
                }

                if (eventType == EventType.MouseUp ||
                    eventType == EventType.Ignore ||
                    eventType == EventType.KeyDown ||
                    eventType == EventType.KeyUp)
                {
                    evt.Use();
                    m_PlacingPoint  = false;
                    m_SelectedIndex = -1;
                    SceneView.RepaintAll();
                }
            }
            else if (polygon.polyEditMode == PolyShape.PolyEditMode.Path)
            {
                if (eventType == EventType.MouseDown)
                {
                    if (polygon.m_Points.Count < 1)
                    {
                        SetupInputPlane(evt.mousePosition);
                    }

                    float hitDistance = Mathf.Infinity;

                    Ray ray = HandleUtility.GUIPointToWorldRay(evt.mousePosition);

                    if (m_Plane.Raycast(ray, out hitDistance))
                    {
                        UndoUtility.RecordObject(polygon, "Add Polygon Shape Point");

                        Vector3 hit = ray.GetPoint(hitDistance);

                        if (polygon.m_Points.Count < 1)
                        {
                            polygon.transform.position = polygon.isOnGrid ? ProGridsInterface.ProGridsSnap(hit) : hit;
                            polygon.transform.rotation = Quaternion.LookRotation(m_Plane.normal) * Quaternion.Euler(new Vector3(90f, 0f, 0f));
                        }

                        Vector3 point = ProGridsInterface.ProGridsSnap(polygon.transform.InverseTransformPoint(hit), Vector3.one);

                        if (polygon.m_Points.Count > 2 && Math.Approx3(polygon.m_Points[0], point))
                        {
                            m_NextMouseUpAdvancesMode = true;
                            return;
                        }

                        polygon.m_Points.Add(point);

                        m_PlacingPoint  = true;
                        m_SelectedIndex = polygon.m_Points.Count - 1;
                        RebuildPolyShapeMesh(polygon);

                        evt.Use();
                    }
                }
            }
            else if (polygon.polyEditMode == PolyShape.PolyEditMode.Edit)
            {
                if (polygon.m_Points.Count < 3)
                {
                    SetPolyEditMode(PolyShape.PolyEditMode.Path);
                    return;
                }

                if (m_DistanceFromHeightHandle > PreferenceKeys.k_MaxPointDistanceFromControl)
                {
                    // point insertion
                    int   index;
                    float distanceToLine;

                    Vector3 p  = EditorHandleUtility.ClosestPointToPolyLine(polygon.m_Points, out index, out distanceToLine, true, polygon.transform);
                    Vector3 wp = polygon.transform.TransformPoint(p);

                    Vector2 ga = HandleUtility.WorldToGUIPoint(polygon.transform.TransformPoint(polygon.m_Points[index % polygon.m_Points.Count]));
                    Vector2 gb = HandleUtility.WorldToGUIPoint(polygon.transform.TransformPoint(polygon.m_Points[(index - 1)]));

                    Vector2 mouse = evt.mousePosition;

                    float distanceToVertex = Mathf.Min(Vector2.Distance(mouse, ga), Vector2.Distance(mouse, gb));

                    if (distanceToVertex > PreferenceKeys.k_MaxPointDistanceFromControl && distanceToLine < PreferenceKeys.k_MaxPointDistanceFromControl)
                    {
                        Handles.color = Color.green;

                        Handles.DotHandleCap(-1, wp, Quaternion.identity, HandleUtility.GetHandleSize(wp) * k_HandleSize, evt.type);

                        if (evt.type == EventType.MouseDown)
                        {
                            evt.Use();

                            UndoUtility.RecordObject(polygon, "Insert Point");
                            polygon.m_Points.Insert(index, p);
                            m_SelectedIndex = index;
                            m_PlacingPoint  = true;
                            RebuildPolyShapeMesh(true);
                            OnBeginVertexMovement();
                        }

                        Handles.color = Color.white;
                    }
                }
            }
        }
        void OnSceneGUI(SceneView sceneView)
        {
#if !UNITY_2018_2_OR_NEWER
            if (s_ResetOnSceneGUIState != null)
            {
                s_ResetOnSceneGUIState.Invoke(sceneView, null);
            }
#endif

            SceneStyles.Init();

            m_CurrentEvent = Event.current;

            EditorMeshHandles.DrawSceneHandles(SceneDragAndDropListener.isDragging ? SelectMode.None : selectMode);

            DrawHandleGUI(sceneView);

#if SHORTCUT_MANAGER
            // Escape isn't assignable as a shortcut
            if (m_CurrentEvent.type == EventType.KeyDown)
            {
                if (m_CurrentEvent.keyCode == KeyCode.Escape && selectMode != SelectMode.Object)
                {
                    selectMode = SelectMode.Object;
                    m_CurrentEvent.Use();
                }
            }
#else
            if (m_CurrentEvent.type == EventType.MouseDown && m_CurrentEvent.button == 1)
            {
                m_IsRightMouseDown = true;
            }

            if (m_CurrentEvent.type == EventType.MouseUp && m_CurrentEvent.button == 1 || m_CurrentEvent.type == EventType.Ignore)
            {
                m_IsRightMouseDown = false;
            }

            if (!m_IsRightMouseDown && (m_CurrentEvent.type == EventType.KeyUp ? m_CurrentEvent.keyCode : KeyCode.None) != KeyCode.None)
            {
                if (ShortcutCheck(m_CurrentEvent))
                {
                    m_CurrentEvent.Use();
                    return;
                }
            }

            if (m_CurrentEvent.type == EventType.KeyDown)
            {
                if (s_Shortcuts.value.Any(x => x.Matches(m_CurrentEvent.keyCode, m_CurrentEvent.modifiers)))
                {
                    m_CurrentEvent.Use();
                }
            }
#endif

            if (selectMode == SelectMode.Object)
            {
                return;
            }

            // Check mouse position in scene and determine if we should highlight something
            if (s_ShowHoverHighlight &&
                m_CurrentEvent.type == EventType.MouseMove &&
                selectMode.IsMeshElementMode())
            {
                m_Hovering.CopyTo(m_HoveringPrevious);

                if (GUIUtility.hotControl != 0 ||
                    EditorSceneViewPicker.MouseRayHitTest(m_CurrentEvent.mousePosition, selectMode, m_ScenePickerPreferences, m_Hovering) > ScenePickerPreferences.maxPointerDistance)
                {
                    m_Hovering.Clear();
                }

                if (!m_Hovering.Equals(m_HoveringPrevious))
                {
                    SceneView.RepaintAll();
                }
            }

            if (Tools.current == Tool.View)
            {
                return;
            }

            // Overrides the toolbar transform tools
            if (Tools.current != Tool.None && Tools.current != m_CurrentTool)
            {
                SetTool_Internal(Tools.current);
            }

            Tools.current = Tool.None;

            if (selectMode.IsMeshElementMode() && MeshSelection.selectedVertexCount > 0)
            {
                var tool = GetToolForSelectMode(m_CurrentTool, s_SelectMode);

                if (tool != null)
                {
                    tool.OnSceneGUI(m_CurrentEvent);
                }
            }

            if (EditorHandleUtility.SceneViewInUse(m_CurrentEvent) || m_CurrentEvent.isKey)
            {
                m_IsDragging = false;

                if (GUIUtility.hotControl == m_DefaultControl)
                {
                    GUIUtility.hotControl = 0;
                }

                return;
            }

            // This prevents us from selecting other objects in the scene,
            // and allows for the selection of faces / vertices.
            m_DefaultControl = GUIUtility.GetControlID(FocusType.Passive);
            HandleUtility.AddDefaultControl(m_DefaultControl);

            if (m_CurrentEvent.type == EventType.MouseDown && HandleUtility.nearestControl == m_DefaultControl)
            {
                // double clicking object
                if (m_CurrentEvent.clickCount > 1)
                {
                    DoubleClick(m_CurrentEvent);
                }

                m_InitialMousePosition = m_CurrentEvent.mousePosition;
                // readyForMouseDrag prevents a bug wherein after ending a drag an errant
                // MouseDrag event is sent with no corresponding MouseDown/MouseUp event.
                m_IsReadyForMouseDrag = true;

                GUIUtility.hotControl = m_DefaultControl;
            }

            if (m_CurrentEvent.type == EventType.MouseDrag && m_IsReadyForMouseDrag && GUIUtility.hotControl == m_DefaultControl)
            {
                if (!m_IsDragging && Vector2.Distance(m_CurrentEvent.mousePosition, m_InitialMousePosition) > k_MouseDragThreshold)
                {
                    sceneView.Repaint();
                    m_IsDragging = true;
                }
            }

            if (m_CurrentEvent.type == EventType.Ignore)
            {
                if (m_IsDragging)
                {
                    m_IsReadyForMouseDrag = false;
                    m_IsDragging          = false;
                    EditorSceneViewPicker.DoMouseDrag(m_MouseDragRect, selectMode, m_ScenePickerPreferences);
                }

                if (m_WasDoubleClick)
                {
                    m_WasDoubleClick = false;
                }

                if (GUIUtility.hotControl == m_DefaultControl)
                {
                    GUIUtility.hotControl = 0;
                }
            }

            if (m_CurrentEvent.type == EventType.MouseUp && GUIUtility.hotControl == m_DefaultControl)
            {
                GUIUtility.hotControl = 0;

                if (m_WasDoubleClick)
                {
                    m_WasDoubleClick = false;
                }
                else
                {
                    if (!m_IsDragging)
                    {
                        if (UVEditor.instance)
                        {
                            UVEditor.instance.ResetUserPivot();
                        }

                        EditorSceneViewPicker.DoMouseClick(m_CurrentEvent, selectMode, m_ScenePickerPreferences);
                        UpdateSelection();
                        SceneView.RepaintAll();
                    }
                    else
                    {
                        m_IsDragging          = false;
                        m_IsReadyForMouseDrag = false;

                        if (UVEditor.instance)
                        {
                            UVEditor.instance.ResetUserPivot();
                        }

                        EditorSceneViewPicker.DoMouseDrag(m_MouseDragRect, selectMode, m_ScenePickerPreferences);

                        if (GUIUtility.hotControl == m_DefaultControl)
                        {
                            GUIUtility.hotControl = 0;
                        }
                    }
                }
            }
        }
Beispiel #23
0
        void DoExistingPointsGUI()
        {
            Transform trs = polygon.transform;
            int       len = polygon.m_Points.Count;

            Vector3 up      = polygon.transform.up;
            Vector3 right   = polygon.transform.right;
            Vector3 forward = polygon.transform.forward;
            Vector3 center  = Vector3.zero;

            Event evt = Event.current;

            bool used = evt.type == EventType.Used;

            if (!used &&
                (evt.type == EventType.MouseDown &&
                 evt.button == 0 &&
                 !EditorHandleUtility.IsAppendModifier(evt.modifiers)))
            {
                m_SelectedIndex = -1;
                Repaint();
            }

            if (polygon.polyEditMode == PolyShape.PolyEditMode.Height)
            {
                if (!used && evt.type == EventType.MouseUp && evt.button == 0 && !EditorHandleUtility.IsAppendModifier(evt.modifiers))
                {
                    evt.Use();
                    SetPolyEditMode(PolyShape.PolyEditMode.Edit);
                }

                bool sceneInUse = EditorHandleUtility.SceneViewInUse(evt);
                Ray  r          = HandleUtility.GUIPointToWorldRay(evt.mousePosition);

                Vector3 origin  = polygon.transform.TransformPoint(Math.Average(polygon.m_Points));
                float   extrude = polygon.extrude;

                if (evt.type == EventType.MouseMove && !sceneInUse)
                {
                    Vector3 p = Math.GetNearestPointRayRay(origin, up, r.origin, r.direction);
                    extrude = ProGridsInterface.ProGridsSnap(s_HeightMouseOffset + Vector3.Distance(origin, p) * Mathf.Sign(Vector3.Dot(p - origin, up)));
                }

                Vector3 extrudePoint = origin + (extrude * up);

                Handles.color = k_HandleColor;
                Handles.DotHandleCap(-1, origin, Quaternion.identity, HandleUtility.GetHandleSize(origin) * k_HandleSize, evt.type);
                Handles.color = k_HandleColorGreen;
                Handles.DrawLine(origin, extrudePoint);
                Handles.DotHandleCap(-1, extrudePoint, Quaternion.identity, HandleUtility.GetHandleSize(extrudePoint) * k_HandleSize, evt.type);
                Handles.color = Color.white;

                if (!sceneInUse && polygon.extrude != extrude)
                {
                    OnBeginVertexMovement();
                    polygon.extrude = extrude;
                    RebuildPolyShapeMesh(false);
                }
            }
            else
            {
                // vertex dots
                for (int ii = 0; ii < len; ii++)
                {
                    Vector3 point = trs.TransformPoint(polygon.m_Points[ii]);

                    center.x += point.x;
                    center.y += point.y;
                    center.z += point.z;

                    float size = HandleUtility.GetHandleSize(point) * k_HandleSize;

                    Handles.color = ii == m_SelectedIndex ? k_HandleSelectedColor : k_HandleColor;

                    EditorGUI.BeginChangeCheck();

                    point = Handles.Slider2D(point, up, right, forward, size, Handles.DotHandleCap, Vector2.zero, true);

                    if (EditorGUI.EndChangeCheck())
                    {
                        UndoUtility.RecordObject(polygon, "Move Polygon Shape Point");

                        Vector3 snapMask = Snapping.GetSnappingMaskBasedOnNormalVector(m_Plane.normal);
                        polygon.m_Points[ii] = ProGridsInterface.ProGridsSnap(trs.InverseTransformPoint(point), snapMask);
                        OnBeginVertexMovement();
                        RebuildPolyShapeMesh(false);
                    }

                    // "clicked" a button
                    if (!used && evt.type == EventType.Used)
                    {
                        if (ii == 0 && polygon.m_Points.Count > 2 && polygon.polyEditMode == PolyShape.PolyEditMode.Path)
                        {
                            m_NextMouseUpAdvancesMode = true;
                            return;
                        }
                        else
                        {
                            used            = true;
                            m_SelectedIndex = ii;
                        }
                    }
                }

                Handles.color = Color.white;

                // height setting
                if (polygon.polyEditMode != PolyShape.PolyEditMode.Path && polygon.m_Points.Count > 2)
                {
                    center.x /= (float)len;
                    center.y /= (float)len;
                    center.z /= (float)len;

                    Vector3 extrude = center + (up * polygon.extrude);
                    m_DistanceFromHeightHandle = Vector2.Distance(HandleUtility.WorldToGUIPoint(extrude), evt.mousePosition);

                    EditorGUI.BeginChangeCheck();

                    Handles.color = k_HandleColor;
                    Handles.DotHandleCap(-1, center, Quaternion.identity, HandleUtility.GetHandleSize(center) * k_HandleSize, evt.type);
                    Handles.DrawLine(center, extrude);
                    Handles.color = k_HandleColorGreen;
                    extrude       = Handles.Slider(extrude, up, HandleUtility.GetHandleSize(extrude) * k_HandleSize, Handles.DotHandleCap, 0f);
                    Handles.color = Color.white;

                    if (EditorGUI.EndChangeCheck())
                    {
                        UndoUtility.RecordObject(polygon, "Set Polygon Shape Height");
                        polygon.extrude = ProGridsInterface.ProGridsSnap(Vector3.Distance(extrude, center) * Mathf.Sign(Vector3.Dot(up, extrude - center)));
                        OnBeginVertexMovement();
                        RebuildPolyShapeMesh(false);
                    }
                }
            }
        }
        public static void DoMouseDrag(Rect mouseDragRect, SelectMode selectionMode, ScenePickerPreferences scenePickerPreferences)
        {
            var pickingOptions = new PickerOptions()
            {
                depthTest      = scenePickerPreferences.cullMode == CullingMode.Back,
                rectSelectMode = scenePickerPreferences.rectSelectMode
            };

            UndoUtility.RecordSelection("Drag Select");
            bool isAppendModifier = EditorHandleUtility.IsAppendModifier(Event.current.modifiers);

            if (!isAppendModifier)
            {
                MeshSelection.ClearElementSelection();
            }

            bool elementsInDragRect = false;

            switch (selectionMode)
            {
            case SelectMode.Vertex:
            case SelectMode.TextureVertex:
            {
                Dictionary <ProBuilderMesh, HashSet <int> > selected = SelectionPicker.PickVerticesInRect(
                    SceneView.lastActiveSceneView.camera,
                    mouseDragRect,
                    MeshSelection.topInternal,
                    pickingOptions,
                    EditorGUIUtility.pixelsPerPoint);

                foreach (var kvp in selected)
                {
                    var            mesh          = kvp.Key;
                    SharedVertex[] sharedIndexes = mesh.sharedVerticesInternal;
                    HashSet <int>  common;

                    if (isAppendModifier)
                    {
                        common = mesh.GetSharedVertexHandles(mesh.selectedIndexesInternal);

                        if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Add)
                        {
                            common.UnionWith(kvp.Value);
                        }
                        else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Subtract)
                        {
                            common.RemoveWhere(x => kvp.Value.Contains(x));
                        }
                        else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Difference)
                        {
                            common.SymmetricExceptWith(kvp.Value);
                        }
                    }
                    else
                    {
                        common = kvp.Value;
                    }

                    elementsInDragRect |= kvp.Value.Any();
                    mesh.SetSelectedVertices(common.SelectMany(x => sharedIndexes[x]));
                }

                break;
            }

            case SelectMode.Face:
            case SelectMode.TextureFace:
            {
                Dictionary <ProBuilderMesh, HashSet <Face> > selected = SelectionPicker.PickFacesInRect(
                    SceneView.lastActiveSceneView.camera,
                    mouseDragRect,
                    MeshSelection.topInternal,
                    pickingOptions,
                    EditorGUIUtility.pixelsPerPoint);

                foreach (var kvp in selected)
                {
                    HashSet <Face> current;

                    if (isAppendModifier)
                    {
                        current = new HashSet <Face>(kvp.Key.selectedFacesInternal);

                        if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Add)
                        {
                            current.UnionWith(kvp.Value);
                        }
                        else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Subtract)
                        {
                            current.RemoveWhere(x => kvp.Value.Contains(x));
                        }
                        else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Difference)
                        {
                            current.SymmetricExceptWith(kvp.Value);
                        }
                    }
                    else
                    {
                        current = kvp.Value;
                    }

                    elementsInDragRect |= kvp.Value.Any();
                    kvp.Key.SetSelectedFaces(current);
                }

                break;
            }

            case SelectMode.Edge:
            case SelectMode.TextureEdge:
            {
                var selected = SelectionPicker.PickEdgesInRect(
                    SceneView.lastActiveSceneView.camera,
                    mouseDragRect,
                    MeshSelection.topInternal,
                    pickingOptions,
                    EditorGUIUtility.pixelsPerPoint);

                foreach (var kvp in selected)
                {
                    ProBuilderMesh        mesh          = kvp.Key;
                    Dictionary <int, int> common        = mesh.sharedVertexLookup;
                    HashSet <EdgeLookup>  selectedEdges = EdgeLookup.GetEdgeLookupHashSet(kvp.Value, common);
                    HashSet <EdgeLookup>  current;

                    if (isAppendModifier)
                    {
                        current = EdgeLookup.GetEdgeLookupHashSet(mesh.selectedEdges, common);

                        if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Add)
                        {
                            current.UnionWith(selectedEdges);
                        }
                        else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Subtract)
                        {
                            current.RemoveWhere(x => selectedEdges.Contains(x));
                        }
                        else if (scenePickerPreferences.selectionModifierBehavior == SelectionModifierBehavior.Difference)
                        {
                            current.SymmetricExceptWith(selectedEdges);
                        }
                    }
                    else
                    {
                        current = selectedEdges;
                    }

                    elementsInDragRect |= kvp.Value.Any();
                    mesh.SetSelectedEdges(current.Select(x => x.local));
                }

                break;
            }
            }

            // if nothing was selected in the drag rect, clear the object selection too
            if (!elementsInDragRect && !isAppendModifier)
            {
                MeshSelection.ClearElementAndObjectSelection();
            }

            ProBuilderEditor.Refresh();
            SceneView.RepaintAll();
        }