示例#1
0
        /// <summary>
        /// The Editing handles are used to manipulate and resize ProBuilderShapes
        /// These handles are used in 2 tools : EditShapeTool and DrawShapeTool. In this second tool,
        /// these handles allow to modified the last created shape.
        /// </summary>
        /// <param name="proBuilderShape">The Shape on which to attach the handles</param>
        /// <param name="updatePrefs">Parameter used to update the DrawShapeTool when needed</param>
        internal static void DoEditingHandles(ProBuilderShape proBuilderShape, bool updatePrefs = false)
        {
            if (proBuilderShape == null)
            {
                return;
            }

            var scale    = proBuilderShape.transform.lossyScale;
            var position = proBuilderShape.transform.position
                           + Vector3.Scale(proBuilderShape.transform.TransformDirection(proBuilderShape.shapeBox.center), scale);
            var matrix = Matrix4x4.TRS(position, proBuilderShape.transform.rotation, Vector3.one);

            using (new Handles.DrawingScope(matrix))
            {
                EditorShapeUtility.UpdateFaces(proBuilderShape.editionBounds, scale, faces);

                for (int i = 0; i < 4; ++i)
                {
                    k_OrientationControlIDs[i] = GUIUtility.GetControlID(FocusType.Passive);
                }
                for (int i = 0; i < faces.Length; ++i)
                {
                    s_FaceControlIDs[i] = GUIUtility.GetControlID(FocusType.Passive);
                }

                var absSize = Math.Abs(proBuilderShape.editionBounds.size);
                if (absSize.x > Mathf.Epsilon && absSize.y > Mathf.Epsilon && absSize.z > Mathf.Epsilon)
                {
                    DoOrientationHandles(proBuilderShape, updatePrefs);
                }

                DoSizeHandles(proBuilderShape, updatePrefs);
            }
        }
示例#2
0
 internal static void ApplyPrefsSettings(ProBuilderShape proBuilderShape)
 {
     proBuilderShape.pivotLocation      = (PivotLocation)s_LastPivotLocation.value;
     proBuilderShape.pivotLocalPosition = s_LastPivotPosition.value;
     proBuilderShape.size     = s_LastSize.value;
     proBuilderShape.rotation = s_LastRotation.value;
 }
示例#3
0
        static void DoOrientationHandles(ProBuilderShape proBuilderShape, bool updatePrefs)
        {
            if (GUIUtility.hotControl != 0 && !k_OrientationControlIDs.Contains(GUIUtility.hotControl))
            {
                return;
            }

            foreach (var f in faces)
            {
                if (f.IsVisible && EditorShapeUtility.PointerIsInFace(f))
                {
                    if (DoOrientationHandle(f, proBuilderShape))
                    {
                        UndoUtility.RecordComponents <Transform, ProBuilderMesh, ProBuilderShape>(proBuilderShape.GetComponents(typeof(Component)), "Rotate Shape");
                        proBuilderShape.RotateInsideBounds(s_ShapeRotation);

                        ProBuilderEditor.Refresh();

                        if (updatePrefs)
                        {
                            DrawShapeTool.SaveShapeParams(proBuilderShape);
                        }
                    }
                }
            }
        }
示例#4
0
        internal static void SaveShapeParams(ProBuilderShape proBuilderShape)
        {
            s_LastPivotLocation.value = (int)proBuilderShape.pivotLocation;
            s_LastPivotPosition.value = proBuilderShape.pivotLocalPosition;
            s_LastSize.value          = proBuilderShape.size;
            s_LastRotation.value      = proBuilderShape.rotation;

            EditorShapeUtility.SaveParams(proBuilderShape.shape);
        }
示例#5
0
        static void ApplyProperties(ProBuilderShape proBuilderShape, Vector3 newCenterPosition, Vector3 newSize)
        {
            var bounds = new Bounds();

            bounds.center = newCenterPosition;
            bounds.size   = newSize;

            UndoUtility.RecordComponents <Transform, ProBuilderMesh, ProBuilderShape>(proBuilderShape.GetComponents(typeof(Component)), "Resize Shape");
            proBuilderShape.UpdateBounds(bounds);

            ProBuilderEditor.Refresh(false);
        }
示例#6
0
        void DrawShapeGUI()
        {
            if (m_BoldCenteredStyle == null)
            {
                m_BoldCenteredStyle = new GUIStyle("BoldLabel")
                {
                    alignment = TextAnchor.MiddleCenter
                }
            }
            ;

            EditorGUILayout.LabelField(EditorShapeUtility.shapeTypes[s_ActiveShapeIndex.value], m_BoldCenteredStyle, GUILayout.ExpandWidth(true));

            if (EditorShapeUtility.s_ResetUserPrefs.value)
            {
                ResetPrefs();
            }

            var shape = currentShapeInOverlay.shape;

            int groupCount = EditorShapeUtility.shapeTypesGUI.Count;

            for (int i = 0; i < groupCount; i++)
            {
                EditorGUI.BeginChangeCheck();
                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                int index = GUILayout.Toolbar(s_ActiveShapeIndex.value - +i * EditorShapeUtility.MaxContentPerGroup, EditorShapeUtility.shapeTypesGUI[i], Styles.command);
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();
                if (EditorGUI.EndChangeCheck())
                {
                    s_ActiveShapeIndex.value = index + i * EditorShapeUtility.MaxContentPerGroup;

                    var type = EditorShapeUtility.availableShapeTypes[s_ActiveShapeIndex];
                    if (shape.GetType() != type)
                    {
                        if (currentShapeInOverlay == m_LastShapeCreated)
                        {
                            m_LastShapeCreated = null;
                        }

                        UndoUtility.RegisterCompleteObjectUndo(currentShapeInOverlay, "Change Shape");
                        Selection.activeObject = null;
                        currentShapeInOverlay.SetShape(EditorShapeUtility.CreateShape(type), currentShapeInOverlay.pivotLocation);
                        SetBounds(currentShapeInOverlay.size);

                        ProBuilderEditor.Refresh();
                    }
                }
            }
        }
    }
示例#7
0
        void ResetPrefs()
        {
            var type = EditorShapeUtility.availableShapeTypes[s_ActiveShapeIndex];

            if (currentShapeInOverlay == m_LastShapeCreated)
            {
                m_LastShapeCreated = null;
            }

            UndoUtility.RegisterCompleteObjectUndo(currentShapeInOverlay, "Change Shape");
            currentShapeInOverlay.SetShape(EditorShapeUtility.CreateShape(type), currentShapeInOverlay.pivotLocation);
            SetBounds(currentShapeInOverlay.size);

            ProBuilderEditor.Refresh();
        }
示例#8
0
        static bool DoOrientationHandle(FaceData face, ProBuilderShape proBuilderShape)
        {
            Event evt        = Event.current;
            bool  hasRotated = false;

            switch (evt.type)
            {
            case EventType.MouseDown:
                if (k_OrientationControlIDs.Contains(HandleUtility.nearestControl) && evt.button == 0)
                {
                    s_CurrentId           = HandleUtility.nearestControl;
                    GUIUtility.hotControl = s_CurrentId;
                    evt.Use();
                }
                break;

            case EventType.MouseUp:
                if (k_OrientationControlIDs.Contains(HandleUtility.nearestControl) && evt.button == 0)
                {
                    GUIUtility.hotControl = 0;
                    evt.Use();
                    if (s_CurrentId == HandleUtility.nearestControl)
                    {
                        //Execute rotation
                        Vector3 targetedNormal = Vector3.zero;
                        for (int i = 0; i < k_OrientationControlIDs.Length; i++)
                        {
                            if (k_OrientationControlIDs[i] == s_CurrentId)
                            {
                                targetedNormal = (s_ArrowsLines[i][1] - face.CenterPosition).normalized;
                                break;
                            }
                        }

                        var currentNormal = face.Normal;
                        currentNormal.Scale(Math.Sign(proBuilderShape.size));
                        targetedNormal.Scale(Math.Sign(proBuilderShape.size));
                        Vector3 rotationAxis = Vector3.Cross(currentNormal, targetedNormal);
                        var     angle        = Vector3.SignedAngle(currentNormal, targetedNormal, rotationAxis);
                        s_ShapeRotation = Quaternion.AngleAxis(angle, rotationAxis);
                        s_CurrentAngle  = (s_CurrentAngle + angle) % 360;

                        hasRotated = true;
                    }
                    s_CurrentId = -1;
                }
                break;

            case EventType.Layout:
                for (int i = 0; i < 4; i++)
                {
                    var   rectPos = 0.8f * s_ArrowsLines[i][1] + 0.2f * face.CenterPosition;
                    float dist    = HandleUtility.DistanceToRectangle(rectPos,
                                                                      Quaternion.LookRotation(face.Normal),
                                                                      HandleUtility.GetHandleSize(face.CenterPosition) * s_DefaultMidpointSquareSize / 2f);
                    HandleUtility.AddControl(k_OrientationControlIDs[i], dist);
                }
                break;

            case EventType.Repaint:
                if (s_CurrentArrowHovered != HandleUtility.nearestControl)
                {
                    s_CurrentAngle = 0f;
                }

                int pointsCount = face.Points.Length;
                s_CurrentArrowHovered = -1;
                for (int i = 0; i < pointsCount; i++)
                {
                    var rectHandleSize = HandleUtility.GetHandleSize(face.CenterPosition) * s_DefaultMidpointSquareSize;

                    var sideDirection  = (face.Points[(i + 1) % pointsCount] - face.Points[i]).normalized;
                    var arrowDirection = Vector3.Cross(face.Normal.normalized, sideDirection).normalized;

                    var topDirection = 2.5f * rectHandleSize * arrowDirection;
                    var top          = face.CenterPosition + topDirection;
                    var A            = topDirection.magnitude;
                    var a            = 0.33f * Mathf.Sqrt(2f * A * A);
                    var h            = 0.5f * Mathf.Sqrt(2f * a * a);
                    s_ArrowsLines[i][0] = top - (h * arrowDirection + h * sideDirection);
                    s_ArrowsLines[i][1] = top;
                    s_ArrowsLines[i][2] = top - (h * arrowDirection - h * sideDirection);

                    bool selected = HandleUtility.nearestControl == k_OrientationControlIDs[i];

                    Color color = selected
                               ? EditorHandleDrawing.edgeSelectedColor
                               : k_BoundsHandleColor;
                    color.a = 1.0f;

                    using (new Handles.DrawingScope(color))
                    {
                        Handles.DrawAAPolyLine(5f, s_ArrowsLines[i]);
                        if (selected)
                        {
                            EditorGUIUtility.AddCursorRect(new Rect(0, 0, Screen.width, Screen.height), MouseCursor.RotateArrow);
                            s_CurrentArrowHovered = HandleUtility.nearestControl;
                            Handles.DrawAAPolyLine(3f,
                                                   new Vector3[]
                            {
                                Vector3.Scale(proBuilderShape.rotation * Vector3.up, proBuilderShape.size / 2f),
                                Vector3.zero,
                                Vector3.Scale(proBuilderShape.rotation * Vector3.forward, proBuilderShape.size / 2f)
                            });
                        }
                    }
                }
                break;

            case EventType.MouseDrag:
                if (k_OrientationControlIDs.Contains(s_CurrentId) && HandleUtility.nearestControl != s_CurrentId)
                {
                    GUIUtility.hotControl = 0;
                    s_CurrentId           = -1;
                }
                break;
            }
            return(hasRotated);
        }
示例#9
0
        static void DoSizeHandles(ProBuilderShape proBuilderShape, bool updatePrefs)
        {
            int faceCount = s_Faces.Length;

            var evt = Event.current;

            var is2D = proBuilderShape.shape is Plane || proBuilderShape.shape is Sprite;

            for (int i = 0; i < faceCount; i++)
            {
                var face = faces[i];
                if (is2D && !face.IsValid)
                {
                    continue;
                }

                if (Event.current.type == EventType.Repaint)
                {
                    Color color = k_BoundsHandleColor;
                    color.a *= face.IsVisible ? 1f : 0.5f;
                    using (new Handles.DrawingScope(color))
                    {
                        int pointsCount = face.Points.Length;
                        for (int k = 0; k < pointsCount; k++)
                        {
                            Handles.DrawLine(face.Points[k], face.Points[(k + 1) % pointsCount]);
                        }
                    }
                }

                if (DoFaceSizeHandle(face, s_FaceControlIDs[i]))
                {
                    if (!s_SizeManipulationInit)
                    {
                        s_StartCenter          = proBuilderShape.transform.position + proBuilderShape.transform.TransformVector(proBuilderShape.shapeBox.center);
                        s_StartScale           = proBuilderShape.transform.lossyScale;
                        s_StartScaleInverse    = new Vector3(1f / Mathf.Abs(s_StartScale.x), 1f / Mathf.Abs(s_StartScale.y), 1f / Mathf.Abs(s_StartScale.z));
                        s_StartPositionLocal   = face.CenterPosition;
                        s_StartPositionGlobal  = proBuilderShape.transform.TransformPoint(Vector3.Scale(face.CenterPosition, s_StartScale));
                        s_StartSize            = proBuilderShape.size;
                        s_SizeManipulationInit = true;
                        s_Scaling = Vector3.Scale(face.Normal, Math.Sign(s_StartSize));
                    }

                    var targetSize = s_StartSize;
                    if (Math.IsCardinalAxis(proBuilderShape.transform.up) &&
                        EditorSnapSettings.gridSnapEnabled &&
                        !EditorSnapSettings.incrementalSnapActive &&
                        !evt.alt)
                    {
                        var faceDelta    = (s_SizeDelta * s_Faces[i].Normal);
                        var facePosition = s_StartPositionGlobal + faceDelta;
                        facePosition = ProBuilderSnapping.Snap(facePosition, EditorSnapping.activeMoveSnapValue);
                        targetSize  += Vector3.Scale((facePosition - s_StartPositionGlobal), s_Scaling);
                    }
                    else
                    {
                        //Should we expand on the 2 sides?
                        var modifier = evt.alt ? 2f : 1f;
                        var delta    = modifier * (s_SizeDelta * s_Faces[i].Normal);
                        delta.Scale(s_Scaling);
                        delta.Scale(s_StartScaleInverse);

                        targetSize += delta;
                        var snap = EditorSnapSettings.incrementalSnapActive
                            ? Vector3.Scale(EditorSnapping.activeMoveSnapValue, Math.Abs(face.Normal))
                            : Vector3.zero;

                        targetSize = ProBuilderSnapping.Snap(targetSize, snap);
                    }

                    var center = Vector3.zero;
                    if (!evt.alt)
                    {
                        center = Vector3.Scale((targetSize - s_StartSize) / 2f, s_Scaling);
                        center = Vector3.Scale(center, Math.Sign(s_StartScale));
                        center = proBuilderShape.transform.TransformVector(center);
                    }

                    ApplyProperties(proBuilderShape, s_StartCenter + center, targetSize);

                    if (updatePrefs)
                    {
                        DrawShapeTool.SaveShapeParams(proBuilderShape);
                    }
                }
            }
        }
        static void DoSizeHandles(ProBuilderShape proBuilderShape, bool updatePrefs)
        {
            int faceCount = s_Faces.Length;

            var evt = Event.current;

            var is2D = proBuilderShape.shape is Plane || proBuilderShape.shape is Sprite;

            for (int i = 0; i < faceCount; i++)
            {
                var face = faces[i];
                if (is2D && !face.IsValid)
                {
                    continue;
                }

                if (Event.current.type == EventType.Repaint)
                {
                    Color color = k_BoundsHandleColor;
                    color.a *= face.IsVisible ? 1f : 0.5f;
                    using (new Handles.DrawingScope(color))
                    {
                        int pointsCount = face.Points.Length;
                        for (int k = 0; k < pointsCount; k++)
                        {
                            Handles.DrawLine(face.Points[k], face.Points[(k + 1) % pointsCount]);
                        }
                    }
                }

                if (DoFaceSizeHandle(face))
                {
                    float modifier = 1f;
                    if (evt.alt)
                    {
                        modifier = 2f;
                    }

                    if (!s_SizeManipulationInit)
                    {
                        s_StartCenter          = proBuilderShape.transform.position + proBuilderShape.transform.TransformVector(proBuilderShape.shapeBox.center);
                        s_StartPosition        = face.CenterPosition;
                        s_StartSize            = proBuilderShape.size;
                        s_SizeManipulationInit = true;

                        s_Scaling = Vector3.Scale(face.Normal, Math.Sign(s_StartSize));
                    }

                    var targetDelta = modifier * (s_TargetSize - s_StartPosition);
                    targetDelta.Scale(s_Scaling);

                    var targetSize = s_StartSize + targetDelta;

                    var snap = Math.IsCardinalAxis(proBuilderShape.transform.up) && EditorSnapSettings.gridSnapEnabled ?
                               EditorSnapping.activeMoveSnapValue :
                               Vector3.zero;
                    targetSize = ProBuilderSnapping.Snap(targetSize, snap);

                    var center = Vector3.zero;
                    if (!evt.alt)
                    {
                        center = Vector3.Scale((targetSize - s_StartSize) / 2f, s_Scaling);
                        center = Vector3.Scale(center, Math.Sign(proBuilderShape.transform.lossyScale));
                        center = proBuilderShape.transform.TransformVector(center);
                    }

                    ApplyProperties(proBuilderShape, s_StartCenter + center, targetSize);

                    if (updatePrefs)
                    {
                        DrawShapeTool.SaveShapeParams(proBuilderShape);
                    }
                }
            }
        }
示例#11
0
        public void DrawShapeParametersGUI(DrawShapeTool tool = null)
        {
            if (target == null || serializedObject == null)
            {
                return;
            }

            serializedObject.Update();

            var foldoutEnabled = tool == null ? s_foldoutEnabled : DrawShapeTool.s_SettingsEnabled.value;

            foldoutEnabled = EditorGUILayout.Foldout(foldoutEnabled, m_ShapePropertyLabel, true);

            if (tool == null)
            {
                s_foldoutEnabled = foldoutEnabled;
            }
            else
            {
                DrawShapeTool.s_SettingsEnabled.value = foldoutEnabled;
            }

            if (foldoutEnabled)
            {
                EditorGUI.indentLevel++;

                EditorGUI.BeginChangeCheck();
                m_ActiveShapeIndex = HasMultipleShapeTypes
                    ? -1
                    : Mathf.Max(-1, Array.IndexOf(EditorShapeUtility.availableShapeTypes, m_CurrentShapeType));
                m_ActiveShapeIndex = EditorGUILayout.Popup(m_ActiveShapeIndex, EditorShapeUtility.shapeTypes);

                if (EditorGUI.EndChangeCheck())
                {
                    var type = EditorShapeUtility.availableShapeTypes[m_ActiveShapeIndex];
                    foreach (var comp in targets)
                    {
                        ProBuilderShape proBuilderShape = ((ProBuilderShape)comp);
                        Shape           shape           = proBuilderShape.shape;
                        if (shape.GetType() != type)
                        {
                            if (tool != null)
                            {
                                DrawShapeTool.s_ActiveShapeIndex.value = m_ActiveShapeIndex;
                            }

                            UndoUtility.RecordComponents <Transform, ProBuilderMesh, ProBuilderShape>(new [] { proBuilderShape }, "Change Shape");
                            proBuilderShape.SetShape(EditorShapeUtility.CreateShape(type), proBuilderShape.pivotLocation);
                            ProBuilderEditor.Refresh();
                        }
                    }
                }

                if (tool)
                {
                    EditorGUILayout.PropertyField(m_ShapePivotProperty, k_ShapePivotLabel);
                }

                var labelWidth = EditorGUIUtility.labelWidth;
                var fieldWidth = EditorGUIUtility.fieldWidth;
                EditorGUIUtility.labelWidth = 30;
                EditorGUIUtility.fieldWidth = 30;
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.PropertyField(m_ShapeSizeXProperty, k_ShapeSizeXLabel);
                var is2D = HasMultipleShapeTypes ||
                           (m_CurrentShapeType != typeof(Plane) && m_CurrentShapeType != typeof(Sprite));
                using (new EditorGUI.DisabledScope(!is2D))
                    EditorGUILayout.PropertyField(m_ShapeSizeYProperty, k_ShapeSizeYLabel);
                EditorGUILayout.PropertyField(m_ShapeSizeZProperty, k_ShapeSizeZLabel);
                EditorGUILayout.EndHorizontal();
                EditorGUIUtility.labelWidth = labelWidth;
                EditorGUIUtility.fieldWidth = fieldWidth;

                EditorGUI.indentLevel--;
            }

            if (!HasMultipleShapeTypes)
            {
                EditorGUILayout.PropertyField(m_ShapeProperty, new GUIContent("Shape Properties"), true);
            }

            if (serializedObject.ApplyModifiedProperties())
            {
                foreach (var comp in targets)
                {
                    var shapeComponent = comp as ProBuilderShape;
                    if (shapeComponent.isEditable)
                    {
                        UndoUtility.RecordComponents <Transform, ProBuilderMesh, ProBuilderShape>(shapeComponent.GetComponents(typeof(Component)), "Resize Shape");
                        shapeComponent.UpdateComponent();
                        if (tool != null)
                        {
                            tool.SetBounds(shapeComponent.size);
                            DrawShapeTool.SaveShapeParams(shapeComponent);
                        }
                        ProBuilderEditor.Refresh();
                    }
                }
            }

            GUI.enabled = true;
        }