SpriteMeshController.cs 24 KB

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