No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SpriteMeshController.cs 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. using System;
  2. using Unity.Mathematics;
  3. using UnityEngine;
  4. namespace UnityEditor.U2D.Animation
  5. {
  6. internal class SpriteMeshController
  7. {
  8. const float k_SnapDistance = 10f;
  9. struct EdgeIntersectionResult
  10. {
  11. public int startVertexIndex;
  12. public int endVertexIndex;
  13. public int intersectEdgeIndex;
  14. public Vector2 endPosition;
  15. }
  16. SpriteMeshDataController m_SpriteMeshDataController = new();
  17. EdgeIntersectionResult m_EdgeIntersectionResult;
  18. public ISpriteMeshView spriteMeshView { get; set; }
  19. public BaseSpriteMeshData spriteMeshData { get; set; }
  20. public ISelection<int> selection { get; set; }
  21. public ICacheUndo cacheUndo { get; set; }
  22. public ITriangulator triangulator { get; set; }
  23. public bool disable { get; set; }
  24. public Rect frame { get; set; }
  25. public void OnGUI()
  26. {
  27. m_SpriteMeshDataController.spriteMeshData = spriteMeshData;
  28. Debug.Assert(spriteMeshView != null);
  29. Debug.Assert(spriteMeshData != null);
  30. Debug.Assert(selection != null);
  31. Debug.Assert(cacheUndo != null);
  32. ValidateSelectionValues();
  33. spriteMeshView.selection = selection;
  34. spriteMeshView.frame = frame;
  35. EditorGUI.BeginDisabledGroup(disable);
  36. spriteMeshView.BeginLayout();
  37. if (spriteMeshView.CanLayout())
  38. {
  39. LayoutVertices();
  40. LayoutEdges();
  41. }
  42. spriteMeshView.EndLayout();
  43. if (spriteMeshView.CanRepaint())
  44. {
  45. DrawEdges();
  46. if (GUI.enabled)
  47. {
  48. PreviewCreateVertex();
  49. PreviewCreateEdge();
  50. PreviewSplitEdge();
  51. }
  52. DrawVertices();
  53. }
  54. HandleSplitEdge();
  55. HandleCreateEdge();
  56. HandleCreateVertex();
  57. EditorGUI.EndDisabledGroup();
  58. HandleSelectVertex();
  59. HandleSelectEdge();
  60. EditorGUI.BeginDisabledGroup(disable);
  61. HandleMoveVertexAndEdge();
  62. EditorGUI.EndDisabledGroup();
  63. EditorGUI.BeginDisabledGroup(disable);
  64. HandleRemoveVertices();
  65. spriteMeshView.DoRepaint();
  66. EditorGUI.EndDisabledGroup();
  67. }
  68. void ValidateSelectionValues()
  69. {
  70. foreach (var index in selection.elements)
  71. {
  72. if (index >= spriteMeshData.vertexCount)
  73. {
  74. selection.Clear();
  75. break;
  76. }
  77. }
  78. }
  79. void LayoutVertices()
  80. {
  81. for (var i = 0; i < spriteMeshData.vertexCount; i++)
  82. {
  83. spriteMeshView.LayoutVertex(spriteMeshData.vertices[i], i);
  84. }
  85. }
  86. void LayoutEdges()
  87. {
  88. for (var i = 0; i < spriteMeshData.edges.Length; i++)
  89. {
  90. var edge = spriteMeshData.edges[i];
  91. var startPosition = spriteMeshData.vertices[edge.x];
  92. var endPosition = spriteMeshData.vertices[edge.y];
  93. spriteMeshView.LayoutEdge(startPosition, endPosition, i);
  94. }
  95. }
  96. void DrawEdges()
  97. {
  98. UpdateEdgeIntersection();
  99. spriteMeshView.BeginDrawEdges();
  100. for (var i = 0; i < spriteMeshData.edges.Length; ++i)
  101. {
  102. if (SkipDrawEdge(i))
  103. continue;
  104. var edge = spriteMeshData.edges[i];
  105. var startPosition = spriteMeshData.vertices[edge.x];
  106. var endPosition = spriteMeshData.vertices[edge.y];
  107. if (selection.Contains(edge.x) && selection.Contains(edge.y))
  108. spriteMeshView.DrawEdgeSelected(startPosition, endPosition);
  109. else
  110. spriteMeshView.DrawEdge(startPosition, endPosition);
  111. }
  112. if (spriteMeshView.IsActionActive(MeshEditorAction.SelectEdge))
  113. {
  114. var hoveredEdge = spriteMeshData.edges[spriteMeshView.hoveredEdge];
  115. var startPosition = spriteMeshData.vertices[hoveredEdge.x];
  116. var endPosition = spriteMeshData.vertices[hoveredEdge.y];
  117. spriteMeshView.DrawEdgeHovered(startPosition, endPosition);
  118. }
  119. spriteMeshView.EndDrawEdges();
  120. }
  121. bool SkipDrawEdge(int edgeIndex)
  122. {
  123. if (GUI.enabled == false)
  124. return false;
  125. return edgeIndex == -1 ||
  126. spriteMeshView.hoveredEdge == edgeIndex && spriteMeshView.IsActionActive(MeshEditorAction.SelectEdge) ||
  127. spriteMeshView.hoveredEdge == edgeIndex && spriteMeshView.IsActionActive(MeshEditorAction.CreateVertex) ||
  128. spriteMeshView.closestEdge == edgeIndex && spriteMeshView.IsActionActive(MeshEditorAction.SplitEdge) ||
  129. edgeIndex == m_EdgeIntersectionResult.intersectEdgeIndex && spriteMeshView.IsActionActive(MeshEditorAction.CreateEdge);
  130. }
  131. void PreviewCreateVertex()
  132. {
  133. if (spriteMeshView.mode == SpriteMeshViewMode.CreateVertex &&
  134. spriteMeshView.IsActionActive(MeshEditorAction.CreateVertex))
  135. {
  136. var clampedMousePos = ClampToFrame(spriteMeshView.mouseWorldPosition);
  137. if (spriteMeshView.hoveredEdge != -1)
  138. {
  139. var edge = spriteMeshData.edges[spriteMeshView.hoveredEdge];
  140. spriteMeshView.BeginDrawEdges();
  141. spriteMeshView.DrawEdge(spriteMeshData.vertices[edge.x], clampedMousePos);
  142. spriteMeshView.DrawEdge(spriteMeshData.vertices[edge.y], clampedMousePos);
  143. spriteMeshView.EndDrawEdges();
  144. }
  145. spriteMeshView.DrawVertex(clampedMousePos);
  146. }
  147. }
  148. void PreviewCreateEdge()
  149. {
  150. if (!spriteMeshView.IsActionActive(MeshEditorAction.CreateEdge))
  151. return;
  152. spriteMeshView.BeginDrawEdges();
  153. spriteMeshView.DrawEdge(spriteMeshData.vertices[m_EdgeIntersectionResult.startVertexIndex], m_EdgeIntersectionResult.endPosition);
  154. if (m_EdgeIntersectionResult.intersectEdgeIndex != -1)
  155. {
  156. var intersectingEdge = spriteMeshData.edges[m_EdgeIntersectionResult.intersectEdgeIndex];
  157. spriteMeshView.DrawEdge(spriteMeshData.vertices[intersectingEdge.x], m_EdgeIntersectionResult.endPosition);
  158. spriteMeshView.DrawEdge(spriteMeshData.vertices[intersectingEdge.y], m_EdgeIntersectionResult.endPosition);
  159. }
  160. spriteMeshView.EndDrawEdges();
  161. if (m_EdgeIntersectionResult.endVertexIndex == -1)
  162. spriteMeshView.DrawVertex(m_EdgeIntersectionResult.endPosition);
  163. }
  164. void PreviewSplitEdge()
  165. {
  166. if (!spriteMeshView.IsActionActive(MeshEditorAction.SplitEdge))
  167. return;
  168. var clampedMousePos = ClampToFrame(spriteMeshView.mouseWorldPosition);
  169. var closestEdge = spriteMeshData.edges[spriteMeshView.closestEdge];
  170. spriteMeshView.BeginDrawEdges();
  171. spriteMeshView.DrawEdge(spriteMeshData.vertices[closestEdge.x], clampedMousePos);
  172. spriteMeshView.DrawEdge(spriteMeshData.vertices[closestEdge.y], clampedMousePos);
  173. spriteMeshView.EndDrawEdges();
  174. spriteMeshView.DrawVertex(clampedMousePos);
  175. }
  176. void DrawVertices()
  177. {
  178. for (var i = 0; i < spriteMeshData.vertexCount; i++)
  179. {
  180. var position = spriteMeshData.vertices[i];
  181. if (selection.Contains(i))
  182. spriteMeshView.DrawVertexSelected(position);
  183. else if (i == spriteMeshView.hoveredVertex && spriteMeshView.IsActionHot(MeshEditorAction.None))
  184. spriteMeshView.DrawVertexHovered(position);
  185. else
  186. spriteMeshView.DrawVertex(position);
  187. }
  188. }
  189. void HandleSelectVertex()
  190. {
  191. if (spriteMeshView.DoSelectVertex(out var additive))
  192. SelectVertex(spriteMeshView.hoveredVertex, additive);
  193. }
  194. void HandleSelectEdge()
  195. {
  196. if (spriteMeshView.DoSelectEdge(out var additive))
  197. SelectEdge(spriteMeshView.hoveredEdge, additive);
  198. }
  199. void HandleMoveVertexAndEdge()
  200. {
  201. if (selection.Count == 0)
  202. return;
  203. if (spriteMeshView.DoMoveVertex(out var finalDeltaPos) || spriteMeshView.DoMoveEdge(out finalDeltaPos))
  204. {
  205. var selectionArray = selection.elements;
  206. finalDeltaPos = MathUtility.MoveRectInsideFrame(CalculateRectFromSelection(), frame, finalDeltaPos);
  207. var movedVertexSelection = GetMovedVertexSelection(in selectionArray, spriteMeshData.vertices, finalDeltaPos);
  208. if (IsMovedEdgeIntersectingWithOtherEdge(in selectionArray, in movedVertexSelection, spriteMeshData.edges, spriteMeshData.vertices))
  209. return;
  210. if (IsMovedVertexIntersectingWithOutline(in selectionArray, in movedVertexSelection, spriteMeshData.outlineEdges, spriteMeshData.vertices))
  211. return;
  212. cacheUndo.BeginUndoOperation(TextContent.moveVertices);
  213. MoveSelectedVertices(in movedVertexSelection);
  214. }
  215. }
  216. void HandleCreateVertex()
  217. {
  218. if (spriteMeshView.DoCreateVertex())
  219. {
  220. var position = ClampToFrame(spriteMeshView.mouseWorldPosition);
  221. var edgeIndex = spriteMeshView.hoveredEdge;
  222. if (spriteMeshView.hoveredEdge != -1)
  223. CreateVertex(position, edgeIndex);
  224. else if (m_SpriteMeshDataController.FindTriangle(position, out var indices, out var barycentricCoords))
  225. CreateVertex(position, indices, barycentricCoords);
  226. }
  227. }
  228. void HandleSplitEdge()
  229. {
  230. if (spriteMeshView.DoSplitEdge())
  231. SplitEdge(ClampToFrame(spriteMeshView.mouseWorldPosition), spriteMeshView.closestEdge);
  232. }
  233. void HandleCreateEdge()
  234. {
  235. if (spriteMeshView.DoCreateEdge())
  236. {
  237. var clampedMousePosition = ClampToFrame(spriteMeshView.mouseWorldPosition);
  238. var edgeIntersectionResult = CalculateEdgeIntersection(selection.activeElement, spriteMeshView.hoveredVertex, spriteMeshView.hoveredEdge, clampedMousePosition);
  239. if (edgeIntersectionResult.endVertexIndex != -1)
  240. {
  241. CreateEdge(selection.activeElement, edgeIntersectionResult.endVertexIndex);
  242. }
  243. else
  244. {
  245. if (edgeIntersectionResult.intersectEdgeIndex != -1)
  246. {
  247. CreateVertex(edgeIntersectionResult.endPosition, edgeIntersectionResult.intersectEdgeIndex);
  248. CreateEdge(selection.activeElement, spriteMeshData.vertexCount - 1);
  249. }
  250. else if (m_SpriteMeshDataController.FindTriangle(edgeIntersectionResult.endPosition, out var indices, out var barycentricCoords))
  251. {
  252. CreateVertex(edgeIntersectionResult.endPosition, indices, barycentricCoords);
  253. CreateEdge(selection.activeElement, spriteMeshData.vertexCount - 1);
  254. }
  255. }
  256. }
  257. }
  258. void HandleRemoveVertices()
  259. {
  260. if (spriteMeshView.DoRemove())
  261. RemoveSelectedVertices();
  262. }
  263. void CreateVertex(Vector2 position, Vector3Int indices, Vector3 barycentricCoords)
  264. {
  265. var bw1 = spriteMeshData.vertexWeights[indices.x];
  266. var bw2 = spriteMeshData.vertexWeights[indices.y];
  267. var bw3 = spriteMeshData.vertexWeights[indices.z];
  268. var result = new EditableBoneWeight();
  269. foreach (var channel in bw1)
  270. {
  271. if (!channel.enabled)
  272. continue;
  273. var weight = channel.weight * barycentricCoords.x;
  274. if (weight > 0f)
  275. result.AddChannel(channel.boneIndex, weight, true);
  276. }
  277. foreach (var channel in bw2)
  278. {
  279. if (!channel.enabled)
  280. continue;
  281. var weight = channel.weight * barycentricCoords.y;
  282. if (weight > 0f)
  283. result.AddChannel(channel.boneIndex, weight, true);
  284. }
  285. foreach (var channel in bw3)
  286. {
  287. if (!channel.enabled)
  288. continue;
  289. var weight = channel.weight * barycentricCoords.z;
  290. if (weight > 0f)
  291. result.AddChannel(channel.boneIndex, weight, true);
  292. }
  293. result.UnifyChannelsWithSameBoneIndex();
  294. result.FilterChannels(0f);
  295. result.Clamp(4, true);
  296. var boneWeight = result.ToBoneWeight(true);
  297. cacheUndo.BeginUndoOperation(TextContent.createVertex);
  298. m_SpriteMeshDataController.CreateVertex(position, -1);
  299. spriteMeshData.vertexWeights[spriteMeshData.vertexCount - 1].SetFromBoneWeight(boneWeight);
  300. Triangulate();
  301. }
  302. void CreateVertex(Vector2 position, int edgeIndex)
  303. {
  304. var edge = spriteMeshData.edges[edgeIndex];
  305. var pos1 = spriteMeshData.vertices[edge.x];
  306. var pos2 = spriteMeshData.vertices[edge.y];
  307. var dir1 = (position - pos1);
  308. var dir2 = (pos2 - pos1);
  309. var t = Vector2.Dot(dir1, dir2.normalized) / dir2.magnitude;
  310. t = Mathf.Clamp01(t);
  311. var bw1 = spriteMeshData.vertexWeights[edge.x].ToBoneWeight(true);
  312. var bw2 = spriteMeshData.vertexWeights[edge.y].ToBoneWeight(true);
  313. var boneWeight = EditableBoneWeightUtility.Lerp(bw1, bw2, t);
  314. cacheUndo.BeginUndoOperation(TextContent.createVertex);
  315. m_SpriteMeshDataController.CreateVertex(position, edgeIndex);
  316. spriteMeshData.vertexWeights[spriteMeshData.vertexCount - 1].SetFromBoneWeight(boneWeight);
  317. Triangulate();
  318. }
  319. void SelectVertex(int index, bool additiveToggle)
  320. {
  321. if (index < 0)
  322. throw new ArgumentException("Index out of range");
  323. var selected = selection.Contains(index);
  324. if (selected)
  325. {
  326. if (additiveToggle)
  327. {
  328. cacheUndo.BeginUndoOperation(TextContent.selection);
  329. selection.Select(index, false);
  330. }
  331. }
  332. else
  333. {
  334. cacheUndo.BeginUndoOperation(TextContent.selection);
  335. if (!additiveToggle)
  336. ClearSelection();
  337. selection.Select(index, true);
  338. }
  339. cacheUndo.IncrementCurrentGroup();
  340. }
  341. void SelectEdge(int index, bool additiveToggle)
  342. {
  343. Debug.Assert(index >= 0);
  344. var edge = spriteMeshData.edges[index];
  345. cacheUndo.BeginUndoOperation(TextContent.selection);
  346. var selected = selection.Contains(edge.x) && selection.Contains(edge.y);
  347. if (selected)
  348. {
  349. if (additiveToggle)
  350. {
  351. selection.Select(edge.x, false);
  352. selection.Select(edge.y, false);
  353. }
  354. }
  355. else
  356. {
  357. if (!additiveToggle)
  358. ClearSelection();
  359. selection.Select(edge.x, true);
  360. selection.Select(edge.y, true);
  361. }
  362. cacheUndo.IncrementCurrentGroup();
  363. }
  364. void ClearSelection()
  365. {
  366. cacheUndo.BeginUndoOperation(TextContent.selection);
  367. selection.Clear();
  368. }
  369. void MoveSelectedVertices(in Vector2[] movedVertices)
  370. {
  371. for (var i = 0; i < selection.Count; ++i)
  372. {
  373. var index = selection.elements[i];
  374. spriteMeshData.vertices[index] = movedVertices[i];
  375. }
  376. Triangulate();
  377. }
  378. void CreateEdge(int fromVertexIndex, int toVertexIndex)
  379. {
  380. cacheUndo.BeginUndoOperation(TextContent.createEdge);
  381. m_SpriteMeshDataController.CreateEdge(fromVertexIndex, toVertexIndex);
  382. Triangulate();
  383. ClearSelection();
  384. selection.Select(toVertexIndex, true);
  385. cacheUndo.IncrementCurrentGroup();
  386. }
  387. void SplitEdge(Vector2 position, int edgeIndex)
  388. {
  389. cacheUndo.BeginUndoOperation(TextContent.splitEdge);
  390. CreateVertex(position, edgeIndex);
  391. cacheUndo.IncrementCurrentGroup();
  392. }
  393. bool IsEdgeSelected()
  394. {
  395. if (selection.Count != 2)
  396. return false;
  397. var indices = selection.elements;
  398. var index1 = indices[0];
  399. var index2 = indices[1];
  400. var edge = new int2(index1, index2);
  401. return spriteMeshData.edges.ContainsAny(edge);
  402. }
  403. void RemoveSelectedVertices()
  404. {
  405. cacheUndo.BeginUndoOperation(IsEdgeSelected() ? TextContent.removeEdge : TextContent.removeVertices);
  406. var verticesToRemove = selection.elements;
  407. var noOfVertsToDelete = verticesToRemove.Length;
  408. var noOfVertsInMesh = m_SpriteMeshDataController.spriteMeshData.vertexCount;
  409. var shouldClearMesh = (noOfVertsInMesh - noOfVertsToDelete) < 3;
  410. if (shouldClearMesh)
  411. {
  412. m_SpriteMeshDataController.spriteMeshData.Clear();
  413. m_SpriteMeshDataController.CreateQuad();
  414. }
  415. else
  416. m_SpriteMeshDataController.RemoveVertex(verticesToRemove);
  417. Triangulate();
  418. selection.Clear();
  419. }
  420. void Triangulate()
  421. {
  422. m_SpriteMeshDataController.Triangulate(triangulator);
  423. m_SpriteMeshDataController.SortTrianglesByDepth();
  424. }
  425. Vector2 ClampToFrame(Vector2 position)
  426. {
  427. return MathUtility.ClampPositionToRect(position, frame);
  428. }
  429. Rect CalculateRectFromSelection()
  430. {
  431. var rect = new Rect();
  432. var min = new Vector2(float.MaxValue, float.MaxValue);
  433. var max = new Vector2(float.MinValue, float.MinValue);
  434. var indices = selection.elements;
  435. foreach (var index in indices)
  436. {
  437. var v = spriteMeshData.vertices[index];
  438. min.x = Mathf.Min(min.x, v.x);
  439. min.y = Mathf.Min(min.y, v.y);
  440. max.x = Mathf.Max(max.x, v.x);
  441. max.y = Mathf.Max(max.y, v.y);
  442. }
  443. rect.min = min;
  444. rect.max = max;
  445. return rect;
  446. }
  447. void UpdateEdgeIntersection()
  448. {
  449. if (selection.Count == 1)
  450. m_EdgeIntersectionResult = CalculateEdgeIntersection(selection.activeElement, spriteMeshView.hoveredVertex, spriteMeshView.hoveredEdge, ClampToFrame(spriteMeshView.mouseWorldPosition));
  451. }
  452. EdgeIntersectionResult CalculateEdgeIntersection(int vertexIndex, int hoveredVertexIndex, int hoveredEdgeIndex, Vector2 targetPosition)
  453. {
  454. Debug.Assert(vertexIndex >= 0);
  455. var edgeIntersection = new EdgeIntersectionResult
  456. {
  457. startVertexIndex = vertexIndex,
  458. endVertexIndex = hoveredVertexIndex,
  459. endPosition = targetPosition,
  460. intersectEdgeIndex = -1
  461. };
  462. var startPoint = spriteMeshData.vertices[edgeIntersection.startVertexIndex];
  463. var intersectsEdge = false;
  464. var lastIntersectingEdgeIndex = -1;
  465. do
  466. {
  467. lastIntersectingEdgeIndex = edgeIntersection.intersectEdgeIndex;
  468. if (intersectsEdge)
  469. {
  470. var dir = edgeIntersection.endPosition - startPoint;
  471. edgeIntersection.endPosition += dir.normalized * 10f;
  472. }
  473. intersectsEdge = SegmentIntersectsEdge(startPoint, edgeIntersection.endPosition, vertexIndex, ref edgeIntersection.endPosition, out edgeIntersection.intersectEdgeIndex);
  474. //if we are hovering a vertex and intersect an edge indexing it we forget about the intersection
  475. var edges = spriteMeshData.edges;
  476. var edge = intersectsEdge ? edges[edgeIntersection.intersectEdgeIndex] : default;
  477. if (intersectsEdge && (edge.x == edgeIntersection.endVertexIndex || edge.y == edgeIntersection.endVertexIndex))
  478. {
  479. edgeIntersection.intersectEdgeIndex = -1;
  480. intersectsEdge = false;
  481. edgeIntersection.endPosition = spriteMeshData.vertices[edgeIntersection.endVertexIndex];
  482. }
  483. if (intersectsEdge)
  484. {
  485. edgeIntersection.endVertexIndex = -1;
  486. var intersectingEdge = spriteMeshData.edges[edgeIntersection.intersectEdgeIndex];
  487. var newPointScreen = spriteMeshView.WorldToScreen(edgeIntersection.endPosition);
  488. var edgeV1 = spriteMeshView.WorldToScreen(spriteMeshData.vertices[intersectingEdge.x]);
  489. var edgeV2 = spriteMeshView.WorldToScreen(spriteMeshData.vertices[intersectingEdge.y]);
  490. if ((newPointScreen - edgeV1).magnitude <= k_SnapDistance)
  491. edgeIntersection.endVertexIndex = intersectingEdge.x;
  492. else if ((newPointScreen - edgeV2).magnitude <= k_SnapDistance)
  493. edgeIntersection.endVertexIndex = intersectingEdge.y;
  494. if (edgeIntersection.endVertexIndex != -1)
  495. {
  496. edgeIntersection.intersectEdgeIndex = -1;
  497. intersectsEdge = false;
  498. edgeIntersection.endPosition = spriteMeshData.vertices[edgeIntersection.endVertexIndex];
  499. }
  500. }
  501. } while (intersectsEdge && lastIntersectingEdgeIndex != edgeIntersection.intersectEdgeIndex);
  502. edgeIntersection.intersectEdgeIndex = intersectsEdge ? edgeIntersection.intersectEdgeIndex : hoveredEdgeIndex;
  503. if (edgeIntersection.endVertexIndex != -1 && !intersectsEdge)
  504. edgeIntersection.endPosition = spriteMeshData.vertices[edgeIntersection.endVertexIndex];
  505. return edgeIntersection;
  506. }
  507. bool SegmentIntersectsEdge(Vector2 p1, Vector2 p2, int ignoreIndex, ref Vector2 point, out int intersectingEdgeIndex)
  508. {
  509. intersectingEdgeIndex = -1;
  510. var sqrDistance = float.MaxValue;
  511. for (var i = 0; i < spriteMeshData.edges.Length; i++)
  512. {
  513. var edge = spriteMeshData.edges[i];
  514. var v1 = spriteMeshData.vertices[edge.x];
  515. var v2 = spriteMeshData.vertices[edge.y];
  516. var pointTmp = Vector2.zero;
  517. if (edge.x != ignoreIndex && edge.y != ignoreIndex &&
  518. MathUtility.SegmentIntersection(p1, p2, v1, v2, ref pointTmp))
  519. {
  520. var sqrMagnitude = (pointTmp - p1).sqrMagnitude;
  521. if (sqrMagnitude < sqrDistance)
  522. {
  523. sqrDistance = sqrMagnitude;
  524. intersectingEdgeIndex = i;
  525. point = pointTmp;
  526. }
  527. }
  528. }
  529. return intersectingEdgeIndex != -1;
  530. }
  531. static Vector2[] GetMovedVertexSelection(in int[] selection, in Vector2[] vertices, Vector2 deltaPosition)
  532. {
  533. var movedVertices = new Vector2[selection.Length];
  534. for (var i = 0; i < selection.Length; i++)
  535. {
  536. var index = selection[i];
  537. movedVertices[i] = vertices[index] + deltaPosition;
  538. }
  539. return movedVertices;
  540. }
  541. static bool IsMovedEdgeIntersectingWithOtherEdge(in int[] selection, in Vector2[] movedVertices, in int2[] meshEdges, in Vector2[] meshVertices)
  542. {
  543. var edgeCount = meshEdges.Length;
  544. var edgeIntersectionPoint = Vector2.zero;
  545. for (var i = 0; i < edgeCount; i++)
  546. {
  547. var selectionIndex = FindSelectionIndexFromEdge(selection, meshEdges[i]);
  548. if (selectionIndex.x == -1 && selectionIndex.y == -1)
  549. continue;
  550. var edgeStart = selectionIndex.x != -1 ? movedVertices[selectionIndex.x] : meshVertices[meshEdges[i].x];
  551. var edgeEnd = selectionIndex.y != -1 ? movedVertices[selectionIndex.y] : meshVertices[meshEdges[i].y];
  552. for (var o = 0; o < edgeCount; o++)
  553. {
  554. if (o == i)
  555. continue;
  556. if (meshEdges[i].x == meshEdges[o].x || meshEdges[i].y == meshEdges[o].x ||
  557. meshEdges[i].x == meshEdges[o].y || meshEdges[i].y == meshEdges[o].y)
  558. continue;
  559. var otherSelectionIndex = FindSelectionIndexFromEdge(in selection, meshEdges[o]);
  560. var otherEdgeStart = otherSelectionIndex.x != -1 ? movedVertices[otherSelectionIndex.x] : meshVertices[meshEdges[o].x];
  561. var otherEdgeEnd = otherSelectionIndex.y != -1 ? movedVertices[otherSelectionIndex.y] : meshVertices[meshEdges[o].y];
  562. if (MathUtility.SegmentIntersection(edgeStart, edgeEnd, otherEdgeStart, otherEdgeEnd, ref edgeIntersectionPoint))
  563. return true;
  564. }
  565. }
  566. return false;
  567. }
  568. static int2 FindSelectionIndexFromEdge(in int[] selection, int2 edge)
  569. {
  570. var selectionIndex = new int2(-1, -1);
  571. for (var m = 0; m < selection.Length; ++m)
  572. {
  573. if (selection[m] == edge.x)
  574. {
  575. selectionIndex.x = m;
  576. break;
  577. }
  578. if (selection[m] == edge.y)
  579. {
  580. selectionIndex.y = m;
  581. break;
  582. }
  583. }
  584. return selectionIndex;
  585. }
  586. static bool IsMovedVertexIntersectingWithOutline(in int[] selection, in Vector2[] movedVertices, in int2[] outlineEdges, in Vector2[] meshVertices)
  587. {
  588. var edgeIntersectionPoint = Vector2.zero;
  589. for (var i = 0; i < selection.Length; ++i)
  590. {
  591. var edgeStart = meshVertices[selection[i]];
  592. var edgeEnd = movedVertices[i];
  593. for (var m = 0; m < outlineEdges.Length; ++m)
  594. {
  595. if (selection[i] == outlineEdges[m].x || selection[i] == outlineEdges[m].y)
  596. continue;
  597. var otherSelectionIndex = FindSelectionIndexFromEdge(in selection, outlineEdges[m]);
  598. var otherEdgeStart = otherSelectionIndex.x != -1 ? movedVertices[otherSelectionIndex.x] : meshVertices[outlineEdges[m].x];
  599. var otherEdgeEnd = otherSelectionIndex.y != -1 ? movedVertices[otherSelectionIndex.y] : meshVertices[outlineEdges[m].y];
  600. if (MathUtility.SegmentIntersection(edgeStart, edgeEnd, otherEdgeStart, otherEdgeEnd, ref edgeIntersectionPoint))
  601. return true;
  602. }
  603. }
  604. return false;
  605. }
  606. }
  607. }