예제 #1
0
        private void DrawVertexPathSceneEditor()
        {
            var bezierColor = globalDisplaySettings.bezierPath;

            bezierColor.a *= .5f;

            if (Getdata.showBezierPathInVertexMode)
            {
                for (int i = 0; i < GetBezierPath.NumSegments; i++)
                {
                    var points = GetBezierPath.GetPointsInSegment(i);

                    for (int j = 0; j < points.Length; j++)
                    {
                        points[j] = MathUtility.TransformPoint(points[j], creator.transform, GetBezierPath.Space);
                    }

                    Handles.DrawBezier(points[0], points[3], points[1], points[2], bezierColor, null, 2);
                }
            }

            Handles.color = globalDisplaySettings.vertexPath;

            for (int i = 0; i < creator.Path.NumPoints; i++)
            {
                var nextIndex = (i + 1) % creator.Path.NumPoints;

                if (nextIndex != 0 || GetBezierPath.IsClosed)
                {
                    Handles.DrawLine(creator.Path.GetPoint(i), creator.Path.GetPoint(nextIndex));
                }
            }

            if (Getdata.showNormalsInVertexMode)
            {
                Handles.color = globalDisplaySettings.normals;

                var normalLines = new Vector3[creator.Path.NumPoints * 2];

                for (int i = 0; i < creator.Path.NumPoints; i++)
                {
                    normalLines[i * 2]     = creator.Path.GetPoint(i);
                    normalLines[i * 2 + 1] = creator.Path.GetPoint(i) + creator.Path.localNormals[i] * globalDisplaySettings.normalsLength;
                }
                Handles.DrawLines(normalLines);
            }
        }
예제 #2
0
        private void DrawHandle(int index)
        {
            var handlePosition    = MathUtility.TransformPoint(GetBezierPath[index], creator.transform, GetBezierPath.Space);
            var anchorHandleSize  = GetHandleDiameter(globalDisplaySettings.anchorSize * Getdata.bezierHandleScale, GetBezierPath[index]);
            var controlHandleSize = GetHandleDiameter(globalDisplaySettings.controlSize * Getdata.bezierHandleScale, GetBezierPath[index]);
            var isAnchorPoint     = index % 3 == 0;
            var isInteractive     = isAnchorPoint || GetBezierPath.ControlPointMode != BezierPath.ControlMode.Automatic;
            var handleSize        = (isAnchorPoint) ? anchorHandleSize : controlHandleSize;
            var doTransformHandle = index == handleIndexToDisplayAsTransform;

            PathHandle.HandleColours handleColours = (isAnchorPoint) ? splineAnchorColours : splineControlColours;

            if (index == handleIndexToDisplayAsTransform)
            {
                handleColours.DefaultColor = (isAnchorPoint) ? globalDisplaySettings.anchorSelected : globalDisplaySettings.controlSelected;
            }

            var cap = capFunctions[(isAnchorPoint) ? globalDisplaySettings.anchorShape : globalDisplaySettings.controlShape];

            PathHandle.HandleInputType handleInputType;

            handlePosition = PathHandle.DrawHandle(handlePosition, GetBezierPath.Space, isInteractive, handleSize, cap, handleColours, out handleInputType, index);

            if (doTransformHandle)
            {
                // Show normals rotate tool
                if (Getdata.showNormals && Tools.current == Tool.Rotate && isAnchorPoint && GetBezierPath.Space == PathSpace.xyz)
                {
                    Handles.color = handlesStartColor;

                    var attachedControlIndex = (index == GetBezierPath.NumPoints - 1) ? index - 1 : index + 1;
                    var dir             = (GetBezierPath[attachedControlIndex] - handlePosition).normalized;
                    var handleRotOffset = (360 + GetBezierPath.GlobalNormalsAngle) % 360;

                    anchorAngleHandle.radius = handleSize * 3;
                    anchorAngleHandle.angle  = handleRotOffset + GetBezierPath.GetAnchorNormalAngle(index / 3);
                    var handleDirection = Vector3.Cross(dir, Vector3.up);
                    var handleMatrix    = Matrix4x4.TRS(
                        handlePosition,
                        Quaternion.LookRotation(handleDirection, dir),
                        Vector3.one
                        );

                    using (new Handles.DrawingScope(handleMatrix))
                    {
                        // draw the handle
                        EditorGUI.BeginChangeCheck();
                        anchorAngleHandle.DrawHandle();
                        if (EditorGUI.EndChangeCheck())
                        {
                            Undo.RecordObject(creator, "Set angle");
                            GetBezierPath.SetAnchorNormalAngle(index / 3, anchorAngleHandle.angle - handleRotOffset);
                        }
                    }
                }
                else
                {
                    handlePosition = Handles.DoPositionHandle(handlePosition, Quaternion.identity);
                }
            }

            switch (handleInputType)
            {
            case PathHandle.HandleInputType.LMBDrag:
                draggingHandleIndex             = index;
                handleIndexToDisplayAsTransform = -1;
                Repaint();
                break;

            case PathHandle.HandleInputType.LMBRelease:
                draggingHandleIndex             = -1;
                handleIndexToDisplayAsTransform = -1;
                Repaint();
                break;

            case PathHandle.HandleInputType.LMBClick:
                draggingHandleIndex = -1;

                if (Event.current.shift)
                {
                    handleIndexToDisplayAsTransform = -1;     // disable move tool if new point added
                }
                else
                {
                    if (handleIndexToDisplayAsTransform == index)
                    {
                        handleIndexToDisplayAsTransform = -1;     // disable move tool if clicking on point under move tool
                    }
                    else
                    {
                        handleIndexToDisplayAsTransform = index;
                    }
                }

                Repaint();
                break;

            case PathHandle.HandleInputType.LMBPress:
                if (handleIndexToDisplayAsTransform != index)
                {
                    handleIndexToDisplayAsTransform = -1;
                    Repaint();
                }
                break;
            }

            var localHandlePosition = MathUtility.InverseTransformPoint(handlePosition, creator.transform, GetBezierPath.Space);

            if (GetBezierPath[index] != localHandlePosition)
            {
                Undo.RecordObject(creator, "Move point");
                GetBezierPath.MovePoint(index, localHandlePosition);
            }
        }
예제 #3
0
        private void DrawBezierPathSceneEditor()
        {
            var displayControlPoints = Getdata.displayControlPoints && (GetBezierPath.ControlPointMode != BezierPath.ControlMode.Automatic || !globalDisplaySettings.hideAutoControls);
            var bounds = GetBezierPath.CalculateBoundsWithTransform(creator.transform);

            if (Event.current.type == EventType.Repaint)
            {
                for (int i = 0; i < GetBezierPath.NumSegments; i++)
                {
                    var points = GetBezierPath.GetPointsInSegment(i);

                    for (int j = 0; j < points.Length; j++)
                    {
                        points[j] = MathUtility.TransformPoint(points[j], creator.transform, GetBezierPath.Space);
                    }

                    if (Getdata.showPerSegmentBounds)
                    {
                        var segmentBounds = CubicBezierUtility.CalculateSegmentBounds(points[0], points[1], points[2], points[3]);

                        Handles.color = globalDisplaySettings.segmentBounds;
                        Handles.DrawWireCube(segmentBounds.center, segmentBounds.size);
                    }

                    // Draw lines between control points
                    if (displayControlPoints)
                    {
                        Handles.color = (GetBezierPath.ControlPointMode == BezierPath.ControlMode.Automatic) ? globalDisplaySettings.handleDisabled : globalDisplaySettings.controlLine;
                        Handles.DrawLine(points[1], points[0]);
                        Handles.DrawLine(points[2], points[3]);
                    }

                    // Draw path
                    var highlightSegment = (i == selectedSegmentIndex && Event.current.shift && draggingHandleIndex == -1 && mouseOverHandleIndex == -1);
                    var segmentColor     = (highlightSegment) ? globalDisplaySettings.highlightedPath : globalDisplaySettings.bezierPath;

                    Handles.DrawBezier(points[0], points[3], points[1], points[2], segmentColor, null, 2);
                }

                if (Getdata.showPathBounds)
                {
                    Handles.color = globalDisplaySettings.bounds;
                    Handles.DrawWireCube(bounds.center, bounds.size);
                }

                // Draw normals
                if (Getdata.showNormals)
                {
                    if (!hasUpdatedNormalsVertexPath)
                    {
                        normalsVertexPath           = new VertexPath(GetBezierPath, creator.transform, normalsSpacing);
                        hasUpdatedNormalsVertexPath = true;
                    }

                    if (editingNormalsOld != Getdata.showNormals)
                    {
                        editingNormalsOld = Getdata.showNormals;
                        Repaint();
                    }

                    var normalLines = new Vector3[normalsVertexPath.NumPoints * 2];

                    Handles.color = globalDisplaySettings.normals;

                    for (int i = 0; i < normalsVertexPath.NumPoints; i++)
                    {
                        normalLines[i * 2]     = normalsVertexPath.GetPoint(i);
                        normalLines[i * 2 + 1] = normalsVertexPath.GetPoint(i) + normalsVertexPath.GetNormal(i) * globalDisplaySettings.normalsLength;
                    }

                    Handles.DrawLines(normalLines);
                }
            }

            if (Getdata.displayAnchorPoints)
            {
                for (int i = 0; i < GetBezierPath.NumPoints; i += 3)
                {
                    DrawHandle(i);
                }
            }
            if (displayControlPoints)
            {
                for (int i = 1; i < GetBezierPath.NumPoints - 1; i += 3)
                {
                    DrawHandle(i);
                    DrawHandle(i + 1);
                }
            }
        }
예제 #4
0
        private void ProcessBezierPathInput(Event e)
        {
            // Find which handle mouse is over. Start by looking at previous handle index first, as most likely to still be closest to mouse
            var previousMouseOverHandleIndex = (mouseOverHandleIndex == -1) ? 0 : mouseOverHandleIndex;

            mouseOverHandleIndex = -1;

            for (int i = 0; i < GetBezierPath.NumPoints; i += 3)
            {
                var handleIndex  = (previousMouseOverHandleIndex + i) % GetBezierPath.NumPoints;
                var handleRadius = GetHandleDiameter(globalDisplaySettings.anchorSize * Getdata.bezierHandleScale, GetBezierPath[handleIndex]) / 2f;
                var pos          = MathUtility.TransformPoint(GetBezierPath[handleIndex], creator.transform, GetBezierPath.Space);
                var dst          = HandleUtility.DistanceToCircle(pos, handleRadius);

                if (dst == 0)
                {
                    mouseOverHandleIndex = handleIndex;
                    break;
                }
            }

            // Shift-left click (when mouse not over a handle) to split or add segment
            if (mouseOverHandleIndex == -1)
            {
                if (e.type == EventType.MouseDown && e.button == 0 && e.shift)
                {
                    UpdatePathMouseInfo();
                    // Insert point along selected segment
                    if (selectedSegmentIndex != -1 && selectedSegmentIndex < GetBezierPath.NumSegments)
                    {
                        var newPathPoint = pathMouseInfo.ClosestWorldPointToMouse;

                        newPathPoint = MathUtility.InverseTransformPoint(newPathPoint, creator.transform, GetBezierPath.Space);
                        Undo.RecordObject(creator, "Split segment");
                        GetBezierPath.SplitSegment(newPathPoint, selectedSegmentIndex, pathMouseInfo.TimeOnBezierSegment);
                    }
                    // If path is not a closed loop, add new point on to the end of the path
                    else if (!GetBezierPath.IsClosed)
                    {
                        // insert new point at same dst from scene camera as the point that comes before it (for a 3d path)
                        var dstCamToEndpoint = (Camera.current.transform.position - GetBezierPath[GetBezierPath.NumPoints - 1]).magnitude;
                        var newPathPoint     = MouseUtility.GetMouseWorldPosition(GetBezierPath.Space, dstCamToEndpoint);

                        newPathPoint = MathUtility.InverseTransformPoint(newPathPoint, creator.transform, GetBezierPath.Space);

                        Undo.RecordObject(creator, "Add segment");
                        if (e.control || e.command)
                        {
                            GetBezierPath.AddSegmentToStart(newPathPoint);
                        }
                        else
                        {
                            GetBezierPath.AddSegmentToEnd(newPathPoint);
                        }
                    }
                }
            }
            // Control click or backspace/delete to remove point
            if (e.keyCode == KeyCode.Backspace || e.keyCode == KeyCode.Delete || ((e.control || e.command) && e.type == EventType.MouseDown && e.button == 0))
            {
                if (mouseOverHandleIndex != -1)
                {
                    Undo.RecordObject(creator, "Delete segment");
                    GetBezierPath.DeleteSegment(mouseOverHandleIndex);

                    if (mouseOverHandleIndex == handleIndexToDisplayAsTransform)
                    {
                        handleIndexToDisplayAsTransform = -1;
                    }

                    mouseOverHandleIndex = -1;
                    Repaint();
                }
            }

            // Holding shift and moving mouse (but mouse not over a handle/dragging a handle)
            if (draggingHandleIndex == -1 && mouseOverHandleIndex == -1)
            {
                var shiftDown = e.shift && !shiftLastFrame;

                if (shiftDown || ((e.type == EventType.MouseMove || e.type == EventType.MouseDrag) && e.shift))
                {
                    UpdatePathMouseInfo();

                    if (pathMouseInfo.MouseDstToLine < segmentSelectDistanceThreshold)
                    {
                        if (pathMouseInfo.ClosestSegmentIndex != selectedSegmentIndex)
                        {
                            selectedSegmentIndex = pathMouseInfo.ClosestSegmentIndex;
                            HandleUtility.Repaint();
                        }
                    }
                    else
                    {
                        selectedSegmentIndex = -1;
                        HandleUtility.Repaint();
                    }
                }
            }
            shiftLastFrame = e.shift;
        }
예제 #5
0
        private void DrawBezierPathInspector()
        {
            using (var check = new EditorGUI.ChangeCheckScope())
            {
                // Path options:
                Getdata.showPathOptions = EditorGUILayout.Foldout(Getdata.showPathOptions, new GUIContent("Bézier Path Options"), true, boldFoldoutStyle);
                if (Getdata.showPathOptions)
                {
                    GetBezierPath.Space            = (PathSpace)EditorGUILayout.Popup("Space", (int)GetBezierPath.Space, spaceNames);
                    GetBezierPath.ControlPointMode = (BezierPath.ControlMode)EditorGUILayout.EnumPopup(new GUIContent("Control Mode"), GetBezierPath.ControlPointMode);
                    if (GetBezierPath.ControlPointMode == BezierPath.ControlMode.Automatic)
                    {
                        GetBezierPath.AutoControlLength = EditorGUILayout.Slider(new GUIContent("Control Spacing"), GetBezierPath.AutoControlLength, 0, 1);
                    }

                    GetBezierPath.IsClosed    = EditorGUILayout.Toggle("Closed Path", GetBezierPath.IsClosed);
                    Getdata.showTransformTool = EditorGUILayout.Toggle(new GUIContent("Enable Transforms"), Getdata.showTransformTool);

                    Tools.hidden = !Getdata.showTransformTool;

                    // Check if out of bounds (can occur after undo operations)
                    if (handleIndexToDisplayAsTransform >= GetBezierPath.NumPoints)
                    {
                        handleIndexToDisplayAsTransform = -1;
                    }

                    // If a point has been selected
                    if (handleIndexToDisplayAsTransform != -1)
                    {
                        EditorGUILayout.LabelField("Selected Point:");

                        using (new EditorGUI.IndentLevelScope())
                        {
                            var currentPosition = creator.BezierPath[handleIndexToDisplayAsTransform];
                            var newPosition     = EditorGUILayout.Vector3Field("Position", currentPosition);

                            if (newPosition != currentPosition)
                            {
                                Undo.RecordObject(creator, "Move point");
                                creator.BezierPath.MovePoint(handleIndexToDisplayAsTransform, newPosition);
                            }
                            // Don't draw the angle field if we aren't selecting an anchor point/not in 3d space
                            if (handleIndexToDisplayAsTransform % 3 == 0 && creator.BezierPath.Space == PathSpace.xyz)
                            {
                                var anchorIndex  = handleIndexToDisplayAsTransform / 3;
                                var currentAngle = creator.BezierPath.GetAnchorNormalAngle(anchorIndex);
                                var newAngle     = EditorGUILayout.FloatField("Angle", currentAngle);

                                if (newAngle != currentAngle)
                                {
                                    Undo.RecordObject(creator, "Set Angle");
                                    creator.BezierPath.SetAnchorNormalAngle(anchorIndex, newAngle);
                                }
                            }
                        }
                    }

                    if (Getdata.showTransformTool & (handleIndexToDisplayAsTransform == -1))
                    {
                        if (GUILayout.Button("Centre Transform"))
                        {
                            var worldCentre  = GetBezierPath.CalculateBoundsWithTransform(creator.transform).center;
                            var transformPos = creator.transform.position;

                            if (GetBezierPath.Space == PathSpace.xy)
                            {
                                transformPos = new Vector3(transformPos.x, transformPos.y, 0);
                            }
                            else if (GetBezierPath.Space == PathSpace.xz)
                            {
                                transformPos = new Vector3(transformPos.x, 0, transformPos.z);
                            }

                            var worldCentreToTransform = transformPos - worldCentre;

                            if (worldCentre != creator.transform.position)
                            {
                                if (worldCentreToTransform != Vector3.zero)
                                {
                                    var localCentreToTransform = MathUtility.InverseTransformVector(worldCentreToTransform, creator.transform, GetBezierPath.Space);

                                    for (int i = 0; i < GetBezierPath.NumPoints; i++)
                                    {
                                        GetBezierPath.SetPoint(i, GetBezierPath.GetPoint(i) + localCentreToTransform, true);
                                    }
                                }

                                creator.transform.position = worldCentre;
                                GetBezierPath.NotifyPathModified();
                            }
                        }
                    }

                    if (GUILayout.Button("Reset Path"))
                    {
                        Undo.RecordObject(creator, "Reset Path");
                        var in2DEditorMode = EditorSettings.defaultBehaviorMode == EditorBehaviorMode.Mode2D;
                        Getdata.ResetBezierPath(creator.transform.position, in2DEditorMode);
                        EditorApplication.QueuePlayerLoopUpdate();
                    }

                    GUILayout.Space(inspectorSectionSpacing);
                }

                Getdata.showNormals = EditorGUILayout.Foldout(Getdata.showNormals, new GUIContent("Normals Options"), true, boldFoldoutStyle);
                if (Getdata.showNormals)
                {
                    GetBezierPath.FlipNormals = EditorGUILayout.Toggle(new GUIContent("Flip Normals"), GetBezierPath.FlipNormals);
                    if (GetBezierPath.Space == PathSpace.xyz)
                    {
                        GetBezierPath.GlobalNormalsAngle = EditorGUILayout.Slider(new GUIContent("Global Angle"), GetBezierPath.GlobalNormalsAngle, 0, 360);

                        if (GUILayout.Button("Reset Normals"))
                        {
                            Undo.RecordObject(creator, "Reset Normals");
                            GetBezierPath.FlipNormals = false;
                            GetBezierPath.ResetNormalAngles();
                        }
                    }
                    GUILayout.Space(inspectorSectionSpacing);
                }

                // Editor display options
                Getdata.showDisplayOptions = EditorGUILayout.Foldout(Getdata.showDisplayOptions, new GUIContent("Display Options"), true, boldFoldoutStyle);
                if (Getdata.showDisplayOptions)
                {
                    Getdata.showPathBounds       = GUILayout.Toggle(Getdata.showPathBounds, new GUIContent("Show Path Bounds"));
                    Getdata.showPerSegmentBounds = GUILayout.Toggle(Getdata.showPerSegmentBounds, new GUIContent("Show Segment Bounds"));
                    Getdata.displayAnchorPoints  = GUILayout.Toggle(Getdata.displayAnchorPoints, new GUIContent("Show Anchor Points"));

                    if (!(GetBezierPath.ControlPointMode == BezierPath.ControlMode.Automatic && globalDisplaySettings.hideAutoControls))
                    {
                        Getdata.displayControlPoints = GUILayout.Toggle(Getdata.displayControlPoints, new GUIContent("Show Control Points"));
                    }

                    Getdata.keepConstantHandleSize = GUILayout.Toggle(Getdata.keepConstantHandleSize, new GUIContent("Constant Point Size", constantSizeTooltip));
                    Getdata.bezierHandleScale      = Mathf.Max(0, EditorGUILayout.FloatField(new GUIContent("Handle Scale"), Getdata.bezierHandleScale));
                    DrawGlobalDisplaySettingsInspector();
                }

                if (check.changed)
                {
                    SceneView.RepaintAll();
                    EditorApplication.QueuePlayerLoopUpdate();
                }
            }
        }