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.

SkinningCache.cs 38KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Unity.Mathematics;
  6. using UnityEngine;
  7. using UnityEditor.U2D.Layout;
  8. using UnityEditor.U2D.Sprites;
  9. using UnityEngine.U2D.Common;
  10. using Debug = UnityEngine.Debug;
  11. using UnityEngine.UIElements;
  12. namespace UnityEditor.U2D.Animation
  13. {
  14. internal class SkinningObject : CacheObject
  15. {
  16. public SkinningCache skinningCache => owner as SkinningCache;
  17. }
  18. internal class SkinningCache : Cache
  19. {
  20. [Serializable]
  21. class SpriteMap : SerializableDictionary<string, SpriteCache> {}
  22. [Serializable]
  23. class MeshMap : SerializableDictionary<SpriteCache, MeshCache> {}
  24. [Serializable]
  25. class SkeletonMap : SerializableDictionary<SpriteCache, SkeletonCache> {}
  26. [Serializable]
  27. class ToolMap : SerializableDictionary<Tools, BaseTool> {}
  28. [Serializable]
  29. class MeshPreviewMap : SerializableDictionary<SpriteCache, MeshPreviewCache> {}
  30. [Serializable]
  31. class CharacterPartMap : SerializableDictionary<SpriteCache, CharacterPartCache> {}
  32. [SerializeField]
  33. SkinningEvents m_Events = new SkinningEvents();
  34. [SerializeField]
  35. List<BaseTool> m_Tools = new List<BaseTool>();
  36. [SerializeField]
  37. SpriteMap m_SpriteMap = new SpriteMap();
  38. [SerializeField]
  39. MeshMap m_MeshMap = new MeshMap();
  40. [SerializeField]
  41. MeshPreviewMap m_MeshPreviewMap = new MeshPreviewMap();
  42. [SerializeField]
  43. SkeletonMap m_SkeletonMap = new SkeletonMap();
  44. [SerializeField]
  45. CharacterPartMap m_CharacterPartMap = new CharacterPartMap();
  46. [SerializeField]
  47. ToolMap m_ToolMap = new ToolMap();
  48. [SerializeField]
  49. SelectionTool m_SelectionTool;
  50. [SerializeField]
  51. CharacterCache m_Character;
  52. [SerializeField]
  53. bool m_BonesReadOnly;
  54. [SerializeField]
  55. SkinningMode m_Mode = SkinningMode.SpriteSheet;
  56. [SerializeField]
  57. BaseTool m_SelectedTool;
  58. [SerializeField]
  59. SpriteCache m_SelectedSprite;
  60. [SerializeField]
  61. SkeletonSelection m_SkeletonSelection = new SkeletonSelection();
  62. [SerializeField]
  63. ISkinningCachePersistentState m_State;
  64. StringBuilder m_StringBuilder = new StringBuilder();
  65. public BaseTool selectedTool
  66. {
  67. get => m_SelectedTool;
  68. set
  69. {
  70. m_SelectedTool = value;
  71. try
  72. {
  73. m_State.lastUsedTool = m_ToolMap[value];
  74. }
  75. catch (KeyNotFoundException)
  76. {
  77. m_State.lastUsedTool = Tools.EditPose;
  78. }
  79. }
  80. }
  81. public virtual SkinningMode mode
  82. {
  83. get => m_Mode;
  84. set
  85. {
  86. m_Mode = CheckModeConsistency(value);
  87. m_State.lastMode = m_Mode;
  88. }
  89. }
  90. public SpriteCache selectedSprite
  91. {
  92. get => m_SelectedSprite;
  93. set
  94. {
  95. m_SelectedSprite = value;
  96. m_State.lastSpriteId = m_SelectedSprite ? m_SelectedSprite.id : String.Empty;
  97. }
  98. }
  99. public float brushSize
  100. {
  101. get => m_State.lastBrushSize;
  102. set => m_State.lastBrushSize = value;
  103. }
  104. public float brushHardness
  105. {
  106. get => m_State.lastBrushHardness;
  107. set => m_State.lastBrushHardness = value;
  108. }
  109. public float brushStep
  110. {
  111. get => m_State.lastBrushStep;
  112. set => m_State.lastBrushStep = value;
  113. }
  114. public int visibilityToolIndex
  115. {
  116. get => m_State.lastVisibilityToolIndex;
  117. set => m_State.lastVisibilityToolIndex = value;
  118. }
  119. public SkeletonSelection skeletonSelection => m_SkeletonSelection;
  120. public IndexedSelection vertexSelection => m_State.lastVertexSelection;
  121. public SkinningEvents events => m_Events;
  122. public SelectionTool selectionTool => m_SelectionTool;
  123. public SpriteCache[] GetSprites()
  124. {
  125. return m_SpriteMap.Values.ToArray();
  126. }
  127. public virtual CharacterCache character => m_Character;
  128. public bool hasCharacter => character != null;
  129. public bool bonesReadOnly => m_BonesReadOnly;
  130. public bool applyingChanges
  131. {
  132. get;
  133. set;
  134. }
  135. SkinningMode CheckModeConsistency(SkinningMode skinningMode)
  136. {
  137. if (skinningMode == SkinningMode.Character && hasCharacter == false)
  138. skinningMode = SkinningMode.SpriteSheet;
  139. return skinningMode;
  140. }
  141. public void Create(ISpriteEditorDataProvider spriteEditor, ISkinningCachePersistentState state)
  142. {
  143. Clear();
  144. var dataProvider = spriteEditor.GetDataProvider<ISpriteEditorDataProvider>();
  145. var boneProvider = spriteEditor.GetDataProvider<ISpriteBoneDataProvider>();
  146. var meshProvider = spriteEditor.GetDataProvider<ISpriteMeshDataProvider>();
  147. var spriteRects = dataProvider.GetSpriteRects();
  148. var textureProvider = spriteEditor.GetDataProvider<ITextureDataProvider>();
  149. m_State = state;
  150. m_State.lastTexture = textureProvider.texture;
  151. for (var i = 0; i < spriteRects.Length; i++)
  152. {
  153. var spriteRect = spriteRects[i];
  154. var sprite = CreateSpriteCache(spriteRect);
  155. CreateSkeletonCache(sprite, boneProvider);
  156. CreateMeshCache(sprite, meshProvider, textureProvider);
  157. CreateMeshPreviewCache(sprite);
  158. }
  159. CreateCharacter(spriteEditor);
  160. }
  161. public void CreateToolCache(ISpriteEditor spriteEditor, LayoutOverlay layoutOverlay)
  162. {
  163. var spriteEditorDataProvider = spriteEditor.GetDataProvider<ISpriteEditorDataProvider>();
  164. var skeletonTool = CreateCache<SkeletonTool>();
  165. var meshTool = CreateCache<MeshTool>();
  166. skeletonTool.Initialize(layoutOverlay);
  167. meshTool.Initialize(layoutOverlay);
  168. m_ToolMap.Add(Tools.EditPose, CreateSkeletonTool<SkeletonToolWrapper>(skeletonTool, SkeletonMode.EditPose, false, layoutOverlay));
  169. m_ToolMap.Add(Tools.EditJoints, CreateSkeletonTool<SkeletonToolWrapper>(skeletonTool, SkeletonMode.EditJoints, true, layoutOverlay));
  170. m_ToolMap.Add(Tools.CreateBone, CreateSkeletonTool<SkeletonToolWrapper>(skeletonTool, SkeletonMode.CreateBone, true, layoutOverlay));
  171. m_ToolMap.Add(Tools.SplitBone, CreateSkeletonTool<SkeletonToolWrapper>(skeletonTool, SkeletonMode.SplitBone, true, layoutOverlay));
  172. m_ToolMap.Add(Tools.ReparentBone, CreateSkeletonTool<BoneReparentTool>(skeletonTool, SkeletonMode.EditPose, false, layoutOverlay));
  173. m_ToolMap.Add(Tools.CharacterPivotTool, CreateSkeletonTool<PivotTool>(skeletonTool, SkeletonMode.Disabled, false, layoutOverlay));
  174. m_ToolMap.Add(Tools.EditGeometry, CreateMeshTool<MeshToolWrapper>(skeletonTool, meshTool, SpriteMeshViewMode.EditGeometry, SkeletonMode.Disabled, layoutOverlay));
  175. m_ToolMap.Add(Tools.CreateVertex, CreateMeshTool<MeshToolWrapper>(skeletonTool, meshTool, SpriteMeshViewMode.CreateVertex, SkeletonMode.Disabled, layoutOverlay));
  176. m_ToolMap.Add(Tools.CreateEdge, CreateMeshTool<MeshToolWrapper>(skeletonTool, meshTool, SpriteMeshViewMode.CreateEdge, SkeletonMode.Disabled, layoutOverlay));
  177. m_ToolMap.Add(Tools.SplitEdge, CreateMeshTool<MeshToolWrapper>(skeletonTool, meshTool, SpriteMeshViewMode.SplitEdge, SkeletonMode.Disabled, layoutOverlay));
  178. m_ToolMap.Add(Tools.GenerateGeometry, CreateMeshTool<GenerateGeometryTool>(skeletonTool, meshTool, SpriteMeshViewMode.EditGeometry, SkeletonMode.EditPose, layoutOverlay));
  179. var copyTool = CreateTool<CopyTool>();
  180. copyTool.Initialize(layoutOverlay);
  181. copyTool.pixelsPerUnit = spriteEditorDataProvider.pixelsPerUnit;
  182. copyTool.skeletonTool = skeletonTool;
  183. copyTool.meshTool = meshTool;
  184. m_ToolMap.Add(Tools.CopyPaste, copyTool);
  185. CreateWeightTools(skeletonTool, meshTool, layoutOverlay);
  186. m_SelectionTool = CreateTool<SelectionTool>();
  187. m_SelectionTool.spriteEditor = spriteEditor;
  188. m_SelectionTool.Initialize(layoutOverlay);
  189. m_SelectionTool.Activate();
  190. var visibilityTool = CreateTool<VisibilityTool>();
  191. visibilityTool.Initialize(layoutOverlay);
  192. visibilityTool.skeletonTool = skeletonTool;
  193. m_ToolMap.Add(Tools.Visibility, visibilityTool);
  194. var switchModeTool = CreateTool<SwitchModeTool>();
  195. m_ToolMap.Add(Tools.SwitchMode, switchModeTool);
  196. }
  197. public void RestoreFromPersistentState()
  198. {
  199. mode = m_State.lastMode;
  200. events.skinningModeChanged.Invoke(mode);
  201. var hasLastSprite = m_SpriteMap.TryGetValue(m_State.lastSpriteId, out var lastSprite);
  202. if (hasLastSprite)
  203. {
  204. selectedSprite = lastSprite;
  205. }
  206. else
  207. {
  208. vertexSelection.Clear();
  209. }
  210. if (m_ToolMap.TryGetValue(m_State.lastUsedTool, out var baseTool))
  211. {
  212. selectedTool = baseTool;
  213. }
  214. else if (m_ToolMap.TryGetValue(Tools.EditPose, out baseTool))
  215. {
  216. selectedTool = baseTool;
  217. }
  218. var visibilityTool = m_ToolMap[Tools.Visibility];
  219. if (m_State.lastVisibilityToolActive)
  220. {
  221. visibilityTool.Activate();
  222. }
  223. }
  224. public void RestoreToolStateFromPersistentState()
  225. {
  226. events.boneSelectionChanged.RemoveListener(BoneSelectionChanged);
  227. events.skeletonPreviewPoseChanged.RemoveListener(SkeletonPreviewPoseChanged);
  228. events.toolChanged.RemoveListener(ToolChanged);
  229. SkeletonCache skeleton = null;
  230. if (hasCharacter)
  231. skeleton = character.skeleton;
  232. else if (selectedSprite != null)
  233. skeleton = selectedSprite.GetSkeleton();
  234. skeletonSelection.Clear();
  235. if (skeleton != null && m_State.lastBoneSelectionIds.Count > 0)
  236. {
  237. bool selectionChanged = false;
  238. foreach (var bone in skeleton.bones)
  239. {
  240. var id = GetBoneNameHash(m_StringBuilder, bone);
  241. if (m_State.lastBoneSelectionIds.Contains(id))
  242. {
  243. skeletonSelection.Select(bone, true);
  244. selectionChanged = true;
  245. }
  246. }
  247. if (selectionChanged)
  248. events.boneSelectionChanged.Invoke();
  249. }
  250. if (m_State.lastPreviewPose.Count > 0)
  251. {
  252. if (hasCharacter)
  253. {
  254. UpdatePoseFromPersistentState(character.skeleton, null);
  255. }
  256. foreach (var sprite in m_SkeletonMap.Keys)
  257. {
  258. UpdatePoseFromPersistentState(m_SkeletonMap[sprite], sprite);
  259. }
  260. }
  261. if (m_State.lastBoneVisibility.Count > 0)
  262. {
  263. if (hasCharacter)
  264. {
  265. UpdateVisibilityFromPersistentState(character.skeleton, null);
  266. }
  267. foreach (var sprite in m_SkeletonMap.Keys)
  268. {
  269. UpdateVisibilityFromPersistentState(m_SkeletonMap[sprite], sprite);
  270. }
  271. }
  272. if (m_State.lastSpriteVisibility.Count > 0 && hasCharacter)
  273. {
  274. foreach (var characterPart in character.parts)
  275. {
  276. if (m_State.lastSpriteVisibility.TryGetValue(characterPart.sprite.id, out var visibility))
  277. {
  278. characterPart.isVisible = visibility;
  279. }
  280. }
  281. foreach (var characterGroup in character.groups)
  282. {
  283. var groupHash = GetCharacterGroupHash(m_StringBuilder, characterGroup, character);
  284. if (m_State.lastGroupVisibility.TryGetValue(groupHash, out var visibility))
  285. {
  286. characterGroup.isVisible = visibility;
  287. }
  288. }
  289. }
  290. events.boneSelectionChanged.AddListener(BoneSelectionChanged);
  291. events.skeletonPreviewPoseChanged.AddListener(SkeletonPreviewPoseChanged);
  292. events.toolChanged.AddListener(ToolChanged);
  293. }
  294. void UpdatePoseFromPersistentState(SkeletonCache skeleton, SpriteCache sprite)
  295. {
  296. var poseChanged = false;
  297. foreach (var bone in skeleton.bones)
  298. {
  299. var id = GetBoneNameHash(m_StringBuilder, bone, sprite);
  300. if (m_State.lastPreviewPose.TryGetValue(id, out var pose))
  301. {
  302. bone.localPose = pose;
  303. poseChanged = true;
  304. }
  305. }
  306. if (poseChanged)
  307. {
  308. skeleton.SetPosePreview();
  309. events.skeletonPreviewPoseChanged.Invoke(skeleton);
  310. }
  311. }
  312. void UpdateVisibilityFromPersistentState(SkeletonCache skeleton, SpriteCache sprite)
  313. {
  314. foreach (var bone in skeleton.bones)
  315. {
  316. var id = GetBoneNameHash(m_StringBuilder, bone, sprite);
  317. if (m_State.lastBoneVisibility.TryGetValue(id, out var visibility))
  318. {
  319. bone.isVisible = visibility;
  320. }
  321. }
  322. }
  323. const string k_NameSeparator = "/";
  324. int GetBoneNameHash(StringBuilder sb, BoneCache bone, SpriteCache sprite = null)
  325. {
  326. sb.Clear();
  327. BuildBoneName(sb, bone);
  328. sb.Append(k_NameSeparator);
  329. if (sprite != null)
  330. {
  331. sb.Append(sprite.id);
  332. }
  333. else
  334. {
  335. sb.Append(0);
  336. }
  337. return Animator.StringToHash(sb.ToString());
  338. }
  339. static void BuildBoneName(StringBuilder sb, BoneCache bone)
  340. {
  341. if (bone.parentBone != null)
  342. {
  343. BuildBoneName(sb, bone.parentBone);
  344. sb.Append(k_NameSeparator);
  345. }
  346. sb.Append(bone.name);
  347. }
  348. static int GetCharacterGroupHash(StringBuilder sb, CharacterGroupCache characterGroup, CharacterCache characterCache)
  349. {
  350. sb.Clear();
  351. BuildGroupName(sb, characterGroup, characterCache);
  352. return Animator.StringToHash(sb.ToString());
  353. }
  354. static void BuildGroupName(StringBuilder sb, CharacterGroupCache group, CharacterCache characterCache)
  355. {
  356. if (group.parentGroup >= 0 && group.parentGroup < characterCache.groups.Length)
  357. {
  358. BuildGroupName(sb, characterCache.groups[group.parentGroup], characterCache);
  359. sb.Append(k_NameSeparator);
  360. }
  361. sb.Append(group.order);
  362. }
  363. void BoneSelectionChanged()
  364. {
  365. m_State.lastBoneSelectionIds.Clear();
  366. m_State.lastBoneSelectionIds.Capacity = skeletonSelection.elements.Length;
  367. for (var i = 0; i < skeletonSelection.elements.Length; ++i)
  368. {
  369. var bone = skeletonSelection.elements[i];
  370. m_State.lastBoneSelectionIds.Add(GetBoneNameHash(m_StringBuilder, bone));
  371. }
  372. }
  373. void SkeletonPreviewPoseChanged(SkeletonCache sc)
  374. {
  375. if (applyingChanges)
  376. return;
  377. m_State.lastPreviewPose.Clear();
  378. if (hasCharacter)
  379. {
  380. StorePersistentStatePoseForSkeleton(character.skeleton, null);
  381. }
  382. foreach (var sprite in m_SkeletonMap.Keys)
  383. {
  384. StorePersistentStatePoseForSkeleton(m_SkeletonMap[sprite], sprite);
  385. }
  386. }
  387. void StorePersistentStatePoseForSkeleton(SkeletonCache skeleton, SpriteCache sprite)
  388. {
  389. foreach (var bone in skeleton.bones)
  390. {
  391. var id = GetBoneNameHash(m_StringBuilder, bone, sprite);
  392. if (bone.NotInDefaultPose())
  393. {
  394. m_State.lastPreviewPose[id] = bone.localPose;
  395. }
  396. }
  397. }
  398. internal void Revert()
  399. {
  400. m_State.lastVertexSelection.Clear();
  401. }
  402. internal void BoneVisibilityChanged()
  403. {
  404. if (applyingChanges)
  405. return;
  406. m_State.lastBoneVisibility.Clear();
  407. if (hasCharacter)
  408. {
  409. StorePersistentStateVisibilityForSkeleton(character.skeleton, null);
  410. }
  411. foreach (var sprite in m_SkeletonMap.Keys)
  412. {
  413. StorePersistentStateVisibilityForSkeleton(m_SkeletonMap[sprite], sprite);
  414. }
  415. }
  416. void StorePersistentStateVisibilityForSkeleton(SkeletonCache skeleton, SpriteCache sprite)
  417. {
  418. foreach (var bone in skeleton.bones)
  419. {
  420. var id = GetBoneNameHash(m_StringBuilder, bone, sprite);
  421. m_State.lastBoneVisibility[id] = bone.isVisible;
  422. }
  423. }
  424. internal void BoneExpansionChanged(BoneCache[] boneCaches)
  425. {
  426. if (applyingChanges)
  427. return;
  428. m_State.lastBoneExpansion.Clear();
  429. if (hasCharacter)
  430. {
  431. foreach (var bone in boneCaches)
  432. {
  433. if (character.skeleton.bones.Contains(bone))
  434. {
  435. var id = GetBoneNameHash(m_StringBuilder, bone, null);
  436. m_State.lastBoneExpansion[id] = true;
  437. }
  438. }
  439. }
  440. foreach (var sprite in m_SkeletonMap.Keys)
  441. {
  442. var skeleton = m_SkeletonMap[sprite];
  443. foreach (var bone in boneCaches)
  444. {
  445. if (skeleton.bones.Contains(bone))
  446. {
  447. var id = GetBoneNameHash(m_StringBuilder, bone, sprite);
  448. m_State.lastBoneExpansion[id] = true;
  449. }
  450. }
  451. }
  452. }
  453. internal BoneCache[] GetExpandedBones()
  454. {
  455. var expandedBones = new HashSet<BoneCache>();
  456. if (m_State.lastBoneExpansion.Count > 0)
  457. {
  458. if (hasCharacter)
  459. {
  460. foreach (var bone in character.skeleton.bones)
  461. {
  462. var id = GetBoneNameHash(m_StringBuilder, bone, null);
  463. if (m_State.lastBoneExpansion.TryGetValue(id, out var expanded))
  464. {
  465. expandedBones.Add(bone);
  466. }
  467. }
  468. }
  469. foreach (var sprite in m_SkeletonMap.Keys)
  470. {
  471. var skeleton = m_SkeletonMap[sprite];
  472. foreach (var bone in skeleton.bones)
  473. {
  474. var id = GetBoneNameHash(m_StringBuilder, bone, sprite);
  475. if (m_State.lastBoneExpansion.TryGetValue(id, out var expanded))
  476. {
  477. expandedBones.Add(bone);
  478. }
  479. }
  480. }
  481. }
  482. return expandedBones.ToArray();
  483. }
  484. internal void SpriteVisibilityChanged(CharacterPartCache cc)
  485. {
  486. m_State.lastSpriteVisibility[cc.sprite.id] = cc.isVisible;
  487. }
  488. internal void GroupVisibilityChanged(CharacterGroupCache gc)
  489. {
  490. if (!hasCharacter)
  491. return;
  492. var groupHash = GetCharacterGroupHash(m_StringBuilder, gc, character);
  493. m_State.lastGroupVisibility[groupHash] = gc.isVisible;
  494. }
  495. void Clear()
  496. {
  497. Destroy();
  498. m_Tools.Clear();
  499. m_SpriteMap.Clear();
  500. m_MeshMap.Clear();
  501. m_MeshPreviewMap.Clear();
  502. m_SkeletonMap.Clear();
  503. m_ToolMap.Clear();
  504. m_CharacterPartMap.Clear();
  505. }
  506. public SpriteCache GetSprite(string id)
  507. {
  508. if (string.IsNullOrEmpty(id))
  509. return null;
  510. m_SpriteMap.TryGetValue(id, out var sprite);
  511. return sprite;
  512. }
  513. public virtual MeshCache GetMesh(SpriteCache sprite)
  514. {
  515. if (sprite == null)
  516. return null;
  517. m_MeshMap.TryGetValue(sprite, out var mesh);
  518. return mesh;
  519. }
  520. public virtual MeshPreviewCache GetMeshPreview(SpriteCache sprite)
  521. {
  522. if (sprite == null)
  523. return null;
  524. m_MeshPreviewMap.TryGetValue(sprite, out var meshPreview);
  525. return meshPreview;
  526. }
  527. public SkeletonCache GetSkeleton(SpriteCache sprite)
  528. {
  529. if (sprite == null)
  530. return null;
  531. m_SkeletonMap.TryGetValue(sprite, out var skeleton);
  532. return skeleton;
  533. }
  534. public virtual CharacterPartCache GetCharacterPart(SpriteCache sprite)
  535. {
  536. if (sprite == null)
  537. return null;
  538. m_CharacterPartMap.TryGetValue(sprite, out var part);
  539. return part;
  540. }
  541. public SkeletonCache GetEffectiveSkeleton(SpriteCache sprite)
  542. {
  543. if (mode == SkinningMode.SpriteSheet)
  544. return GetSkeleton(sprite);
  545. if (hasCharacter)
  546. return character.skeleton;
  547. return null;
  548. }
  549. public BaseTool GetTool(Tools tool)
  550. {
  551. m_ToolMap.TryGetValue(tool, out var t);
  552. return t;
  553. }
  554. public override void BeginUndoOperation(string operationName)
  555. {
  556. if (isUndoOperationSet == false)
  557. {
  558. base.BeginUndoOperation(operationName);
  559. undo.RegisterCompleteObjectUndo(m_State, operationName);
  560. }
  561. }
  562. public UndoScope UndoScope(string operationName, bool incrementGroup = false)
  563. {
  564. return new UndoScope(this, operationName, incrementGroup);
  565. }
  566. public DisableUndoScope DisableUndoScope()
  567. {
  568. return new DisableUndoScope(this);
  569. }
  570. public T CreateTool<T>() where T : BaseTool
  571. {
  572. var tool = CreateCache<T>();
  573. m_Tools.Add(tool);
  574. return tool;
  575. }
  576. void UpdateCharacterPart(CharacterPartCache characterPart)
  577. {
  578. var sprite = characterPart.sprite;
  579. var characterPartBones = characterPart.bones;
  580. var newBones = new List<BoneCache>(characterPartBones);
  581. newBones.RemoveAll(b => b == null || IsRemoved(b) || b.skeleton != character.skeleton);
  582. var removedBonesCount = characterPartBones.Length - newBones.Count;
  583. characterPartBones = newBones.ToArray();
  584. characterPart.bones = characterPartBones;
  585. sprite.UpdateMesh(characterPartBones);
  586. if (removedBonesCount > 0)
  587. sprite.SmoothFill();
  588. }
  589. public void CreateSpriteSheetSkeletons()
  590. {
  591. Debug.Assert(character != null);
  592. using (new DefaultPoseScope(character.skeleton))
  593. {
  594. var characterParts = character.parts;
  595. foreach (var characterPart in characterParts)
  596. CreateSpriteSheetSkeleton(characterPart);
  597. }
  598. SyncSpriteSheetSkeletons();
  599. }
  600. public void SyncSpriteSheetSkeletons()
  601. {
  602. Debug.Assert(character != null);
  603. var characterParts = character.parts;
  604. foreach (var characterPart in characterParts)
  605. characterPart.SyncSpriteSheetSkeleton();
  606. }
  607. public void CreateSpriteSheetSkeleton(CharacterPartCache characterPart)
  608. {
  609. UpdateCharacterPart(characterPart);
  610. Debug.Assert(character != null);
  611. Debug.Assert(character.skeleton != null);
  612. Debug.Assert(character.skeleton.isPosePreview == false);
  613. var sprite = characterPart.sprite;
  614. var characterPartBones = characterPart.bones;
  615. var skeleton = sprite.GetSkeleton();
  616. Debug.Assert(skeleton != null);
  617. var spriteBones = characterPartBones.ToSpriteBone(characterPart.localToWorldMatrix);
  618. skeleton.SetBones(CreateBoneCacheFromSpriteBones(spriteBones, 1.0f), false);
  619. events.skeletonTopologyChanged.Invoke(skeleton);
  620. }
  621. SpriteCache CreateSpriteCache(SpriteRect spriteRect)
  622. {
  623. var sprite = CreateCache<SpriteCache>();
  624. sprite.name = spriteRect.name;
  625. sprite.id = spriteRect.spriteID.ToString();
  626. sprite.textureRect = spriteRect.rect;
  627. sprite.position = spriteRect.rect.position;
  628. m_SpriteMap[sprite.id] = sprite;
  629. return sprite;
  630. }
  631. void CreateSkeletonCache(SpriteCache sprite, ISpriteBoneDataProvider boneProvider)
  632. {
  633. var guid = new GUID(sprite.id);
  634. var skeleton = CreateCache<SkeletonCache>();
  635. skeleton.position = sprite.textureRect.position;
  636. skeleton.SetBones(CreateBoneCacheFromSpriteBones(boneProvider.GetBones(guid).ToArray(), 1.0f), false);
  637. m_SkeletonMap[sprite] = skeleton;
  638. }
  639. void CreateMeshCache(SpriteCache sprite, ISpriteMeshDataProvider meshProvider, ITextureDataProvider textureDataProvider)
  640. {
  641. Debug.Assert(m_SkeletonMap.ContainsKey(sprite));
  642. var guid = new GUID(sprite.id);
  643. var mesh = new MeshCache();
  644. var skeleton = m_SkeletonMap[sprite] as SkeletonCache;
  645. mesh.sprite = sprite;
  646. mesh.SetCompatibleBoneSet(skeleton.bones);
  647. var metaVertices = meshProvider.GetVertices(guid);
  648. if (metaVertices.Length > 0)
  649. {
  650. var vertices = new Vector2[metaVertices.Length];
  651. var weights = new EditableBoneWeight[metaVertices.Length];
  652. for (var i = 0; i < metaVertices.Length; ++i)
  653. {
  654. vertices[i] = metaVertices[i].position;
  655. weights[i] = EditableBoneWeightUtility.CreateFromBoneWeight(metaVertices[i].boneWeight);
  656. }
  657. mesh.SetVertices(vertices, weights);
  658. mesh.SetIndices(meshProvider.GetIndices(guid));
  659. mesh.SetEdges(EditorUtilities.ToInt2(meshProvider.GetEdges(guid)));
  660. }
  661. else
  662. {
  663. GenerateOutline(sprite, textureDataProvider, out var vertices, out var indices, out var edges);
  664. var vertexWeights = new EditableBoneWeight[vertices.Length];
  665. for (var i = 0; i < vertexWeights.Length; ++i)
  666. vertexWeights[i] = new EditableBoneWeight();
  667. mesh.SetVertices(vertices, vertexWeights);
  668. mesh.SetIndices(indices);
  669. mesh.SetEdges(edges);
  670. }
  671. mesh.textureDataProvider = textureDataProvider;
  672. m_MeshMap[sprite] = mesh;
  673. }
  674. static void GenerateOutline(SpriteCache sprite, ITextureDataProvider textureDataProvider,
  675. out Vector2[] vertices, out int[] indices, out int2[] edges)
  676. {
  677. if (textureDataProvider == null ||
  678. textureDataProvider.texture == null)
  679. {
  680. vertices = new Vector2[0];
  681. indices = new int[0];
  682. edges = new int2[0];
  683. return;
  684. }
  685. const float detail = 0.05f;
  686. const byte alphaTolerance = 200;
  687. var smd = new SpriteMeshData();
  688. smd.SetFrame(sprite.textureRect);
  689. var meshDataController = new SpriteMeshDataController
  690. {
  691. spriteMeshData = smd
  692. };
  693. meshDataController.OutlineFromAlpha(new OutlineGenerator(), textureDataProvider, detail, alphaTolerance);
  694. meshDataController.Triangulate(new Triangulator());
  695. vertices = smd.vertices;
  696. indices = smd.indices;
  697. edges = smd.edges;
  698. }
  699. void CreateMeshPreviewCache(SpriteCache sprite)
  700. {
  701. Debug.Assert(sprite != null);
  702. Debug.Assert(m_MeshPreviewMap.ContainsKey(sprite) == false);
  703. var meshPreview = CreateCache<MeshPreviewCache>();
  704. meshPreview.sprite = sprite;
  705. meshPreview.SetMeshDirty();
  706. m_MeshPreviewMap.Add(sprite, meshPreview);
  707. }
  708. void CreateCharacter(ISpriteEditorDataProvider spriteEditor)
  709. {
  710. var characterProvider = spriteEditor.GetDataProvider<ICharacterDataProvider>();
  711. if (characterProvider != null)
  712. {
  713. var characterData = characterProvider.GetCharacterData();
  714. var characterParts = new List<CharacterPartCache>();
  715. m_Character = CreateCache<CharacterCache>();
  716. m_BonesReadOnly = spriteEditor.GetDataProvider<IMainSkeletonDataProvider>() != null;
  717. var skeleton = CreateCache<SkeletonCache>();
  718. var characterBones = characterData.bones;
  719. skeleton.SetBones(CreateBoneCacheFromSpriteBones(characterBones, 1.0f));
  720. skeleton.position = Vector3.zero;
  721. var bones = skeleton.bones;
  722. foreach (var p in characterData.parts)
  723. {
  724. var spriteBones = p.bones != null ? p.bones.ToList() : new List<int>();
  725. var characterPartBones = spriteBones.ConvertAll(i => bones.ElementAtOrDefault(i)).ToArray();
  726. var characterPart = CreateCache<CharacterPartCache>();
  727. var positionInt = p.spritePosition.position;
  728. characterPart.position = new Vector2(positionInt.x, positionInt.y);
  729. characterPart.sprite = GetSprite(p.spriteId);
  730. characterPart.bones = characterPartBones;
  731. characterPart.parentGroup = p.parentGroup;
  732. characterPart.order = p.order;
  733. var mesh = characterPart.sprite.GetMesh();
  734. if (mesh != null)
  735. mesh.SetCompatibleBoneSet(characterPartBones);
  736. characterParts.Add(characterPart);
  737. m_CharacterPartMap.Add(characterPart.sprite, characterPart);
  738. }
  739. if (characterData.characterGroups != null)
  740. {
  741. m_Character.groups = characterData.characterGroups.Select(x =>
  742. {
  743. var group = CreateCache<CharacterGroupCache>();
  744. group.name = x.name;
  745. group.parentGroup = x.parentGroup;
  746. group.order = x.order;
  747. return group;
  748. }).ToArray();
  749. }
  750. else
  751. {
  752. m_Character.groups = new CharacterGroupCache[0];
  753. }
  754. m_Character.parts = characterParts.ToArray();
  755. m_Character.skeleton = skeleton;
  756. m_Character.dimension = characterData.dimension;
  757. m_Character.pivot = characterData.pivot;
  758. CreateSpriteSheetSkeletons();
  759. }
  760. }
  761. T CreateSkeletonTool<T>(SkeletonTool skeletonTool, SkeletonMode skeletonMode, bool editBindPose, LayoutOverlay layoutOverlay) where T : SkeletonToolWrapper
  762. {
  763. var tool = CreateTool<T>();
  764. tool.skeletonTool = skeletonTool;
  765. tool.mode = skeletonMode;
  766. tool.editBindPose = editBindPose;
  767. tool.Initialize(layoutOverlay);
  768. return tool;
  769. }
  770. void CreateWeightTools(SkeletonTool skeletonTool, MeshTool meshTool, LayoutOverlay layoutOverlay)
  771. {
  772. var weightPainterTool = CreateCache<WeightPainterTool>();
  773. weightPainterTool.Initialize(layoutOverlay);
  774. weightPainterTool.skeletonTool = skeletonTool;
  775. weightPainterTool.meshTool = meshTool;
  776. {
  777. var tool = CreateTool<SpriteBoneInfluenceTool>();
  778. tool.Initialize(layoutOverlay);
  779. tool.skeletonTool = skeletonTool;
  780. m_ToolMap.Add(Tools.BoneInfluence, tool);
  781. }
  782. {
  783. var tool = CreateTool<BoneSpriteInfluenceTool>();
  784. tool.Initialize(layoutOverlay);
  785. tool.skeletonTool = skeletonTool;
  786. m_ToolMap.Add(Tools.SpriteInfluence, tool);
  787. }
  788. {
  789. var tool = CreateTool<WeightPainterToolWrapper>();
  790. tool.weightPainterTool = weightPainterTool;
  791. tool.paintMode = WeightPainterMode.Slider;
  792. tool.title = TextContent.weightSlider;
  793. tool.Initialize(layoutOverlay);
  794. m_ToolMap.Add(Tools.WeightSlider, tool);
  795. }
  796. {
  797. var tool = CreateTool<WeightPainterToolWrapper>();
  798. tool.weightPainterTool = weightPainterTool;
  799. tool.paintMode = WeightPainterMode.Brush;
  800. tool.title = TextContent.weightBrush;
  801. tool.Initialize(layoutOverlay);
  802. m_ToolMap.Add(Tools.WeightBrush, tool);
  803. }
  804. {
  805. var tool = CreateTool<GenerateWeightsTool>();
  806. tool.Initialize(layoutOverlay);
  807. tool.meshTool = meshTool;
  808. tool.skeletonTool = skeletonTool;
  809. m_ToolMap.Add(Tools.GenerateWeights, tool);
  810. }
  811. }
  812. T CreateMeshTool<T>(SkeletonTool skeletonTool, MeshTool meshTool, SpriteMeshViewMode meshViewMode, SkeletonMode skeletonMode, LayoutOverlay layoutOverlay) where T : MeshToolWrapper
  813. {
  814. var tool = CreateTool<T>();
  815. tool.skeletonTool = skeletonTool;
  816. tool.meshTool = meshTool;
  817. tool.meshMode = meshViewMode;
  818. tool.skeletonMode = skeletonMode;
  819. tool.Initialize(layoutOverlay);
  820. return tool;
  821. }
  822. public void RestoreBindPose()
  823. {
  824. var sprites = GetSprites();
  825. foreach (var sprite in sprites)
  826. sprite.RestoreBindPose();
  827. if (character != null)
  828. character.skeleton.RestoreDefaultPose();
  829. }
  830. public void UndoRedoPerformed()
  831. {
  832. foreach (var tool in m_Tools)
  833. {
  834. if (tool == null)
  835. continue;
  836. if (!tool.isActive)
  837. tool.Deactivate();
  838. }
  839. foreach (var tool in m_Tools)
  840. {
  841. if (tool == null)
  842. continue;
  843. if (tool.isActive)
  844. tool.Activate();
  845. }
  846. }
  847. public BoneCache[] CreateBoneCacheFromSpriteBones(UnityEngine.U2D.SpriteBone[] spriteBones, float scale)
  848. {
  849. var bones = Array.ConvertAll(spriteBones, b => CreateCache<BoneCache>());
  850. for (var i = 0; i < spriteBones.Length; ++i)
  851. {
  852. var spriteBone = spriteBones[i];
  853. var bone = bones[i];
  854. if (spriteBone.parentId >= 0)
  855. bone.SetParent(bones[spriteBone.parentId]);
  856. bone.name = spriteBone.name;
  857. bone.guid = spriteBone.guid?.Length == 0 ? GUID.Generate().ToString() : spriteBone.guid;
  858. bone.localLength = spriteBone.length * scale;
  859. bone.depth = spriteBone.position.z;
  860. bone.localPosition = (Vector2)spriteBone.position * scale;
  861. bone.localRotation = spriteBone.rotation;
  862. if (spriteBone.color.a == 0)
  863. bone.bindPoseColor = ModuleUtility.CalculateNiceColor(i, 6);
  864. else
  865. bone.bindPoseColor = spriteBone.color;
  866. }
  867. foreach (var bone in bones)
  868. {
  869. if (bone.parentBone != null && bone.parentBone.localLength > 0f && (bone.position - bone.parentBone.endPosition).sqrMagnitude < 0.005f)
  870. bone.parentBone.chainedChild = bone;
  871. }
  872. return bones;
  873. }
  874. public bool IsOnVisualElement()
  875. {
  876. if (selectedTool == null || selectedTool.layoutOverlay == null)
  877. return false;
  878. var overlay = selectedTool.layoutOverlay;
  879. var point = InternalEngineBridge.GUIUnclip(Event.current.mousePosition);
  880. point = overlay.parent.parent.LocalToWorld(point);
  881. var selectedElement = selectedTool.layoutOverlay.panel.Pick(point);
  882. return selectedElement != null
  883. && selectedElement.pickingMode != PickingMode.Ignore
  884. && selectedElement.FindCommonAncestor(overlay) == overlay;
  885. }
  886. void ToolChanged(ITool tool)
  887. {
  888. var visibilityTool = GetTool(Tools.Visibility);
  889. if ((ITool) visibilityTool == tool)
  890. {
  891. m_State.lastVisibilityToolActive = visibilityTool.isActive;
  892. }
  893. }
  894. }
  895. }