Açıklama Yok
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 37KB

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