A game about forced loneliness, made by TACStudios
at master 9.5 kB view raw
1using System; 2using System.Linq; 3using UnityEngine; 4 5namespace UnityEditor.U2D.Common.Path 6{ 7 internal class EditablePathController : IEditablePathController 8 { 9 private ISnapping<Vector3> m_Snapping = new Snapping(); 10 11 public IEditablePath editablePath { get; set; } 12 public IEditablePath closestEditablePath { get { return editablePath; } } 13 14 public ISnapping<Vector3> snapping 15 { 16 get { return m_Snapping; } 17 set { m_Snapping = value; } 18 } 19 20 public bool enableSnapping { get; } 21 22 public void RegisterUndo(string name) 23 { 24 if (editablePath.undoObject != null) 25 editablePath.undoObject.RegisterUndo(name); 26 } 27 28 public void ClearSelection() 29 { 30 editablePath.selection.Clear(); 31 } 32 33 public void SelectPoint(int index, bool select) 34 { 35 editablePath.selection.Select(index, select); 36 } 37 38 public void CreatePoint(int index, Vector3 position) 39 { 40 ClearSelection(); 41 42 if (editablePath.shapeType == ShapeType.Polygon) 43 { 44 editablePath.InsertPoint(index + 1, new ControlPoint() { position = position }); 45 } 46 else if (editablePath.shapeType == ShapeType.Spline) 47 { 48 var nextIndex = NextIndex(index); 49 var currentPoint = editablePath.GetPoint(index); 50 var nextPoint = editablePath.GetPoint(nextIndex); 51 52 float t; 53 var closestPoint = BezierUtility.ClosestPointOnCurve( 54 position, 55 currentPoint.position, 56 nextPoint.position, 57 GetRightTangentPosition(index), 58 GetLeftTangentPosition(nextIndex), 59 out t); 60 61 Vector3 leftStartPosition; 62 Vector3 leftEndPosition; 63 Vector3 leftStartTangent; 64 Vector3 leftEndTangent; 65 66 Vector3 rightStartPosition; 67 Vector3 rightEndPosition; 68 Vector3 rightStartTangent; 69 Vector3 rightEndTangent; 70 71 BezierUtility.SplitBezier(t, currentPoint.position, nextPoint.position, GetRightTangentPosition(index), GetLeftTangentPosition(nextIndex), 72 out leftStartPosition, out leftEndPosition, out leftStartTangent, out leftEndTangent, 73 out rightStartPosition, out rightEndPosition, out rightStartTangent, out rightEndTangent); 74 75 var newPointIndex = index + 1; 76 var newPoint = new ControlPoint() 77 { 78 position = closestPoint, 79 leftTangent = leftEndTangent, 80 rightTangent = rightStartTangent, 81 tangentMode = TangentMode.Continuous 82 }; 83 84 currentPoint.rightTangent = leftStartTangent; 85 nextPoint.leftTangent = rightEndTangent; 86 87 if (currentPoint.tangentMode == TangentMode.Linear && nextPoint.tangentMode == TangentMode.Linear) 88 { 89 newPoint.tangentMode = TangentMode.Linear; 90 newPoint.localLeftTangent = Vector3.zero; 91 newPoint.localRightTangent = Vector3.zero; 92 currentPoint.localRightTangent = Vector3.zero; 93 nextPoint.localLeftTangent = Vector3.zero; 94 } 95 else 96 { 97 if (currentPoint.tangentMode == TangentMode.Linear) 98 currentPoint.tangentMode = TangentMode.Broken; 99 100 if (nextPoint.tangentMode == TangentMode.Linear) 101 nextPoint.tangentMode = TangentMode.Broken; 102 } 103 104 editablePath.SetPoint(index, currentPoint); 105 editablePath.SetPoint(nextIndex, nextPoint); 106 editablePath.InsertPoint(newPointIndex, newPoint); 107 } 108 } 109 110 public void RemoveSelectedPoints() 111 { 112 var minPointCount = editablePath.isOpenEnded ? 2 : 3; 113 114 if (editablePath.pointCount > minPointCount) 115 { 116 var indices = editablePath.selection.elements.OrderByDescending( i => i); 117 118 foreach (var index in indices) 119 if (editablePath.pointCount > minPointCount) 120 editablePath.RemovePoint(index); 121 122 ClearSelection(); 123 } 124 } 125 126 public void MoveSelectedPoints(Vector3 delta) 127 { 128 delta = Vector3.ProjectOnPlane(delta, editablePath.forward); 129 130 for (var i = 0; i < editablePath.pointCount; ++i) 131 { 132 if (editablePath.selection.Contains(i)) 133 { 134 var controlPoint = editablePath.GetPoint(i); 135 controlPoint.position += delta; 136 editablePath.SetPoint(i, controlPoint); 137 } 138 } 139 } 140 141 public void MoveEdge(int index, Vector3 delta) 142 { 143 if (editablePath.isOpenEnded && index == editablePath.pointCount - 1) 144 return; 145 146 var controlPoint = editablePath.GetPoint(index); 147 controlPoint.position += delta; 148 editablePath.SetPoint(index, controlPoint); 149 controlPoint = NextControlPoint(index); 150 controlPoint.position += delta; 151 editablePath.SetPoint(NextIndex(index), controlPoint); 152 } 153 154 public void SetLeftTangent(int index, Vector3 position, bool setToLinear, bool mirror, Vector3 cachedRightTangent, TangentMode cachedTangentMode) 155 { 156 var controlPoint = editablePath.GetPoint(index); 157 controlPoint.tangentMode = cachedTangentMode; 158 controlPoint.leftTangent = position; 159 controlPoint.mirrorLeft = false; 160 161 if (setToLinear) 162 { 163 controlPoint.leftTangent = controlPoint.position; 164 controlPoint.rightTangent = cachedRightTangent; 165 } 166 else if (controlPoint.tangentMode == TangentMode.Continuous || mirror) 167 { 168 var magnitude = controlPoint.localRightTangent.magnitude; 169 170 if (mirror) 171 magnitude = controlPoint.localLeftTangent.magnitude; 172 173 controlPoint.localRightTangent = magnitude * -controlPoint.localLeftTangent.normalized; 174 } 175 176 editablePath.SetPoint(index, controlPoint); 177 editablePath.UpdateTangentMode(index); 178 } 179 180 public void SetRightTangent(int index, Vector3 position, bool setToLinear, bool mirror, Vector3 cachedLeftTangent, TangentMode cachedTangentMode) 181 { 182 var controlPoint = editablePath.GetPoint(index); 183 controlPoint.tangentMode = cachedTangentMode; 184 controlPoint.rightTangent = position; 185 controlPoint.mirrorLeft = true; 186 187 if (setToLinear) 188 { 189 controlPoint.rightTangent = controlPoint.position; 190 controlPoint.leftTangent = cachedLeftTangent; 191 } 192 else if (controlPoint.tangentMode == TangentMode.Continuous || mirror) 193 { 194 var magnitude = controlPoint.localLeftTangent.magnitude; 195 196 if (mirror) 197 magnitude = controlPoint.localRightTangent.magnitude; 198 199 controlPoint.localLeftTangent = magnitude * -controlPoint.localRightTangent.normalized; 200 } 201 202 editablePath.SetPoint(index, controlPoint); 203 editablePath.UpdateTangentMode(index); 204 } 205 206 public void ClearClosestPath() { } 207 public void AddClosestPath(float distance) { } 208 209 private Vector3 GetLeftTangentPosition(int index) 210 { 211 var isLinear = Mathf.Approximately(editablePath.GetPoint(index).localLeftTangent.sqrMagnitude, 0f); 212 213 if (isLinear) 214 { 215 var position = editablePath.GetPoint(index).position; 216 var prevPosition = PrevControlPoint(index).position; 217 218 return (1f / 3f) * (prevPosition - position) + position; 219 } 220 221 return editablePath.GetPoint(index).leftTangent; 222 } 223 224 private Vector3 GetRightTangentPosition(int index) 225 { 226 var isLinear = Mathf.Approximately(editablePath.GetPoint(index).localRightTangent.sqrMagnitude, 0f); 227 228 if (isLinear) 229 { 230 var position = editablePath.GetPoint(index).position; 231 var nextPosition = NextControlPoint(index).position; 232 233 return (1f / 3f) * (nextPosition - position) + position; 234 } 235 236 return editablePath.GetPoint(index).rightTangent; 237 } 238 239 private int NextIndex(int index) 240 { 241 return EditablePathUtility.Mod(index + 1, editablePath.pointCount); 242 } 243 244 private ControlPoint NextControlPoint(int index) 245 { 246 return editablePath.GetPoint(NextIndex(index)); 247 } 248 249 private int PrevIndex(int index) 250 { 251 return EditablePathUtility.Mod(index - 1, editablePath.pointCount); 252 } 253 254 private ControlPoint PrevControlPoint(int index) 255 { 256 return editablePath.GetPoint(PrevIndex(index)); 257 } 258 } 259}