暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

SpriteMeshDataController.cs 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. using System;
  2. using System.Collections.Generic;
  3. using Unity.Mathematics;
  4. using UnityEngine;
  5. using UnityEditor.U2D.Sprites;
  6. using Unity.Jobs;
  7. using Unity.Collections;
  8. namespace UnityEditor.U2D.Animation
  9. {
  10. internal struct WeightedTriangle : IComparable<WeightedTriangle>
  11. {
  12. public int p1;
  13. public int p2;
  14. public int p3;
  15. public float weight;
  16. public int CompareTo(WeightedTriangle other)
  17. {
  18. return weight.CompareTo(other.weight);
  19. }
  20. }
  21. internal struct SpriteJobData
  22. {
  23. public BaseSpriteMeshData spriteMesh;
  24. public NativeArray<float2> vertices;
  25. public NativeArray<int2> edges;
  26. public NativeArray<int> indices;
  27. public NativeArray<BoneWeight> weights;
  28. public NativeArray<int4> result;
  29. };
  30. internal class SpriteMeshDataController
  31. {
  32. public BaseSpriteMeshData spriteMeshData;
  33. float2[] m_VerticesTemp = new float2[0];
  34. int2[] m_EdgesTemp = new int2[0];
  35. public void CreateVertex(Vector2 position)
  36. {
  37. CreateVertex(position, -1);
  38. }
  39. public void CreateVertex(Vector2 position, int edgeIndex)
  40. {
  41. Debug.Assert(spriteMeshData != null, "Assert failed. Expected: spriteMeshData != null. Actual: spriteMeshData == null");
  42. spriteMeshData.AddVertex(position, default(BoneWeight));
  43. if (edgeIndex != -1)
  44. {
  45. var edge = spriteMeshData.edges[edgeIndex];
  46. RemoveEdge(edge);
  47. CreateEdge(edge.x, spriteMeshData.vertexCount - 1);
  48. CreateEdge(edge.y, spriteMeshData.vertexCount - 1);
  49. }
  50. }
  51. public void CreateEdge(int index1, int index2)
  52. {
  53. Debug.Assert(spriteMeshData != null, "Assert failed. Expected: spriteMeshData != null. Actual: spriteMeshData == null");
  54. Debug.Assert(index1 >= 0, $"Assert failed. Expected: index1 >= 0. Actual: index1 == {index1}");
  55. Debug.Assert(index2 >= 0, $"Assert failed. Expected: index2 >= 0. Actual: index2 == {index2}");
  56. Debug.Assert(index1 < spriteMeshData.vertexCount, $"Assert failed. Expected: index1 < spriteMeshData.vertexCount. Actual: index1 == {index1} spriteMeshData.vertexCount == {spriteMeshData.vertexCount}");
  57. Debug.Assert(index2 < spriteMeshData.vertexCount, $"Assert failed. Expected: index2 < spriteMeshData.vertexCount. Actual: index2 == {index2} spriteMeshData.vertexCount == {spriteMeshData.vertexCount}");
  58. Debug.Assert(index1 != index2, $"Assert failed. Expected: index1 != index2. Actual: index1 == {index1} index2 == {index2}");
  59. var newEdge = new int2(index1, index2);
  60. if (!spriteMeshData.edges.ContainsAny(newEdge))
  61. {
  62. var listOfEdges = new List<int2>(spriteMeshData.edges)
  63. {
  64. newEdge
  65. };
  66. spriteMeshData.SetEdges(listOfEdges.ToArray());
  67. }
  68. }
  69. public void RemoveVertex(int index)
  70. {
  71. Debug.Assert(spriteMeshData != null);
  72. //We need to delete the edges that reference the index
  73. if (FindEdgesContainsIndex(index, out var edgesWithIndex))
  74. {
  75. //If there are 2 edges referencing the same index we are removing, we can create a new one that connects the endpoints ("Unsplit").
  76. if (edgesWithIndex.Count == 2)
  77. {
  78. var first = edgesWithIndex[0];
  79. var second = edgesWithIndex[1];
  80. int index1 = first.x != index ? first.x : first.y;
  81. int index2 = second.x != index ? second.x : second.y;
  82. CreateEdge(index1, index2);
  83. }
  84. //remove found edges
  85. for (int i = 0; i < edgesWithIndex.Count; i++)
  86. {
  87. RemoveEdge(edgesWithIndex[i]);
  88. }
  89. }
  90. //Fix indices in edges greater than the one we are removing
  91. for (int i = 0; i < spriteMeshData.edges.Length; i++)
  92. {
  93. var edge = spriteMeshData.edges[i];
  94. if (edge.x > index)
  95. edge.x--;
  96. if (edge.y > index)
  97. edge.y--;
  98. spriteMeshData.edges[i] = edge;
  99. }
  100. spriteMeshData.RemoveVertex(index);
  101. }
  102. public void RemoveVertex(IEnumerable<int> indices)
  103. {
  104. var sortedIndexList = new List<int>(indices);
  105. if (sortedIndexList.Count == 0)
  106. return;
  107. sortedIndexList.Sort();
  108. for (var i = sortedIndexList.Count - 1; i >= 0; --i)
  109. {
  110. RemoveVertex(sortedIndexList[i]);
  111. }
  112. }
  113. void RemoveEdge(int2 edge)
  114. {
  115. Debug.Assert(spriteMeshData != null);
  116. var listOfEdges = new List<int2>(spriteMeshData.edges);
  117. listOfEdges.Remove(edge);
  118. spriteMeshData.SetEdges(listOfEdges.ToArray());
  119. }
  120. bool FindEdgesContainsIndex(int index, out List<int2> result)
  121. {
  122. Debug.Assert(spriteMeshData != null);
  123. bool found = false;
  124. result = new List<int2>();
  125. for (int i = 0; i < spriteMeshData.edges.Length; ++i)
  126. {
  127. var edge = spriteMeshData.edges[i];
  128. if (edge.x == index || edge.y == index)
  129. {
  130. found = true;
  131. result.Add(edge);
  132. }
  133. }
  134. return found;
  135. }
  136. public void CreateQuad()
  137. {
  138. var frame = new Rect(Vector2.zero, spriteMeshData.frame.size);
  139. var verts = new Vector2[]
  140. {
  141. new Vector2(frame.xMin, frame.yMin),
  142. new Vector2(frame.xMax, frame.yMin),
  143. new Vector2(frame.xMin, frame.yMax),
  144. new Vector2(frame.xMax, frame.yMax)
  145. };
  146. for(var i = 0; i < verts.Length; ++i)
  147. CreateVertex(verts[i]);
  148. var tris = new int[]
  149. {
  150. 0, 2, 3, 1
  151. };
  152. for (var i = 0; i < tris.Length; ++i)
  153. {
  154. var n = (i + 1) % tris.Length;
  155. CreateEdge(tris[i], tris[n]);
  156. }
  157. }
  158. public JobHandle TriangulateJob(ITriangulator triangulator, SpriteJobData spriteData)
  159. {
  160. Debug.Assert(spriteMeshData != null);
  161. Debug.Assert(triangulator != null);
  162. FillMeshDataContainers(out m_VerticesTemp, out m_EdgesTemp, out var weightData, out var hasWeightData);
  163. return triangulator.ScheduleTriangulate(in m_VerticesTemp, in m_EdgesTemp, ref spriteData.vertices, ref spriteData.indices, ref spriteData.edges, ref spriteData.result);
  164. }
  165. public void Triangulate(ITriangulator triangulator)
  166. {
  167. Debug.Assert(spriteMeshData != null);
  168. Debug.Assert(triangulator != null);
  169. FillMeshDataContainers(out m_VerticesTemp, out m_EdgesTemp, out var weightData, out var hasWeightData);
  170. triangulator.Triangulate(ref m_EdgesTemp, ref m_VerticesTemp, out var indices);
  171. if (m_VerticesTemp.Length == 0 || indices.Length == 0)
  172. {
  173. spriteMeshData.Clear();
  174. CreateQuad();
  175. FillMeshDataContainers(out m_VerticesTemp, out m_EdgesTemp, out weightData, out hasWeightData);
  176. triangulator.Triangulate(ref m_EdgesTemp, ref m_VerticesTemp, out indices);
  177. }
  178. spriteMeshData.Clear();
  179. spriteMeshData.SetIndices(indices);
  180. spriteMeshData.SetEdges(m_EdgesTemp);
  181. var hasNewVertices = m_VerticesTemp.Length != weightData.Length;
  182. for (var i = 0; i < m_VerticesTemp.Length; ++i)
  183. {
  184. var boneWeight = default(BoneWeight);
  185. if (!hasNewVertices)
  186. boneWeight = weightData[i].ToBoneWeight(true);
  187. spriteMeshData.AddVertex(m_VerticesTemp[i], boneWeight);
  188. }
  189. if(hasNewVertices && hasWeightData)
  190. CalculateWeights(new BoundedBiharmonicWeightsGenerator(), null, 0.01f);
  191. }
  192. void FillMeshDataContainers(out float2[] vertices, out int2[] edges, out EditableBoneWeight[] weightData, out bool hasWeightData)
  193. {
  194. edges = spriteMeshData.edges;
  195. vertices = EditorUtilities.ToFloat2(spriteMeshData.vertices);
  196. weightData = new EditableBoneWeight[spriteMeshData.vertexWeights.Length];
  197. Array.Copy(spriteMeshData.vertexWeights, weightData, weightData.Length);
  198. hasWeightData = false;
  199. if (weightData.Length > 0 && weightData[0] != default)
  200. hasWeightData = true;
  201. }
  202. public JobHandle Subdivide(ITriangulator triangulator, SpriteJobData spriteData, float largestAreaFactor, float areaThreshold)
  203. {
  204. Debug.Assert(spriteMeshData != null);
  205. Debug.Assert(triangulator != null);
  206. m_EdgesTemp = spriteMeshData.edges;
  207. m_VerticesTemp = EditorUtilities.ToFloat2(spriteMeshData.vertices);
  208. try
  209. {
  210. triangulator.Tessellate(0f, 0f, 0f, largestAreaFactor, areaThreshold, 100, ref m_VerticesTemp, ref m_EdgesTemp, out var indices);
  211. spriteMeshData.Clear();
  212. for (var i = 0; i < m_VerticesTemp.Length; ++i)
  213. spriteMeshData.AddVertex(m_VerticesTemp[i], default(BoneWeight));
  214. spriteMeshData.SetIndices(indices);
  215. spriteMeshData.SetEdges(m_EdgesTemp);
  216. }
  217. catch (Exception) { }
  218. return default(JobHandle);
  219. }
  220. public void ClearWeights(ISelection<int> selection)
  221. {
  222. Debug.Assert(spriteMeshData != null);
  223. for (var i = 0; i < spriteMeshData.vertexCount; ++i)
  224. if (selection == null || (selection.Count == 0 || selection.Contains(i)))
  225. spriteMeshData.vertexWeights[i].SetFromBoneWeight(default(BoneWeight));
  226. }
  227. public void OutlineFromAlpha(IOutlineGenerator outlineGenerator, ITextureDataProvider textureDataProvider, float outlineDetail, byte alphaTolerance)
  228. {
  229. Debug.Assert(spriteMeshData != null, "Assert failed. Expected: spriteMeshData != null. Actual: spriteMeshData == null");
  230. Debug.Assert(textureDataProvider != null, "Assert failed. Expected: textureDataProvider != null. Actual: textureDataProvider == null");
  231. Debug.Assert(textureDataProvider.texture != null, "Assert failed. Expected: textureDataProvider.texture != null. Actual: textureDataProvider.texture == null");
  232. int width, height;
  233. textureDataProvider.GetTextureActualWidthAndHeight(out width, out height);
  234. var scale = new Vector2(textureDataProvider.texture.width / (float)width, textureDataProvider.texture.height / (float)height);
  235. var scaleInv = new Vector2(1f / scale.x, 1f / scale.y);
  236. var rectOffset = spriteMeshData.frame.size * 0.5f;
  237. var scaledRect = spriteMeshData.frame;
  238. scaledRect.min = Vector2.Scale(scaledRect.min, scale);
  239. scaledRect.max = Vector2.Scale(scaledRect.max, scale);
  240. spriteMeshData.Clear();
  241. outlineGenerator.GenerateOutline(textureDataProvider, scaledRect, outlineDetail, alphaTolerance, false, out var paths);
  242. var vertexIndexBase = 0;
  243. var vertices = new List<Vector2>(spriteMeshData.vertices);
  244. var edges = new List<int2>(spriteMeshData.edges);
  245. for (var i = 0; i < paths.Length; ++i)
  246. {
  247. var numPathVertices = paths[i].Length;
  248. for (var j = 0; j <= numPathVertices; j++)
  249. {
  250. if (j < numPathVertices)
  251. vertices.Add(Vector2.Scale(paths[i][j], scaleInv) + rectOffset);
  252. if (j > 0)
  253. edges.Add(new int2(vertexIndexBase + j - 1, vertexIndexBase + j % numPathVertices));
  254. }
  255. vertexIndexBase += numPathVertices;
  256. }
  257. var vertexWeights = new EditableBoneWeight[vertices.Count];
  258. for (var i = 0; i < vertexWeights.Length; ++i)
  259. vertexWeights[i] = new EditableBoneWeight();
  260. spriteMeshData.SetVertices(vertices.ToArray(), vertexWeights);
  261. spriteMeshData.SetEdges(edges.ToArray());
  262. }
  263. public void NormalizeWeights(ISelection<int> selection)
  264. {
  265. Debug.Assert(spriteMeshData != null);
  266. for (var i = 0; i < spriteMeshData.vertexCount; ++i)
  267. if (selection == null || (selection.Count == 0 || selection.Contains(i)))
  268. spriteMeshData.vertexWeights[i].Normalize();
  269. }
  270. public JobHandle CalculateWeightsJob(IWeightsGenerator weightsGenerator, ISelection<int> selection, float filterTolerance, SpriteJobData sd)
  271. {
  272. Debug.Assert(spriteMeshData != null);
  273. GetControlPoints(out var controlPoints, out var bones, out var pins);
  274. var vertices = EditorUtilities.ToFloat2(spriteMeshData.vertices);
  275. var indices = spriteMeshData.indices;
  276. var edges = spriteMeshData.edges;
  277. return weightsGenerator.CalculateJob(spriteMeshData.spriteName, in vertices, in indices, in edges, in controlPoints, in bones, in pins, sd);
  278. }
  279. public void CalculateWeights(IWeightsGenerator weightsGenerator, ISelection<int> selection, float filterTolerance)
  280. {
  281. Debug.Assert(spriteMeshData != null);
  282. GetControlPoints(out var controlPoints, out var bones, out var pins);
  283. var vertices = EditorUtilities.ToFloat2(spriteMeshData.vertices);
  284. var indices = spriteMeshData.indices;
  285. var edges = spriteMeshData.edges;
  286. var boneWeights = weightsGenerator.Calculate(spriteMeshData.spriteName, in vertices, in indices, in edges, in controlPoints, in bones, in pins);
  287. Debug.Assert(boneWeights.Length == spriteMeshData.vertexCount);
  288. for (var i = 0; i < spriteMeshData.vertexCount; ++i)
  289. {
  290. if (selection == null || (selection.Count == 0 || selection.Contains(i)))
  291. {
  292. var editableBoneWeight = EditableBoneWeightUtility.CreateFromBoneWeight(boneWeights[i]);
  293. if (filterTolerance > 0f)
  294. {
  295. editableBoneWeight.FilterChannels(filterTolerance);
  296. editableBoneWeight.Normalize();
  297. }
  298. spriteMeshData.vertexWeights[i] = editableBoneWeight;
  299. }
  300. }
  301. }
  302. public void CalculateWeightsSafe(IWeightsGenerator weightsGenerator, ISelection<int> selection, float filterTolerance)
  303. {
  304. var tempSelection = new IndexedSelection();
  305. var vertexSelector = new GenericVertexSelector();
  306. vertexSelector.spriteMeshData = spriteMeshData;
  307. vertexSelector.selection = tempSelection;
  308. vertexSelector.SelectionCallback = (int i) => {
  309. return spriteMeshData.vertexWeights[i].Sum() == 0f && (selection == null || selection.Count == 0 || selection.Contains(i));
  310. };
  311. vertexSelector.Select();
  312. if (tempSelection.Count > 0)
  313. CalculateWeights(weightsGenerator, tempSelection, filterTolerance);
  314. }
  315. public void SmoothWeights(int iterations, ISelection<int> selection)
  316. {
  317. var boneWeights = new BoneWeight[spriteMeshData.vertexCount];
  318. for (var i = 0; i < spriteMeshData.vertexCount; i++)
  319. boneWeights[i] = spriteMeshData.vertexWeights[i].ToBoneWeight(false);
  320. SmoothingUtility.SmoothWeights(boneWeights, spriteMeshData.indices, spriteMeshData.boneCount, iterations, out var smoothedWeights);
  321. for (var i = 0; i < spriteMeshData.vertexCount; i++)
  322. if (selection == null || (selection.Count == 0 || selection.Contains(i)))
  323. spriteMeshData.vertexWeights[i].SetFromBoneWeight(smoothedWeights[i]);
  324. }
  325. public bool FindTriangle(Vector2 point, out Vector3Int indices, out Vector3 barycentricCoords)
  326. {
  327. Debug.Assert(spriteMeshData != null);
  328. indices = Vector3Int.zero;
  329. barycentricCoords = Vector3.zero;
  330. if (spriteMeshData.indices.Length < 3)
  331. return false;
  332. var triangleCount = spriteMeshData.indices.Length / 3;
  333. for (var i = 0; i < triangleCount; ++i)
  334. {
  335. indices.x = spriteMeshData.indices[i * 3];
  336. indices.y = spriteMeshData.indices[i * 3 + 1];
  337. indices.z = spriteMeshData.indices[i * 3 + 2];
  338. MathUtility.Barycentric(
  339. point,
  340. spriteMeshData.vertices[indices.x],
  341. spriteMeshData.vertices[indices.y],
  342. spriteMeshData.vertices[indices.z],
  343. out barycentricCoords);
  344. if (barycentricCoords.x >= 0f && barycentricCoords.y >= 0f && barycentricCoords.z >= 0f)
  345. return true;
  346. }
  347. return false;
  348. }
  349. List<float> m_VertexOrderList = new List<float>(1000);
  350. List<WeightedTriangle> m_WeightedTriangles = new List<WeightedTriangle>(1000);
  351. public void SortTrianglesByDepth()
  352. {
  353. Debug.Assert(spriteMeshData != null);
  354. if (spriteMeshData.boneCount == 0)
  355. return;
  356. m_VertexOrderList.Clear();
  357. m_WeightedTriangles.Clear();
  358. for (var i = 0; i < spriteMeshData.vertexCount; i++)
  359. {
  360. var vertexOrder = 0f;
  361. var boneWeight = spriteMeshData.vertexWeights[i];
  362. for (var j = 0; j < boneWeight.Count; ++j)
  363. vertexOrder += spriteMeshData.GetBoneDepth(boneWeight[j].boneIndex) * boneWeight[j].weight;
  364. m_VertexOrderList.Add(vertexOrder);
  365. }
  366. for (var i = 0; i < spriteMeshData.indices.Length; i += 3)
  367. {
  368. var p1 = spriteMeshData.indices[i];
  369. var p2 = spriteMeshData.indices[i + 1];
  370. var p3 = spriteMeshData.indices[i + 2];
  371. var weight = (m_VertexOrderList[p1] + m_VertexOrderList[p2] + m_VertexOrderList[p3]) / 3f;
  372. m_WeightedTriangles.Add(new WeightedTriangle() { p1 = p1, p2 = p2, p3 = p3, weight = weight });
  373. }
  374. m_WeightedTriangles.Sort();
  375. var newIndices = new int[m_WeightedTriangles.Count * 3];
  376. for (var i = 0; i < m_WeightedTriangles.Count; ++i)
  377. {
  378. var triangle = m_WeightedTriangles[i];
  379. var indexCount = i * 3;
  380. newIndices[indexCount] = triangle.p1;
  381. newIndices[indexCount + 1] = triangle.p2;
  382. newIndices[indexCount + 2] = triangle.p3;
  383. }
  384. spriteMeshData.SetIndices(newIndices);
  385. }
  386. public void GetMultiEditChannelData(ISelection<int> selection, int channel,
  387. out bool enabled, out int boneIndex, out float weight,
  388. out bool isEnabledMixed, out bool isBoneIndexMixed, out bool isWeightMixed)
  389. {
  390. Debug.Assert(spriteMeshData != null);
  391. if (selection == null)
  392. throw new ArgumentNullException("selection is null");
  393. var first = true;
  394. enabled = false;
  395. boneIndex = -1;
  396. weight = 0f;
  397. isEnabledMixed = false;
  398. isBoneIndexMixed = false;
  399. isWeightMixed = false;
  400. var indices = selection.elements;
  401. foreach (var i in indices)
  402. {
  403. var editableBoneWeight = spriteMeshData.vertexWeights[i];
  404. if (first)
  405. {
  406. enabled = editableBoneWeight[channel].enabled;
  407. boneIndex = editableBoneWeight[channel].boneIndex;
  408. weight = editableBoneWeight[channel].weight;
  409. first = false;
  410. }
  411. else
  412. {
  413. if (enabled != editableBoneWeight[channel].enabled)
  414. {
  415. isEnabledMixed = true;
  416. enabled = false;
  417. }
  418. if (boneIndex != editableBoneWeight[channel].boneIndex)
  419. {
  420. isBoneIndexMixed = true;
  421. boneIndex = -1;
  422. }
  423. if (Mathf.Abs(weight - editableBoneWeight[channel].weight) > Mathf.Epsilon)
  424. {
  425. isWeightMixed = true;
  426. weight = 0f;
  427. }
  428. }
  429. }
  430. }
  431. public void SetMultiEditChannelData(ISelection<int> selection, int channel,
  432. bool oldEnabled, bool newEnabled, int oldBoneIndex, int newBoneIndex, float oldWeight, float newWeight)
  433. {
  434. Debug.Assert(spriteMeshData != null);
  435. if (selection == null)
  436. throw new ArgumentNullException("selection is null");
  437. var channelEnabledChanged = oldEnabled != newEnabled;
  438. var boneIndexChanged = oldBoneIndex != newBoneIndex;
  439. var weightChanged = Mathf.Abs(oldWeight - newWeight) > Mathf.Epsilon;
  440. var indices = selection.elements;
  441. foreach (var i in indices)
  442. {
  443. var editableBoneWeight = spriteMeshData.vertexWeights[i];
  444. if (channelEnabledChanged)
  445. editableBoneWeight[channel].enabled = newEnabled;
  446. if (boneIndexChanged)
  447. editableBoneWeight[channel].boneIndex = newBoneIndex;
  448. if (weightChanged)
  449. editableBoneWeight[channel].weight = newWeight;
  450. if (channelEnabledChanged || weightChanged)
  451. editableBoneWeight.CompensateOtherChannels(channel);
  452. }
  453. }
  454. public void GetControlPoints(out float2[] points, out int2[] edges, out int[] pins)
  455. {
  456. Debug.Assert(spriteMeshData != null);
  457. points = null;
  458. edges = null;
  459. var pointList = new List<Vector2>();
  460. var edgeList = new List<int2>();
  461. var pinList = new List<int>();
  462. var bones = new List<SpriteBoneData>(spriteMeshData.boneCount);
  463. for (var i = 0; i < spriteMeshData.boneCount; ++i)
  464. bones.Add(spriteMeshData.GetBoneData(i));
  465. foreach (var bone in bones)
  466. {
  467. var length = (bone.endPosition - bone.position).magnitude;
  468. if (length > 0f)
  469. {
  470. var index1 = FindPoint(pointList, bone.position, 0.01f);
  471. var index2 = FindPoint(pointList, bone.endPosition, 0.01f);
  472. if (index1 == -1)
  473. {
  474. pointList.Add(bone.position);
  475. index1 = pointList.Count - 1;
  476. }
  477. if (index2 == -1)
  478. {
  479. pointList.Add(bone.endPosition);
  480. index2 = pointList.Count - 1;
  481. }
  482. edgeList.Add(new int2(index1, index2));
  483. }
  484. else if (bone.length == 0f)
  485. {
  486. pointList.Add(bone.position);
  487. pinList.Add(pointList.Count - 1);
  488. }
  489. }
  490. points = new float2[pointList.Count];
  491. for (var i = 0; i < pointList.Count; ++i)
  492. points[i] = pointList[i];
  493. edges = edgeList.ToArray();
  494. pins = pinList.ToArray();
  495. }
  496. static int FindPoint(IReadOnlyList<Vector2> points, Vector2 point, float distanceTolerance)
  497. {
  498. var sqrTolerance = distanceTolerance * distanceTolerance;
  499. for (var i = 0; i < points.Count; ++i)
  500. {
  501. if ((points[i] - point).sqrMagnitude <= sqrTolerance)
  502. return i;
  503. }
  504. return -1;
  505. }
  506. public void SmoothFill()
  507. {
  508. var tempSelection = new IndexedSelection();
  509. var vertexSelector = new GenericVertexSelector();
  510. var currentWeightSum = 0f;
  511. var prevWeightSum = 0f;
  512. vertexSelector.spriteMeshData = spriteMeshData;
  513. vertexSelector.selection = tempSelection;
  514. vertexSelector.SelectionCallback = (int i) => {
  515. var sum = spriteMeshData.vertexWeights[i].Sum();
  516. currentWeightSum += sum;
  517. return sum < 0.99f;
  518. };
  519. do
  520. {
  521. prevWeightSum = currentWeightSum;
  522. currentWeightSum = 0f;
  523. vertexSelector.Select();
  524. if (tempSelection.Count > 0)
  525. SmoothWeights(1, tempSelection);
  526. }
  527. while (currentWeightSum - prevWeightSum > 0.001f);
  528. if (tempSelection.Count > 0)
  529. NormalizeWeights(tempSelection);
  530. }
  531. }
  532. }