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.

BoneSpriteInfluenceTool.cs 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEditor.U2D.Layout;
  5. namespace UnityEditor.U2D.Animation
  6. {
  7. internal class BoneSpriteInfluenceToolController
  8. {
  9. SkinningEvents m_Events;
  10. IBoneSpriteInfluenceToolModel m_Model;
  11. public BoneSpriteInfluenceToolController(IBoneSpriteInfluenceToolModel model, SkinningEvents events)
  12. {
  13. m_Events = events;
  14. m_Model = model;
  15. }
  16. public void Activate()
  17. {
  18. m_Events.selectedSpriteChanged.AddListener(OnSpriteSelectionChanged);
  19. m_Events.boneSelectionChanged.AddListener(OnBoneSelectionChanged);
  20. m_Events.boneNameChanged.AddListener(OnBoneNameChanged);
  21. m_Events.skeletonTopologyChanged.AddListener(OnSkeletonTopologyChanged);
  22. m_Events.meshChanged.AddListener(OnMeshChanged);
  23. m_Events.skinningModeChanged.AddListener(OnSkinningModeChanged);
  24. ShowHideView(true);
  25. }
  26. public void Deactivate()
  27. {
  28. m_Events.selectedSpriteChanged.RemoveListener(OnSpriteSelectionChanged);
  29. m_Events.boneSelectionChanged.RemoveListener(OnBoneSelectionChanged);
  30. m_Events.boneNameChanged.RemoveListener(OnBoneNameChanged);
  31. m_Events.skeletonTopologyChanged.RemoveListener(OnSkeletonTopologyChanged);
  32. m_Events.meshChanged.RemoveListener(OnMeshChanged);
  33. m_Events.skinningModeChanged.RemoveListener(OnSkinningModeChanged);
  34. ShowHideView(false);
  35. }
  36. void OnSpriteSelectionChanged(SpriteCache sprite)
  37. {
  38. if (m_Model.view.visible)
  39. {
  40. m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
  41. UpdateAddRemoveButtons();
  42. }
  43. }
  44. void OnBoneSelectionChanged()
  45. {
  46. if (m_Model.view.visible)
  47. {
  48. UpdateSelectedBonesInfluencedSprites();
  49. m_Model.view.UpdateList(m_Model.influencedSprites);
  50. m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
  51. UpdateAddRemoveButtons();
  52. SetViewHeaderText();
  53. }
  54. }
  55. void OnBoneNameChanged(BoneCache bone)
  56. {
  57. if (m_Model.view.visible)
  58. {
  59. SetViewHeaderText();
  60. }
  61. }
  62. void OnSkeletonTopologyChanged(SkeletonCache skeleton)
  63. {
  64. if (m_Model.view.visible)
  65. {
  66. m_Model.view.UpdateList(m_Model.influencedSprites);
  67. m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
  68. }
  69. }
  70. void OnMeshChanged(MeshCache mesh)
  71. {
  72. if (m_Model.view.visible)
  73. {
  74. m_Model.view.UpdateList(m_Model.influencedSprites);
  75. m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
  76. UpdateAddRemoveButtons();
  77. }
  78. }
  79. void OnSkinningModeChanged(SkinningMode skinningMode)
  80. {
  81. UpdateAddRemoveButtons();
  82. }
  83. void ShowHideView(bool show)
  84. {
  85. m_Model.view.SetHiddenFromLayout(!show);
  86. if (show)
  87. {
  88. UpdateSelectedBonesInfluencedSprites();
  89. m_Model.view.UpdateList(m_Model.influencedSprites);
  90. m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
  91. m_Model.view.listLabelText = TextContent.influencedSprites;
  92. m_Model.view.SetTooltips(TextContent.addSpriteInfluenceTooltip, TextContent.removeSpriteInfluenceTooltip);
  93. UpdateAddRemoveButtons();
  94. SetViewHeaderText();
  95. }
  96. }
  97. void SetViewHeaderText()
  98. {
  99. var headerText = m_Model.selectedBone != null ? m_Model.selectedBone.name : TextContent.noBoneSelected;
  100. m_Model.view.headerText = headerText;
  101. }
  102. public void OnViewCreated()
  103. {
  104. m_Model.view.onAddElement += AddSelectedSpriteInfluenceToBone;
  105. m_Model.view.onRemoveElement += RemoveSelectedSpriteInfluenceFromBone;
  106. m_Model.view.onSelectionChanged += SelectSprite;
  107. ShowHideView(false);
  108. }
  109. void AddSelectedSpriteInfluenceToBone()
  110. {
  111. if(m_Model.selectedSprite == null)
  112. return;
  113. var character = m_Model.characterSkeleton;
  114. if (character == null)
  115. return;
  116. if(m_Model.influencedSprites.Contains(m_Model.selectedSprite))
  117. return;
  118. var characterPart = m_Model.GetSpriteCharacterPart(m_Model.selectedSprite);
  119. var characterBones = characterPart.bones.ToList();
  120. var selectedBone = m_Model.selectedBone;
  121. characterBones.Add(selectedBone);
  122. using (m_Model.UndoScope(TextContent.addSpriteInfluence))
  123. {
  124. characterPart.bones = characterBones.ToArray();
  125. m_Events.characterPartChanged.Invoke(characterPart);
  126. UpdateSelectedBonesInfluencedSprites();
  127. m_Model.view.UpdateList(m_Model.influencedSprites);
  128. m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
  129. UpdateAddRemoveButtons();
  130. }
  131. }
  132. void RemoveSelectedSpriteInfluenceFromBone()
  133. {
  134. var character = m_Model.characterSkeleton;
  135. if (character == null)
  136. return;
  137. var selectedBone = m_Model.selectedBone;
  138. var selectedSprite = m_Model.selectedSprite;
  139. using (m_Model.UndoScope(TextContent.removeSpriteInfluence))
  140. {
  141. var characterPart = m_Model.GetSpriteCharacterPart(selectedSprite);
  142. var characterBones = characterPart.bones.ToList();
  143. characterBones.Remove(selectedBone);
  144. characterPart.bones = characterBones.ToArray();
  145. m_Events.characterPartChanged.Invoke(characterPart);
  146. selectedSprite.SmoothFill();
  147. UpdateSelectedBonesInfluencedSprites();
  148. m_Model.view.UpdateList(m_Model.influencedSprites);
  149. m_Model.view.UpdateSelection(new TransformCache[] {m_Model.selectedSprite});
  150. UpdateAddRemoveButtons();
  151. }
  152. }
  153. void SelectSprite(IEnumerable<object> selectedSprite)
  154. {
  155. using (m_Model.UndoScope(TextContent.spriteSelection))
  156. {
  157. var firstSelected = selectedSprite.FirstOrDefault();
  158. m_Model.selectedSprite = (SpriteCache)firstSelected;
  159. m_Events.selectedSpriteChanged.Invoke(m_Model.selectedSprite);
  160. }
  161. }
  162. void UpdateSelectedBonesInfluencedSprites()
  163. {
  164. var selectedBone = m_Model.selectedBone;
  165. if (selectedBone != null)
  166. {
  167. if (m_Model.hasCharacter)
  168. {
  169. var spriteList = new List<TransformCache>();
  170. foreach (var characterPartCache in selectedBone.skinningCache.character.parts)
  171. {
  172. if(characterPartCache.bones.Contains(selectedBone))
  173. spriteList.Add(characterPartCache.sprite);
  174. }
  175. m_Model.influencedSprites = spriteList;
  176. }
  177. else
  178. {
  179. var spriteList = new List<TransformCache>();
  180. var sprites = selectedBone.skinningCache.GetSprites();
  181. foreach (var sprite in sprites)
  182. {
  183. if(sprite.GetSkeleton().bones.Contains(selectedBone))
  184. spriteList.Add(sprite);
  185. }
  186. m_Model.influencedSprites = spriteList;
  187. }
  188. }
  189. else
  190. {
  191. m_Model.influencedSprites = new List<TransformCache>();
  192. }
  193. }
  194. public bool ShouldEnableAddButton()
  195. {
  196. if (IsCharacterMode())
  197. {
  198. var hasSelectedBone = m_Model.selectedBone != null;
  199. var selectedSprite = m_Model.selectedSprite;
  200. var hasSelectedSprite = selectedSprite != null;
  201. return hasSelectedBone && hasSelectedSprite && !m_Model.influencedSprites.Contains(selectedSprite);
  202. }
  203. return false;
  204. }
  205. void UpdateAddRemoveButtons()
  206. {
  207. m_Model.view.ToggleAddButton(ShouldEnableAddButton());
  208. m_Model.view.ToggleRemoveButton(IsCharacterMode());
  209. }
  210. public bool IsCharacterMode()
  211. {
  212. return m_Model.hasCharacter && m_Model.skinningMode == SkinningMode.Character;
  213. }
  214. }
  215. interface IBoneSpriteInfluenceToolModel
  216. {
  217. IInfluenceWindow view { get; }
  218. BoneCache selectedBone { get; }
  219. SpriteCache selectedSprite { get; set; }
  220. List<TransformCache> influencedSprites { get; set; }
  221. bool hasCharacter { get; }
  222. SkinningMode skinningMode { get; }
  223. SkeletonCache characterSkeleton { get; }
  224. UndoScope UndoScope(string description);
  225. CharacterPartCache GetSpriteCharacterPart(SpriteCache sprite);
  226. }
  227. class BoneSpriteInfluenceTool : BaseTool, IBoneSpriteInfluenceToolModel
  228. {
  229. BoneSpriteInfluenceToolController m_Controller;
  230. MeshPreviewBehaviour m_MeshPreviewBehaviour = new MeshPreviewBehaviour();
  231. InfluenceWindow m_View;
  232. public SkeletonTool skeletonTool { get; set; }
  233. public override IMeshPreviewBehaviour previewBehaviour => m_MeshPreviewBehaviour;
  234. internal override void OnCreate()
  235. {
  236. m_Controller = new BoneSpriteInfluenceToolController(this, skinningCache.events);
  237. }
  238. IInfluenceWindow IBoneSpriteInfluenceToolModel.view => m_View;
  239. BoneCache IBoneSpriteInfluenceToolModel.selectedBone => skinningCache.skeletonSelection.elements.FirstOrDefault();
  240. SpriteCache IBoneSpriteInfluenceToolModel.selectedSprite
  241. {
  242. get => skinningCache.selectedSprite;
  243. set => skinningCache.selectedSprite = value;
  244. }
  245. List<TransformCache> IBoneSpriteInfluenceToolModel.influencedSprites { get; set; }
  246. bool IBoneSpriteInfluenceToolModel.hasCharacter => skinningCache.hasCharacter;
  247. SkinningMode IBoneSpriteInfluenceToolModel.skinningMode => skinningCache.mode;
  248. SkeletonCache IBoneSpriteInfluenceToolModel.characterSkeleton => skinningCache.character != null ? skinningCache.character.skeleton : null;
  249. UndoScope IBoneSpriteInfluenceToolModel.UndoScope(string description)
  250. {
  251. return skinningCache.UndoScope(description);
  252. }
  253. public CharacterPartCache GetSpriteCharacterPart(SpriteCache sprite)
  254. {
  255. return sprite.GetCharacterPart();
  256. }
  257. protected override void OnActivate()
  258. {
  259. m_Controller.Activate();
  260. if(skeletonTool != null)
  261. skeletonTool.Activate();
  262. }
  263. protected override void OnDeactivate()
  264. {
  265. m_Controller.Deactivate();
  266. if(skeletonTool != null)
  267. skeletonTool.Deactivate();
  268. }
  269. public override void Initialize(LayoutOverlay layout)
  270. {
  271. if (m_View == null)
  272. {
  273. m_View = InfluenceWindow.CreateFromUxml();
  274. m_View.SetListReorderable(false);
  275. m_View.SetAllowMultiselect(false);
  276. m_Controller.OnViewCreated();
  277. }
  278. layout.rightOverlay.Add(m_View);
  279. }
  280. protected override void OnGUI()
  281. {
  282. m_MeshPreviewBehaviour.showWeightMap = true;
  283. m_MeshPreviewBehaviour.overlaySelected = true;
  284. m_MeshPreviewBehaviour.drawWireframe = true;
  285. skeletonTool.skeletonStyle = SkeletonStyles.WeightMap;
  286. skeletonTool.mode = SkeletonMode.EditPose;
  287. skeletonTool.editBindPose = false;
  288. skeletonTool.DoGUI();
  289. }
  290. }
  291. }