void SetIsEditing(bool isEditing)
        {
            GUIUtility.hotControl = 0;

            if (isEditing && !m_IsEditing)
            {
                if (ProBuilderEditor.instance != null)
                {
                    ProBuilderEditor.instance.ClearElementSelection();
                }

                UndoUtility.RecordObject(m_Target, "Edit Bezier Shape");
                UndoUtility.RecordObject(m_Target.mesh, "Edit Bezier Shape");

                UpdateMesh(true);
            }

            m_Target.isEditing = isEditing;

            if (m_Target.isEditing)
            {
                ProBuilderEditor.selectMode |= SelectMode.InputTool;
            }
            else
            {
                ProBuilderEditor.selectMode &= ~SelectMode.InputTool;
            }

            if (m_Target.isEditing)
            {
                Tools.current = Tool.None;
                UpdateControlPoints();
            }
        }
        void SetGroup(ProBuilderMesh pb, int index)
        {
            UndoUtility.RecordObject(pb, "Set Smoothing Group");

            foreach (Face face in pb.selectedFaceCount < 1 ? pb.facesInternal : pb.selectedFacesInternal)
            {
                face.smoothingGroup = index;
            }

            // todo pb.Rebuild
            pb.ToMesh();
            pb.Refresh();
            pb.Optimize();

            SmoothGroupData data;

            if (!m_SmoothGroups.TryGetValue(pb, out data))
            {
                m_SmoothGroups.Add(pb, new SmoothGroupData(pb));
            }
            else
            {
                data.Rebuild(pb);
            }

            ProBuilderEditor.Refresh();
        }
Example #3
0
        /// <summary>
        /// Overlay GUI
        /// </summary>
        /// <param name="target">the target of this overlay</param>
        /// <param name="view">the current SceneView where to display the overlay</param>
        void OnOverlayGUI(UObject target, SceneView view)
        {
            switch (polygon.polyEditMode)
            {
            case PolyShape.PolyEditMode.Path:
            {
                EditorGUILayout.HelpBox("Click To Add Points\nPress 'Enter' or 'Space' to Set Height", MessageType.Info);
                break;
            }

            case PolyShape.PolyEditMode.Height:
            {
                EditorGUILayout.HelpBox("Move Mouse to Set Height\nPress 'Enter' or 'Space' to Finalize", MessageType.Info);
                break;
            }

            case PolyShape.PolyEditMode.Edit:
            {
                if (GUILayout.Button("Quit Editing", UI.EditorGUIUtility.GetActiveStyle("Button")))
                {
                    SetPolyEditMode(PolyShape.PolyEditMode.None);
                }
                EditorGUILayout.HelpBox("Move Poly Shape points to update the shape\nPress 'Enter' or 'Space' to Finalize", MessageType.Info);
                break;
            }
            }

            EditorGUI.BeginChangeCheck();

            float extrude = polygon.extrude;

            extrude = EditorGUILayout.FloatField("Extrusion", extrude);

            bool flipNormals = polygon.flipNormals;

            flipNormals = EditorGUILayout.Toggle("Flip Normals", flipNormals);

            if (EditorGUI.EndChangeCheck())
            {
                if (polygon.polyEditMode == PolyShape.PolyEditMode.None)
                {
                    if (ProBuilderEditor.instance != null)
                    {
                        ProBuilderEditor.instance.ClearElementSelection();
                    }

                    UndoUtility.RecordObject(polygon, "Change Polygon Shape Settings");
                    UndoUtility.RecordObject(polygon.mesh, "Change Polygon Shape Settings");
                }
                else
                {
                    UndoUtility.RecordObject(polygon, "Change Polygon Shape Settings");
                }

                polygon.extrude     = extrude;
                polygon.flipNormals = flipNormals;

                RebuildPolyShapeMesh(polygon);
            }
        }
Example #4
0
        void HandleKeyEvent(Event evt)
        {
            KeyCode key = evt.keyCode;

            switch (key)
            {
            case KeyCode.Space:
            case KeyCode.Return:
            {
                if (polygon.polyEditMode == PolyShape.PolyEditMode.Path)
                {
                    if (SceneCameraIsAlignedWithPolyUp())
                    {
                        SetPolyEditMode(PolyShape.PolyEditMode.Edit);
                    }
                    else
                    {
                        SetPolyEditMode(PolyShape.PolyEditMode.Height);
                    }

                    evt.Use();
                }
                else if (polygon.polyEditMode == PolyShape.PolyEditMode.Height ||
                         polygon.polyEditMode == PolyShape.PolyEditMode.Edit)
                {
                    LeaveTool();
                    evt.Use();
                }

                break;
            }

            case KeyCode.Backspace:
            {
                if (m_SelectedIndex > -1)
                {
                    UndoUtility.RecordObject(polygon, "Delete Selected Points");
                    polygon.m_Points.RemoveAt(m_SelectedIndex);
                    m_SelectedIndex = -1;
                    RebuildPolyShapeMesh(polygon);
                    evt.Use();
                }
                break;
            }

            case KeyCode.Escape:
            {
                if (polygon.polyEditMode == PolyShape.PolyEditMode.Path)
                {
                    DestroyImmediate(polygon.gameObject);
                }

                LeaveTool();

                evt.Use();
                break;
            }
            }
        }
Example #5
0
        void SetPolyEditMode(PolyShape.PolyEditMode mode)
        {
            PolyShape.PolyEditMode old = polygon.polyEditMode;

            if (mode != old)
            {
                // Clear the control always
                GUIUtility.hotControl = 0;

                // Entering edit mode after the shape has been finalized once before, which means
                // possibly reverting manual changes.  Store undo state so that if this was
                // not intentional user can revert.
                if (polygon.polyEditMode == PolyShape.PolyEditMode.None && polygon.m_Points.Count > 2)
                {
                    if (ProBuilderEditor.instance != null)
                    {
                        ProBuilderEditor.instance.ClearElementSelection();
                    }

                    UndoUtility.RecordObject(polygon, "Edit Polygon Shape");
                    UndoUtility.RecordObject(polygon.mesh, "Edit Polygon Shape");
                }

                polygon.polyEditMode = mode;

                if (polygon.polyEditMode == PolyShape.PolyEditMode.None)
                {
                    ProBuilderEditor.selectMode = ProBuilderEditor.selectMode & ~(SelectMode.InputTool);
                }
                else
                {
                    ProBuilderEditor.selectMode = ProBuilderEditor.selectMode | SelectMode.InputTool;
                }

                if (polygon.polyEditMode != PolyShape.PolyEditMode.None)
                {
                    Tools.current = Tool.None;
                }

                // If coming from Path -> Height set the mouse / origin offset
                if (old == PolyShape.PolyEditMode.Path && mode == PolyShape.PolyEditMode.Height && Event.current != null)
                {
                    Vector3 up     = polygon.transform.up;
                    Vector3 origin = polygon.transform.TransformPoint(Math.Average(polygon.m_Points));
                    Ray     r      = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
                    Vector3 p      = Math.GetNearestPointRayRay(origin, up, r.origin, r.direction);
                    s_HeightMouseOffset = polygon.extrude -
                                          ProGridsInterface.ProGridsSnap(
                        Vector3.Distance(origin, p) * Mathf.Sign(Vector3.Dot(p - origin, up)));
                }

                RebuildPolyShapeMesh(polygon);
            }
        }
        /// <summary>
        /// Applies the currently queued material to the selected face and eats the event.
        /// </summary>
        /// <param name="em"></param>
        /// <param name="pb"></param>
        /// <param name="quad"></param>
        /// <returns></returns>
        public bool ClickShortcutCheck(EventModifiers em, ProBuilderMesh pb, Face quad)
        {
            if (UVEditor.instance == null)
            {
                if (em == (EventModifiers.Control | EventModifiers.Shift))
                {
                    UndoUtility.RecordObject(pb, "Quick Apply");
                    quad.material = m_QueuedMaterial;
                    pb.ToMesh();
                    pb.Refresh();
                    pb.Optimize();
                    EditorUtility.ShowNotification("Quick Apply Material");
                    return(true);
                }
            }

            return(false);
        }
Example #7
0
        public override void OnInspectorGUI()
        {
            switch (polygon.polyEditMode)
            {
            case PolyShape.PolyEditMode.None:
            {
                if (GUILayout.Button("Edit Poly Shape"))
                {
                    SetPolyEditMode(PolyShape.PolyEditMode.Edit);
                }

                EditorGUILayout.HelpBox(
                    "Editing a poly shape will erase any modifications made to the mesh!\n\nIf you accidentally enter Edit Mode you can Undo to get your changes back.",
                    MessageType.Warning);

                break;
            }

            case PolyShape.PolyEditMode.Path:
            {
                EditorGUILayout.HelpBox("\nClick To Add Points\n\nPress 'Enter' or 'Space' to Set Height\n", MessageType.Info);
                break;
            }

            case PolyShape.PolyEditMode.Height:
            {
                EditorGUILayout.HelpBox("\nMove Mouse to Set Height\n\nPress 'Enter' or 'Space' to Finalize\n", MessageType.Info);
                break;
            }

            case PolyShape.PolyEditMode.Edit:
            {
                if (GUILayout.Button("Editing Poly Shape", UI.EditorGUIUtility.GetActiveStyle("Button")))
                {
                    SetPolyEditMode(PolyShape.PolyEditMode.None);
                }
                break;
            }
            }

            EditorGUI.BeginChangeCheck();

            float extrude = polygon.extrude;

            extrude = EditorGUILayout.FloatField("Extrusion", extrude);

            bool flipNormals = polygon.flipNormals;

            flipNormals = EditorGUILayout.Toggle("Flip Normals", flipNormals);

            if (EditorGUI.EndChangeCheck())
            {
                if (polygon.polyEditMode == PolyShape.PolyEditMode.None)
                {
                    if (ProBuilderEditor.instance != null)
                    {
                        ProBuilderEditor.instance.ClearElementSelection();
                    }

                    UndoUtility.RecordObject(polygon, "Change Polygon Shape Settings");
                    UndoUtility.RecordObject(polygon.mesh, "Change Polygon Shape Settings");
                }
                else
                {
                    UndoUtility.RecordObject(polygon, "Change Polygon Shape Settings");
                }

                polygon.extrude     = extrude;
                polygon.flipNormals = flipNormals;

                RebuildPolyShapeMesh(polygon);
            }

            // GUILayout.Label("selected : " + m_SelectedIndex);
        }
Example #8
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);
                    }
                }
            }
        }
Example #9
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;
                    }
                }
            }
        }
        static void OnSceneGUI(SceneView sceneView)
        {
            var evt = Event.current;

            if (evt.type == EventType.DragUpdated)
            {
                if (!s_IsSceneViewDragAndDrop)
                {
                    s_IsSceneViewDragAndDrop = true;
                }

                int        submeshIndex;
                GameObject go = HandleUtility.PickGameObject(evt.mousePosition, out submeshIndex);

                SetMeshPreview(go != null ? go.GetComponent <ProBuilderMesh>() : null);

                if (s_IsFaceDragAndDropOverrideEnabled)
                {
                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                    evt.Use();
                }
            }
            else if (evt.type == EventType.DragExited)
            {
                if (s_IsFaceDragAndDropOverrideEnabled)
                {
                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                    evt.Use();
                    SetMeshPreview(null);
                }

                s_IsSceneViewDragAndDrop = false;
            }
            else if (evt.type == EventType.DragPerform)
            {
                s_IsSceneViewDragAndDrop = false;
                int        submeshIndex;
                GameObject go = HandleUtility.PickGameObject(evt.mousePosition, out submeshIndex);
                SetMeshPreview(go != null ? go.GetComponent <ProBuilderMesh>() : null);

                if (s_CurrentPreview != null && s_IsFaceDragAndDropOverrideEnabled)
                {
                    UndoUtility.RecordObject(s_CurrentPreview, "Set Face Material");
                    UndoUtility.RecordObject(s_CurrentPreview.renderer, "Set Face Material");

                    s_CurrentPreview.SetMaterial(s_CurrentPreview.selectedFacesInternal, s_PreviewMaterial);

                    InternalMeshUtility.FilterUnusedSubmeshIndexes(s_CurrentPreview);

                    s_CurrentPreview.ToMesh();
                    s_CurrentPreview.Refresh();
                    s_CurrentPreview.Optimize();

                    evt.Use();
                }

                SetMeshPreview(null);
            }
            else if (evt.type == EventType.Repaint && s_IsFaceDragAndDropOverrideEnabled)
            {
                if (s_PreviewMaterial.SetPass(0))
                {
                    Graphics.DrawMeshNow(s_PreviewMesh, s_Matrix, 0);
                }
            }
        }
Example #11
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();
                        }
                    }
                }
            }
        }
 void OnBeginVertexModification()
 {
     m_IsMoving = true;
     UndoUtility.RecordObject(m_Target, "Modify Bezier Spline");
     Lightmapping.PushGIWorkflowMode();
 }
        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 void OnInspectorGUI()
        {
            if (!m_IsEditing)
            {
                if (GUILayout.Button("Edit Bezier Shape"))
                {
                    SetIsEditing(true);
                }

                EditorGUILayout.HelpBox("Editing a Bezier Shape will erase any modifications made to the mesh!\n\nIf you accidentally enter Edit Mode you can Undo to get your changes back.", MessageType.Warning);

                return;
            }

            if (GUILayout.Button("Editing Bezier Shape", UI.EditorGUIUtility.GetActiveStyle("Button")))
            {
                SetIsEditing(false);
            }

            Event e = Event.current;

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

            EditorGUI.BeginChangeCheck();

            bool handleIsValid = (m_currentHandle > -1 && m_currentHandle < m_Points.Count);

            BezierPoint inspectorPoint = handleIsValid ?
                                         m_Points[m_currentHandle] :
                                         new BezierPoint(Vector3_Zero, Vector3_Backward, Vector3_Forward, Quaternion.identity);

            inspectorPoint = DoBezierPointGUI(inspectorPoint);

            if (handleIsValid && EditorGUI.EndChangeCheck())
            {
                if (!m_IsMoving)
                {
                    OnBeginVertexModification();
                }

                m_Points[m_currentHandle] = inspectorPoint;
                UpdateMesh(false);
            }

            EditorGUI.BeginChangeCheck();

            if (GUILayout.Button("Clear Points"))
            {
                UndoUtility.RecordObject(m_Target, "Clear Bezier Spline Points");
                m_Points.Clear();
                UpdateMesh(true);
            }

            if (GUILayout.Button("Add Point"))
            {
                UndoUtility.RecordObject(m_Target, "Add Bezier Spline Point");

                if (m_Points.Count > 0)
                {
                    m_Points.Add(new BezierPoint(m_Points[m_Points.Count - 1].position,
                                                 m_Points[m_Points.Count - 1].tangentIn,
                                                 m_Points[m_Points.Count - 1].tangentOut,
                                                 Quaternion.identity));
                    UpdateMesh(true);
                }
                else
                {
                    m_Target.Init();
                }

                m_currentHandle = (BezierHandle)(m_Points.Count - 1);

                SceneView.RepaintAll();
            }

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            m_TangentMode = (BezierTangentMode)GUILayout.Toolbar((int)m_TangentMode, s_TangentModeIcons, commandStyle);
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            m_CloseLoop = EditorGUILayout.Toggle("Close Loop", m_CloseLoop);
            m_Smooth    = EditorGUILayout.Toggle("Smooth", m_Smooth);
            m_Radius    = Mathf.Max(.001f, EditorGUILayout.FloatField("Radius", m_Radius));
            m_Rows      = Math.Clamp(EditorGUILayout.IntField("Rows", m_Rows), 3, 512);
            m_Columns   = Math.Clamp(EditorGUILayout.IntField("Columns", m_Columns), 3, 512);

            if (EditorGUI.EndChangeCheck())
            {
                UpdateMesh(true);
            }
        }
        void OnGUI()
        {
            GUILayout.BeginHorizontal(EditorStyles.toolbar);

            GUILayout.FlexibleSpace();

            GUIStyle style = m_WorldSpace ? EditorStyles.toolbarButton : UI.EditorGUIUtility.GetOnStyle(EditorStyles.toolbarButton);

            if (GUILayout.Button(m_WorldSpace ? "World Space" : "Model Space", style))
            {
                m_WorldSpace = !m_WorldSpace;
            }

            GUILayout.EndHorizontal();

            if (m_Selection == null || m_Selection.Count < 1 || !m_Selection.Any(x => x.Key.selectedVertexCount > 0))
            {
                GUILayout.FlexibleSpace();
                GUILayout.Label("Select a ProBuilder Mesh", UI.EditorGUIUtility.CenteredGreyMiniLabel);
                GUILayout.FlexibleSpace();
                return;
            }

            Event e = Event.current;

            if (m_IsActive)
            {
                if (e.type == EventType.Ignore ||
                    e.type == EventType.MouseUp)
                {
                    OnVertexMovementFinish();
                }
            }

            m_Scroll = EditorGUILayout.BeginScrollView(m_Scroll);

            foreach (var kvp in m_Selection)
            {
                ProBuilderMesh        mesh = kvp.Key;
                VertexEditorSelection sel  = kvp.Value;

                bool open = sel.isVisible;

                EditorGUI.BeginChangeCheck();
                open = EditorGUILayout.Foldout(open, mesh.name);
                if (EditorGUI.EndChangeCheck())
                {
                    sel.isVisible = open;
                }

                if (open)
                {
                    int index = 0;

                    bool wasWideMode = EditorGUIUtility.wideMode;
                    EditorGUIUtility.wideMode = true;
                    Color     background = GUI.backgroundColor;
                    Transform transform  = mesh.transform;

                    foreach (int u in sel.common)
                    {
                        GUI.backgroundColor = index % 2 == 0 ? s_EvenColor : s_OddColor;
                        GUILayout.BeginHorizontal(UI.EditorGUIUtility.solidBackgroundStyle);
                        GUI.backgroundColor = background;

                        GUILayout.Label(u.ToString(), GUILayout.MinWidth(32), GUILayout.MaxWidth(32));

                        Vector3 v = mesh.positionsInternal[mesh.sharedVerticesInternal[u][0]];

                        if (m_WorldSpace)
                        {
                            v = transform.TransformPoint(v);
                        }

                        EditorGUI.BeginChangeCheck();

                        v = EditorGUILayout.Vector3Field("", v);

                        if (EditorGUI.EndChangeCheck())
                        {
                            if (!m_IsActive)
                            {
                                OnVertexMovementBegin(mesh);
                            }

                            UndoUtility.RecordObject(mesh, "Set Vertex Postion");

                            mesh.SetSharedVertexPosition(u, m_WorldSpace ? transform.InverseTransformPoint(v) : v);

                            if (ProBuilderEditor.instance != null)
                            {
                                mesh.RefreshUV(MeshSelection.selectedFacesInEditZone[mesh]);
                                mesh.Refresh(RefreshMask.Normals);
                                mesh.mesh.RecalculateBounds();
                                ProBuilderEditor.Refresh();
                            }
                        }
                        index++;
                        GUILayout.EndHorizontal();
                    }

                    GUI.backgroundColor       = background;
                    EditorGUIUtility.wideMode = wasWideMode;
                }
            }

            EditorGUILayout.EndScrollView();
        }
Example #16
0
        public override void OnInspectorGUI()
        {
            switch (polygon.polyEditMode)
            {
            case PolyShape.PolyEditMode.None:
            {
                if (GUILayout.Button("Edit Poly Shape"))
                {
                    ProBuilderEditor.selectMode = SelectMode.Object;
                    polygon.polyEditMode        = PolyShape.PolyEditMode.Edit;
                    PolyShapeTool tool = CreateInstance <PolyShapeTool>();
                    tool.polygon = polygon;
                    ToolManager.SetActiveTool(tool);
                    Undo.RegisterCreatedObjectUndo(tool, "Open Polyshape Tool");
                }

                EditorGUILayout.HelpBox(
                    "Editing a poly shape will erase any modifications made to the mesh!\n\nIf you accidentally enter Edit Mode you can Undo to get your changes back.",
                    MessageType.Warning);

                break;
            }

            case PolyShape.PolyEditMode.Path:
            {
                EditorGUILayout.HelpBox("\nClick To Add Points\n\nPress 'Enter' or 'Space' to Set Height\n", MessageType.Info);
                break;
            }

            case PolyShape.PolyEditMode.Height:
            {
                EditorGUILayout.HelpBox("\nMove Mouse to Set Height\n\nPress 'Enter' or 'Space' to Finalize\n", MessageType.Info);
                break;
            }

            case PolyShape.PolyEditMode.Edit:
            {
                EditorGUILayout.HelpBox("\nMove Poly Shape points to update the shape\n\nPress 'Enter' or 'Space' to Finalize\n", MessageType.Info);
                break;
            }
            }

            EditorGUI.BeginChangeCheck();

            float extrude = polygon.extrude;

            extrude = EditorGUILayout.FloatField("Extrusion", extrude);

            bool flipNormals = polygon.flipNormals;

            flipNormals = EditorGUILayout.Toggle("Flip Normals", flipNormals);

            if (EditorGUI.EndChangeCheck())
            {
                if (polygon.polyEditMode == PolyShape.PolyEditMode.None)
                {
                    if (ProBuilderEditor.instance != null)
                    {
                        ProBuilderEditor.instance.ClearElementSelection();
                    }

                    UndoUtility.RecordComponents <ProBuilderMesh, PolyShape>(polygon.GetComponents(typeof(Component)), "Edit Polygon Shape");
                }
                else
                {
                    UndoUtility.RecordObject(polygon, "Change Polygon Shape Settings");
                }

                polygon.extrude     = extrude;
                polygon.flipNormals = flipNormals;

                RebuildPolyShapeMesh(polygon);
            }
        }