123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- using System;
- using System.Linq;
- using UnityEngine;
- namespace UnityEditor.Experimental.Rendering.Universal.Path2D
- {
- internal class EditablePathController : IEditablePathController
- {
- private ISnapping<Vector3> m_Snapping = new Snapping();
- public IEditablePath editablePath { get; set; }
- public IEditablePath closestEditablePath { get { return editablePath; } }
- public ISnapping<Vector3> snapping
- {
- get { return m_Snapping; }
- set { m_Snapping = value; }
- }
- public bool enableSnapping { get; set; }
- public void RegisterUndo(string name)
- {
- if (editablePath.undoObject != null)
- editablePath.undoObject.RegisterUndo(name);
- }
- public void ClearSelection()
- {
- editablePath.selection.Clear();
- }
- public void SelectPoint(int index, bool select)
- {
- editablePath.selection.Select(index, select);
- }
- public void CreatePoint(int index, Vector3 position)
- {
- ClearSelection();
- if (editablePath.shapeType == ShapeType.Polygon)
- {
- editablePath.InsertPoint(index + 1, new ControlPoint() { position = position });
- }
- else if (editablePath.shapeType == ShapeType.Spline)
- {
- var nextIndex = NextIndex(index);
- var currentPoint = editablePath.GetPoint(index);
- var nextPoint = editablePath.GetPoint(nextIndex);
- float t;
- var closestPoint = BezierUtility.ClosestPointOnCurve(
- position,
- currentPoint.position,
- nextPoint.position,
- GetRightTangentPosition(index),
- GetLeftTangentPosition(nextIndex),
- out t);
- Vector3 leftStartPosition;
- Vector3 leftEndPosition;
- Vector3 leftStartTangent;
- Vector3 leftEndTangent;
- Vector3 rightStartPosition;
- Vector3 rightEndPosition;
- Vector3 rightStartTangent;
- Vector3 rightEndTangent;
- BezierUtility.SplitBezier(t, currentPoint.position, nextPoint.position, GetRightTangentPosition(index), GetLeftTangentPosition(nextIndex),
- out leftStartPosition, out leftEndPosition, out leftStartTangent, out leftEndTangent,
- out rightStartPosition, out rightEndPosition, out rightStartTangent, out rightEndTangent);
- var newPointIndex = index + 1;
- var newPoint = new ControlPoint()
- {
- position = closestPoint,
- leftTangent = leftEndTangent,
- rightTangent = rightStartTangent,
- tangentMode = TangentMode.Continuous
- };
- currentPoint.rightTangent = leftStartTangent;
- nextPoint.leftTangent = rightEndTangent;
- if (currentPoint.tangentMode == TangentMode.Linear && nextPoint.tangentMode == TangentMode.Linear)
- {
- newPoint.tangentMode = TangentMode.Linear;
- newPoint.localLeftTangent = Vector3.zero;
- newPoint.localRightTangent = Vector3.zero;
- currentPoint.localRightTangent = Vector3.zero;
- nextPoint.localLeftTangent = Vector3.zero;
- }
- else
- {
- if (currentPoint.tangentMode == TangentMode.Linear)
- currentPoint.tangentMode = TangentMode.Broken;
- if (nextPoint.tangentMode == TangentMode.Linear)
- nextPoint.tangentMode = TangentMode.Broken;
- }
- editablePath.SetPoint(index, currentPoint);
- editablePath.SetPoint(nextIndex, nextPoint);
- editablePath.InsertPoint(newPointIndex, newPoint);
- }
- }
- public void RemoveSelectedPoints()
- {
- var minPointCount = editablePath.isOpenEnded ? 2 : 3;
- if (editablePath.pointCount > minPointCount)
- {
- var indices = editablePath.selection.elements.OrderByDescending( i => i);
- foreach (var index in indices)
- if (editablePath.pointCount > minPointCount)
- editablePath.RemovePoint(index);
- ClearSelection();
- }
- }
- public void MoveSelectedPoints(Vector3 delta)
- {
- delta = Vector3.ProjectOnPlane(delta, editablePath.forward);
- for (var i = 0; i < editablePath.pointCount; ++i)
- {
- if (editablePath.selection.Contains(i))
- {
- var controlPoint = editablePath.GetPoint(i);
- controlPoint.position += delta;
- editablePath.SetPoint(i, controlPoint);
- }
- }
- }
- public void MoveEdge(int index, Vector3 delta)
- {
- if (editablePath.isOpenEnded && index == editablePath.pointCount - 1)
- return;
-
- var controlPoint = editablePath.GetPoint(index);
- controlPoint.position += delta;
- editablePath.SetPoint(index, controlPoint);
- controlPoint = NextControlPoint(index);
- controlPoint.position += delta;
- editablePath.SetPoint(NextIndex(index), controlPoint);
- }
- public void SetLeftTangent(int index, Vector3 position, bool setToLinear, bool mirror, Vector3 cachedRightTangent)
- {
- var controlPoint = editablePath.GetPoint(index);
- controlPoint.leftTangent = position;
- controlPoint.mirrorLeft = false;
- if (setToLinear)
- {
- controlPoint.leftTangent = controlPoint.position;
- controlPoint.rightTangent = cachedRightTangent;
- }
- else if (controlPoint.tangentMode == TangentMode.Continuous || mirror)
- {
- var magnitude = controlPoint.localRightTangent.magnitude;
- if (mirror)
- magnitude = controlPoint.localLeftTangent.magnitude;
- controlPoint.localRightTangent = magnitude * -controlPoint.localLeftTangent.normalized;
- }
- editablePath.SetPoint(index, controlPoint);
- }
- public void SetRightTangent(int index, Vector3 position, bool setToLinear, bool mirror, Vector3 cachedLeftTangent)
- {
- var controlPoint = editablePath.GetPoint(index);
- controlPoint.rightTangent = position;
- controlPoint.mirrorLeft = true;
- if (setToLinear)
- {
- controlPoint.rightTangent = controlPoint.position;
- controlPoint.leftTangent = cachedLeftTangent;
- }
- else if (controlPoint.tangentMode == TangentMode.Continuous || mirror)
- {
- var magnitude = controlPoint.localLeftTangent.magnitude;
- if (mirror)
- magnitude = controlPoint.localRightTangent.magnitude;
- controlPoint.localLeftTangent = magnitude * -controlPoint.localRightTangent.normalized;
- }
- editablePath.SetPoint(index, controlPoint);
- }
- public void ClearClosestPath() { }
- public void AddClosestPath(float distance) { }
- private Vector3 GetLeftTangentPosition(int index)
- {
- var isLinear = Mathf.Approximately(editablePath.GetPoint(index).localLeftTangent.sqrMagnitude, 0f);
- if (isLinear)
- {
- var position = editablePath.GetPoint(index).position;
- var prevPosition = PrevControlPoint(index).position;
- return (1f / 3f) * (prevPosition - position) + position;
- }
- return editablePath.GetPoint(index).leftTangent;
- }
- private Vector3 GetRightTangentPosition(int index)
- {
- var isLinear = Mathf.Approximately(editablePath.GetPoint(index).localRightTangent.sqrMagnitude, 0f);
- if (isLinear)
- {
- var position = editablePath.GetPoint(index).position;
- var nextPosition = NextControlPoint(index).position;
- return (1f / 3f) * (nextPosition - position) + position;
- }
- return editablePath.GetPoint(index).rightTangent;
- }
- private int NextIndex(int index)
- {
- return EditablePathUtility.Mod(index + 1, editablePath.pointCount);
- }
- private ControlPoint NextControlPoint(int index)
- {
- return editablePath.GetPoint(NextIndex(index));
- }
- private int PrevIndex(int index)
- {
- return EditablePathUtility.Mod(index - 1, editablePath.pointCount);
- }
- private ControlPoint PrevControlPoint(int index)
- {
- return editablePath.GetPoint(PrevIndex(index));
- }
- }
- }
|