SkinningCache.cs 37 KB

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