GenerateGeometryTool.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. using System;
  2. using UnityEditor.U2D.Layout;
  3. using UnityEngine;
  4. namespace UnityEditor.U2D.Animation
  5. {
  6. internal class GenerateGeometryTool : MeshToolWrapper
  7. {
  8. private const float kWeightTolerance = 0.1f;
  9. private SpriteMeshDataController m_SpriteMeshDataController = new SpriteMeshDataController();
  10. private ITriangulator m_Triangulator;
  11. private IOutlineGenerator m_OutlineGenerator;
  12. private IWeightsGenerator m_WeightGenerator;
  13. private GenerateGeometryPanel m_GenerateGeometryPanel;
  14. internal override void OnCreate()
  15. {
  16. m_Triangulator = new Triangulator();
  17. m_OutlineGenerator = new OutlineGenerator();
  18. m_WeightGenerator = new BoundedBiharmonicWeightsGenerator();
  19. }
  20. public override void Initialize(LayoutOverlay layout)
  21. {
  22. base.Initialize(layout);
  23. m_GenerateGeometryPanel = GenerateGeometryPanel.GenerateFromUXML();
  24. m_GenerateGeometryPanel.skinningCache = skinningCache;
  25. layout.rightOverlay.Add(m_GenerateGeometryPanel);
  26. BindElements();
  27. Hide();
  28. }
  29. private void BindElements()
  30. {
  31. Debug.Assert(m_GenerateGeometryPanel != null);
  32. m_GenerateGeometryPanel.onAutoGenerateGeometry += (float d, byte a, float s) =>
  33. {
  34. var selectedSprite = skinningCache.selectedSprite;
  35. if (selectedSprite != null)
  36. {
  37. EditorUtility.DisplayProgressBar(TextContent.generatingGeometry, selectedSprite.name, 0f);
  38. using (skinningCache.UndoScope(TextContent.generateGeometry))
  39. {
  40. GenerateGeometry(selectedSprite, d / 100f, a, s);
  41. if (m_GenerateGeometryPanel.generateWeights)
  42. {
  43. EditorUtility.DisplayProgressBar(TextContent.generatingWeights, selectedSprite.name, 1f);
  44. GenerateWeights(selectedSprite);
  45. }
  46. skinningCache.vertexSelection.Clear();
  47. skinningCache.events.meshChanged.Invoke(selectedSprite.GetMesh());
  48. }
  49. EditorUtility.ClearProgressBar();
  50. }
  51. };
  52. m_GenerateGeometryPanel.onAutoGenerateGeometryAll += (float d, byte a, float s) =>
  53. {
  54. var sprites = skinningCache.GetSprites();
  55. using (skinningCache.UndoScope(TextContent.generateGeometry))
  56. {
  57. for (var i = 0; i < sprites.Length; ++i)
  58. {
  59. var sprite = sprites[i];
  60. if (!sprite.IsVisible())
  61. continue;
  62. EditorUtility.DisplayProgressBar(TextContent.generateGeometry, sprite.name, i * 2f / (sprites.Length * 2f));
  63. GenerateGeometry(sprite, d / 100f, a, s);
  64. if (m_GenerateGeometryPanel.generateWeights)
  65. {
  66. EditorUtility.DisplayProgressBar(TextContent.generatingWeights, sprite.name, (i * 2f + 1) / (sprites.Length * 2f));
  67. GenerateWeights(sprite);
  68. }
  69. }
  70. foreach(var sprite in sprites)
  71. skinningCache.events.meshChanged.Invoke(sprite.GetMesh());
  72. EditorUtility.ClearProgressBar();
  73. }
  74. };
  75. }
  76. protected override void OnActivate()
  77. {
  78. base.OnActivate();
  79. UpdateButton();
  80. Show();
  81. skinningCache.events.selectedSpriteChanged.AddListener(OnSelectedSpriteChanged);
  82. }
  83. protected override void OnDeactivate()
  84. {
  85. base.OnDeactivate();
  86. Hide();
  87. skinningCache.events.selectedSpriteChanged.RemoveListener(OnSelectedSpriteChanged);
  88. }
  89. private void Show()
  90. {
  91. m_GenerateGeometryPanel.SetHiddenFromLayout(false);
  92. }
  93. private void Hide()
  94. {
  95. m_GenerateGeometryPanel.SetHiddenFromLayout(true);
  96. }
  97. private void UpdateButton()
  98. {
  99. var selectedSprite = skinningCache.selectedSprite;
  100. if (selectedSprite == null)
  101. m_GenerateGeometryPanel.SetMode(GenerateGeometryPanel.GenerateMode.Multiple);
  102. else
  103. m_GenerateGeometryPanel.SetMode(GenerateGeometryPanel.GenerateMode.Single);
  104. }
  105. private void OnSelectedSpriteChanged(SpriteCache sprite)
  106. {
  107. UpdateButton();
  108. }
  109. private void GenerateGeometry(SpriteCache sprite, float outlineDetail, byte alphaTolerance, float subdivide)
  110. {
  111. Debug.Assert(sprite != null);
  112. var mesh = sprite.GetMesh();
  113. Debug.Assert(mesh != null);
  114. m_SpriteMeshDataController.spriteMeshData = mesh;
  115. m_SpriteMeshDataController.OutlineFromAlpha(m_OutlineGenerator, mesh.textureDataProvider, outlineDetail, alphaTolerance);
  116. m_SpriteMeshDataController.Triangulate(m_Triangulator);
  117. if (subdivide > 0f)
  118. {
  119. var largestAreaFactor = Mathf.Lerp(0.5f, 0.05f, Math.Min(subdivide, 100f) / 100f);
  120. m_SpriteMeshDataController.Subdivide(m_Triangulator, largestAreaFactor);
  121. }
  122. foreach (var vertex in mesh.vertices)
  123. vertex.position -= sprite.textureRect.position;
  124. }
  125. private void GenerateWeights(SpriteCache sprite)
  126. {
  127. Debug.Assert(sprite != null);
  128. var mesh = sprite.GetMesh();
  129. Debug.Assert(mesh != null);
  130. using (new DefaultPoseScope(skinningCache.GetEffectiveSkeleton(sprite)))
  131. {
  132. if (NeedsAssociateBones(sprite.GetCharacterPart()))
  133. {
  134. using (new AssociateBonesScope(sprite))
  135. {
  136. GenerateWeights(mesh);
  137. }
  138. }
  139. else
  140. GenerateWeights(mesh);
  141. }
  142. }
  143. private bool NeedsAssociateBones(CharacterPartCache characterPart)
  144. {
  145. if (characterPart == null)
  146. return false;
  147. var skeleton = characterPart.skinningCache.character.skeleton;
  148. return characterPart.BoneCount == 0 ||
  149. (characterPart.BoneCount == 1 && characterPart.GetBone(0) == skeleton.GetBone(0));
  150. }
  151. private void GenerateWeights(MeshCache mesh)
  152. {
  153. Debug.Assert(mesh != null);
  154. m_SpriteMeshDataController.spriteMeshData = mesh;
  155. m_SpriteMeshDataController.CalculateWeights(m_WeightGenerator, null, kWeightTolerance);
  156. m_SpriteMeshDataController.SortTrianglesByDepth();
  157. }
  158. protected override void OnGUI()
  159. {
  160. m_MeshPreviewBehaviour.showWeightMap = m_GenerateGeometryPanel.generateWeights;
  161. m_MeshPreviewBehaviour.overlaySelected = m_GenerateGeometryPanel.generateWeights;
  162. skeletonTool.skeletonStyle = SkeletonStyles.Default;
  163. if (m_GenerateGeometryPanel.generateWeights)
  164. skeletonTool.skeletonStyle = SkeletonStyles.WeightMap;
  165. DoSkeletonGUI();
  166. }
  167. }
  168. }