Пример #1
0
        /// <summary>
        /// Draw the control handle for manipulating <paramref name="pointIndex"/> of <paramref name="spline"/>
        /// </summary>
        /// <param name="spline">spline to draw for</param>
        /// <param name="pointIndex">control point index to render from the <paramref name="spline"/></param>
        protected virtual void DrawSelectedHandles(ISpline3DEditor spline, int pointIndex)
        {
            float3 point = spline.GetControlPoint3DWorld(pointIndex);

            EditorGUI.BeginChangeCheck();

            Quaternion handleRotation = Quaternion.identity;

            if (Tools.pivotRotation == PivotRotation.Local && SceneView.lastActiveSceneView != null)
            {
                // point handle away from camera
                handleRotation = LastSceneCameraTrans.rotation;
            }

            float3 pos = Handles.DoPositionHandle(point, handleRotation);

            if (EditorGUI.EndChangeCheck() && spline is Object objSpline)
            {
                Undo.RecordObject(objSpline, "Move Point");
                EditorUtility.SetDirty(objSpline);

                spline.UpdateControlPointWorld(pointIndex, pos, SplinePoint.Point);

                SceneView.RepaintAll();
            }
        }
Пример #2
0
        /// <summary>
        /// Renders a blue dot at each control point of the spline and a control handle for the point that is selected
        /// </summary>
        /// <param name="spline">spline to render control points for</param>
        protected void RenderControlPoints(ISpline3DEditor spline)
        {
            for (int i = 0; i < spline.ControlPointCount; i++)
            {
                bool selected = m_editControlPoint == i;
                Handles.color = selected ? Color.blue : new Color(0f, 1f, 1f, 0.73f);

                // draw handles
                if (selected)
                {
                    DrawSelectedHandles(spline, i);
                }
                else
                {
                    Vector3 editorPosition = spline.GetControlPoint3DWorld(i);

                    float size = HandleUtility.GetHandleSize(editorPosition) / 12f;
                    if (Handles.Button(editorPosition, Quaternion.identity, size, size, Handles.DotHandleCap))
                    {
                        m_editControlPoint = i;
                        Repaint();
                    }
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Handles the control logic for adding a point. This will draw a red line from the mouse position to the closest point along the
        /// curve
        /// </summary>
        /// <param name="spline">spline to handle control point logic for</param>
        protected void PointSelection(ISpline3DEditor spline)
        {
            int    splineIndex;
            float3 splinePoint, splineMousePoint;

            ClosestPointSelection(Event.current.mousePosition, spline, out splineIndex, out splinePoint, out splineMousePoint);

            if (splineIndex != m_editNewPointIndex)
            {
                m_editNewPointIndex = splineIndex;
                Repaint(); // force refresh inspector
            }

            Handles.color = Color.red;
            Handles.DrawLine(splinePoint, splineMousePoint);

            if (EditorInputAbstractions.LeftClick() && spline is Object objSpline)
            {
                Undo.RecordObject(objSpline, "Insert Spline Point");
                EditorUtility.SetDirty(objSpline);

                if ((m_editNewPointIndex == spline.ControlPointCount - 1 || spline.ControlPointCount == 1) &&
                    splinePoint.Equals(spline.GetControlPoint3DLocal(m_editNewPointIndex)))
                {
                    spline.AddControlPoint(splineMousePoint);
                }
                else
                {
                    spline.InsertControlPointWorldSpace(m_editNewPointIndex, splineMousePoint);
                }

                SceneView.RepaintAll();
            }
        }
Пример #4
0
        public void UpdateControlPoint(ISimpleSpline3D spline, int index, float3 newPoint, SplinePoint pointType)
        {
            ISpline3DEditor spline3D = spline as ISpline3DEditor;

            Assert.NotNull(spline3D);

            spline3D.UpdateControlPointWorld(index, newPoint, pointType);
        }
Пример #5
0
        public void InsertControlPointLocalSpace(ISimpleSpline3D spline, int index, float3 point)
        {
            ISpline3DEditor spline3D = spline as ISpline3DEditor;

            Assert.NotNull(spline3D);

            spline3D.InsertControlPointLocalSpace(index, point);
        }
Пример #6
0
        protected override void MoveWithTransform(ISpline3DEditor spline)
        {
            if (m_editMoveWithTrans)
            {
                return;
            }

            Vector3 currentPosition = m_sourceTrans.position;

            if (currentPosition != m_lastTransPosition)
            {
                Vector3 delta = m_lastTransPosition - currentPosition;
                m_lastTransPosition = currentPosition;

                // move all the points by delta amount
                spline.MoveControlPoints(new float3(delta.x, delta.y, delta.z));
            }
        }
Пример #7
0
        /// <inheritdoc cref="Base3DEditor.DrawSelectedHandles"/>
        protected override void DrawSelectedHandles(ISpline3DEditor spline, int pointIndex)
        {
            float3 point = spline.GetControlPoint3DWorld(pointIndex);

            EditorGUI.BeginChangeCheck();

            ISpline3DPlane plane = spline as ISpline3DPlane;
            float3         pos   = Handles.DoPositionHandle(point, plane.Forward);

            if (EditorGUI.EndChangeCheck() && spline is Object objSpline)
            {
                Undo.RecordObject(objSpline, "Move Point");
                EditorUtility.SetDirty(objSpline);

                spline.UpdateControlPointWorld(pointIndex, pos, SplinePoint.Point);

                SceneView.RepaintAll();
            }
        }
Пример #8
0
        /// <summary>
        /// Find the closest point to the spline
        /// </summary>
        /// <param name="mouse">mouse position</param>
        /// <param name="spline">spline to check</param>
        /// <param name="index">spline index of the closest point</param>
        /// <returns>closest point on the spline to the mouse</returns>
        protected override bool ClosestPointSelection(float2 mouse, ISpline3DEditor spline, out int index, out float3 splinePoint,
                                                      out float3 creationPoint)
        {
            index       = 0;
            splinePoint = float3.zero;

            float2 mouseComparison = new float2(mouse.x, LastSceneCamera.pixelHeight - mouse.y);
            float  bestDistance    = float.MaxValue;

            // this could potentially be cached as long as the spline doesn't change and the camera is at the same position
            for (int i = 1; i < spline.SegmentPointCount; i++)
            {
                for (int s = 0; s <= 64; s++)
                {
                    float   progress       = s / 64f;
                    float3  p              = spline.Get3DPoint(progress, i - 1);
                    Vector3 screenPosition = LastSceneCamera.WorldToScreenPoint(p);

                    HandleDrawCross(screenPosition, 0.5f);

                    float dist = math.distance(mouseComparison, new float2(screenPosition.x, screenPosition.y));
                    if (bestDistance > dist)
                    {
                        splinePoint  = p;
                        bestDistance = dist;

                        if (progress > 0.5)
                        {
                            index = (i + 1) % spline.ControlPointCount;
                        }
                        else
                        {
                            index = i;
                        }
                    }
                }
            }

            if (!(spline is ILoopingSpline) || !((ILoopingSpline)spline).Looped)
            {
                if (math.distance(splinePoint, spline.GetControlPoint3DWorld(0)) <= 0.00001f)
                {
                    index = 0;
                }
                else if (math.distance(splinePoint, spline.GetControlPoint3DWorld(spline.ControlPointCount - 1)) <= 0.00001f)
                {
                    index = spline.ControlPointCount;
                }
            }

            // convert the spline point and mouse position into the new point position
            if (!splinePoint.Equals(float3.zero))
            {
                Vector3 camPosition = LastSceneCameraTrans.position;

                float worldDistance = math.distance(splinePoint, camPosition);
                Ray   cameraRay     = LastSceneCamera.ScreenPointToRay(new Vector3(mouseComparison.x, mouseComparison.y, 0f));

                creationPoint = cameraRay.GetPoint(worldDistance);
                return(true);
            }

            creationPoint = default;
            return(false);
        }
Пример #9
0
        /// <summary>
        /// Shared Inspector logic
        /// </summary>
        /// <param name="spline">spline to show inspector for</param>
        protected void OnInspectorGUI(ISpline3DEditor spline)
        {
            if (GUILayout.Button("Edit Points"))
            {
                m_editing           = !m_editing;
                m_editControlPoint  = null;
                m_editNewPointIndex = -1;
                m_lastTransPosition = m_sourceTrans?.position ?? Vector3.zero;

                SceneView.RepaintAll();
            }

            if (!m_editing)
            {
                GUILayout.Space(5);
                EditorGUILayout.HelpBox(
                    $"Points: {spline.ControlPointCount}\n" +
                    $"Length: {spline.Length():N3}", MessageType.None);

                if (spline is ILoopingSpline loop)
                {
                    EditorGUI.BeginChangeCheck();
                    loop.Looped = EditorGUILayout.Toggle("Loop", loop.Looped);
                    if (EditorGUI.EndChangeCheck())
                    {
                        SceneView.RepaintAll();
                    }
                }

                if (spline is IArkableSpline arked)
                {
                    EditorGUI.BeginChangeCheck();
                    arked.ArkParameterization = EditorGUILayout.Toggle("Ark Parametrization", arked.ArkParameterization);
                    if (EditorGUI.EndChangeCheck() && spline is Object objSpline)
                    {
                        EditorUtility.SetDirty(objSpline);
                    }

                    if (arked.ArkParameterization)
                    {
                        EditorGUI.BeginChangeCheck();
                        arked.ArkLength = EditorGUILayout.FloatField("Ark Length", arked.ArkLength);
                        if (EditorGUI.EndChangeCheck() && spline is Object objSpline2)
                        {
                            EditorUtility.SetDirty(objSpline2);
                        }
                    }
                }

                GUILayout.Space(5);

                // Draw spline points - Draw a point every set interval to illustrate where bezier points will be
                EditorGUI.BeginChangeCheck();
                m_debugPointQty = (int)EditorGUILayout.Slider("Draw points", m_debugPointQty, 0, 200);
                if (EditorGUI.EndChangeCheck())
                {
                    SceneView.RepaintAll();
                }
            }
            else
            {
                if (m_sourceTrans != null)
                {
                    bool value = EditorGUILayout.Toggle("Move Points with Transform", m_editMoveWithTrans);
                    if (value != m_editMoveWithTrans)
                    {
                        m_editMoveWithTrans = value;
                        m_lastTransPosition = m_sourceTrans.position;
                    }

                    MoveWithTransform(spline);
                }

                if (m_editNewPointIndex >= 0)
                {
                    EditorGUILayout.LabelField($"New At Index: {m_editNewPointIndex}");
                }

                if (m_editControlPoint == null)
                {
                    EditorGUILayout.HelpBox($"No Control Point Selected!", MessageType.None);
                }
                else
                {
                    m_editNewPointIndex = -1;
                    EditorGUILayout.LabelField($"Control Point: {m_editControlPoint}");

                    // show the current control point location
                    EditorGUI.BeginChangeCheck();
                    if (m_inspector3dPoint)
                    {
                        float3 currentPoint = spline.GetControlPoint3DLocal(m_editControlPoint.Value);
                        currentPoint = EditorGUILayout.Vector3Field("Point", currentPoint);
                        if (EditorGUI.EndChangeCheck())
                        {
                            spline.UpdateControlPointLocal(m_editControlPoint.Value, currentPoint, SplinePoint.Point);
                            SceneView.RepaintAll();
                        }
                    }
                    else
                    { // useful for spline plane
                        ISpline2DEditor spline2D = spline as ISpline2DEditor;

                        float2 currentPoint = spline2D.GetControlPoint2DLocal(m_editControlPoint.Value);
                        currentPoint = EditorGUILayout.Vector2Field("Point", currentPoint);
                        if (EditorGUI.EndChangeCheck())
                        {
                            spline2D.UpdateControlPointLocal(m_editControlPoint.Value, currentPoint, SplinePoint.Point);
                            SceneView.RepaintAll();
                        }
                    }

                    SplineEditMode existingValue = spline.GetEditMode(m_editControlPoint.Value);
                    SplineEditMode editMode      = (SplineEditMode)EditorGUILayout.EnumPopup("Edit Mode", existingValue);
                    if (editMode != existingValue && spline is Object objSpline)
                    {
                        Undo.RecordObject(objSpline, $"Change EditMode of Point {m_editControlPoint}");
                        EditorUtility.SetDirty(objSpline);
                        spline.ChangeEditMode(m_editControlPoint.Value, editMode);

                        SceneView.RepaintAll();
                    }

                    GUILayout.Space(10);
                    if (GUILayout.Button("Remove Point") ||
                        Event.current.isKey && Event.current.type == EventType.KeyDown &&
                        Event.current.keyCode == KeyCode.Delete)
                    {
                        spline.RemoveControlPoint(m_editControlPoint.Value);
                        m_editControlPoint = null;

                        SceneView.RepaintAll();

                        if (Event.current.keyCode == KeyCode.Delete)
                        {
                            // Sadly this doesn't actually work :( dammit Unity
                            GUIUtility.hotControl = 0;
                            Event.current.Use();
                        }
                    }
                }
            }
        }