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.

CopyTool.cs 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. using UnityEditor.U2D.Common;
  6. using UnityEditor.U2D.Layout;
  7. using UnityEngine.U2D;
  8. namespace UnityEditor.U2D.Animation
  9. {
  10. internal interface ICopyToolStringStore
  11. {
  12. string stringStore
  13. {
  14. get;
  15. set;
  16. }
  17. }
  18. internal class SystemCopyBufferStringStore : ICopyToolStringStore
  19. {
  20. public string stringStore
  21. {
  22. get => EditorGUIUtility.systemCopyBuffer;
  23. set => EditorGUIUtility.systemCopyBuffer = value;
  24. }
  25. }
  26. internal class BoneStorage
  27. {
  28. public BoneCache[] bones;
  29. public Dictionary<string, string> boneMapping;
  30. public BoneStorage(BoneCache[] bones, Dictionary<string, string> boneMapping = null)
  31. {
  32. this.bones = bones;
  33. this.boneMapping = boneMapping ?? new Dictionary<string, string>();
  34. }
  35. }
  36. internal class CopyTool : MeshToolWrapper
  37. {
  38. ICopyToolStringStore m_CopyToolStringStore;
  39. CopyToolView m_CopyToolView;
  40. bool m_HasValidCopyData = false;
  41. int m_LastCopyDataHash;
  42. public float pixelsPerUnit
  43. {
  44. private get;
  45. set;
  46. }
  47. public bool hasValidCopiedData
  48. {
  49. get
  50. {
  51. var hashCode = m_CopyToolStringStore.stringStore.GetHashCode();
  52. if (hashCode != m_LastCopyDataHash)
  53. {
  54. m_HasValidCopyData = IsValidCopyData(m_CopyToolStringStore.stringStore);
  55. m_LastCopyDataHash = hashCode;
  56. }
  57. return m_HasValidCopyData;
  58. }
  59. }
  60. public ICopyToolStringStore copyToolStringStore
  61. {
  62. set => m_CopyToolStringStore = value;
  63. }
  64. internal override void OnCreate()
  65. {
  66. m_CopyToolView = new CopyToolView();
  67. m_CopyToolView.onPasteActivated += OnPasteActivated;
  68. m_CopyToolStringStore = new SystemCopyBufferStringStore();
  69. disableMeshEditor = true;
  70. }
  71. public override void Initialize(LayoutOverlay layout)
  72. {
  73. m_CopyToolView.Initialize(layout);
  74. }
  75. protected override void OnActivate()
  76. {
  77. base.OnActivate();
  78. m_CopyToolView.Show(skinningCache.bonesReadOnly);
  79. }
  80. protected override void OnDeactivate()
  81. {
  82. base.OnDeactivate();
  83. m_CopyToolView.Hide();
  84. }
  85. void CopyMeshFromSpriteCache(SpriteCache sprite, SkinningCopySpriteData skinningSpriteData)
  86. {
  87. if (meshTool == null)
  88. return;
  89. meshTool.SetupSprite(sprite);
  90. skinningSpriteData.vertices = meshTool.mesh.vertices;
  91. skinningSpriteData.vertexWeights = meshTool.mesh.vertexWeights;
  92. skinningSpriteData.indices = meshTool.mesh.indices;
  93. skinningSpriteData.edges = meshTool.mesh.edges;
  94. skinningSpriteData.boneWeightGuids = new List<string>(meshTool.mesh.bones.Length);
  95. skinningSpriteData.boneWeightNames = new List<string>(meshTool.mesh.bones.Length);
  96. foreach (var bone in meshTool.mesh.bones)
  97. {
  98. skinningSpriteData.boneWeightGuids.Add(bone.guid);
  99. skinningSpriteData.boneWeightNames.Add(bone.name);
  100. }
  101. }
  102. public void OnCopyActivated()
  103. {
  104. SkinningCopyData skinningCopyData = null;
  105. var selectedSprite = skinningCache.selectedSprite;
  106. if (selectedSprite == null)
  107. {
  108. var sprites = skinningCache.GetSprites();
  109. if(!skinningCache.character || sprites.Length > 1)
  110. skinningCopyData = CopyAll();
  111. else if(sprites.Length == 1)
  112. skinningCopyData = CopySingle(sprites[0]);
  113. }
  114. else
  115. {
  116. skinningCopyData = CopySingle(selectedSprite);
  117. }
  118. if (skinningCopyData != null)
  119. m_CopyToolStringStore.stringStore = SkinningCopyUtility.SerializeSkinningCopyDataToString(skinningCopyData);
  120. skinningCache.events.copy.Invoke();
  121. }
  122. SkinningCopyData CopyAll()
  123. {
  124. var skinningCopyData = new SkinningCopyData
  125. {
  126. pixelsPerUnit = pixelsPerUnit,
  127. isCharacterData = skinningCache.hasCharacter,
  128. characterBones = skinningCache.hasCharacter
  129. ? skinningCache.character.skeleton.bones.ToSpriteBone(Matrix4x4.identity)
  130. : null
  131. };
  132. var sprites = skinningCache.GetSprites();
  133. foreach (var sprite in sprites)
  134. skinningCopyData.copyData.Add(GetDataForSprite(sprite));
  135. if (meshTool != null)
  136. meshTool.SetupSprite(null);
  137. return skinningCopyData;
  138. }
  139. SkinningCopyData CopySingle(SpriteCache sprite)
  140. {
  141. var skinningCopyData = new SkinningCopyData
  142. {
  143. pixelsPerUnit = pixelsPerUnit,
  144. isCharacterData = false,
  145. characterBones = Array.Empty<SpriteBone>()
  146. };
  147. skinningCopyData.copyData.Add(GetDataForSprite(sprite));
  148. return skinningCopyData;
  149. }
  150. SkinningCopySpriteData GetDataForSprite(SpriteCache sprite)
  151. {
  152. var skinningSpriteData = new SkinningCopySpriteData();
  153. skinningSpriteData.spriteName = sprite.name;
  154. CopyMeshFromSpriteCache(sprite, skinningSpriteData);
  155. // Bones
  156. var rootBones = new List<BoneCache>();
  157. var boneCache = Array.Empty<BoneCache>();
  158. if (skinningCache.hasCharacter)
  159. {
  160. var characterPart = skinningCache.GetCharacterPart(sprite);
  161. if (characterPart != null && characterPart.bones != null)
  162. {
  163. boneCache = characterPart.bones;
  164. var bones = characterPart.bones.FindRoots();
  165. foreach (var bone in bones)
  166. rootBones.Add(bone);
  167. }
  168. }
  169. else
  170. {
  171. var skeleton = skinningCache.GetEffectiveSkeleton(sprite);
  172. if (skeleton != null && skeleton.boneCount > 0)
  173. {
  174. boneCache = skeleton.bones;
  175. var bones = boneCache.FindRoots();
  176. foreach (var bone in bones)
  177. rootBones.Add(bone);
  178. }
  179. }
  180. if (rootBones.Count > 0)
  181. {
  182. skinningSpriteData.spriteBones = new List<SpriteBoneCopyData>();
  183. foreach (var rootBone in rootBones)
  184. {
  185. var rootBoneIndex = skinningSpriteData.spriteBones.Count;
  186. GetSpriteBoneDataRecursively(skinningSpriteData.spriteBones, rootBone, new List<BoneCache>(boneCache));
  187. if (skinningCache.hasCharacter)
  188. {
  189. // Offset the bones based on the currently selected Sprite in Character mode
  190. var characterPart = sprite.GetCharacterPart();
  191. if (characterPart != null)
  192. {
  193. var offset = characterPart.position;
  194. var rootSpriteBone = skinningSpriteData.spriteBones[rootBoneIndex];
  195. rootSpriteBone.spriteBone.position -= offset;
  196. skinningSpriteData.spriteBones[rootBoneIndex] = rootSpriteBone;
  197. }
  198. }
  199. }
  200. }
  201. return skinningSpriteData;
  202. }
  203. static void GetSpriteBoneDataRecursively(IList<SpriteBoneCopyData> bones, BoneCache rootBone, List<BoneCache> boneCache)
  204. {
  205. AppendSpriteBoneDataRecursively(bones, rootBone, -1, boneCache);
  206. }
  207. static void AppendSpriteBoneDataRecursively(IList<SpriteBoneCopyData> bones, BoneCache currentBone, int parentIndex, List<BoneCache> boneCache)
  208. {
  209. var currentParentIndex = bones.Count;
  210. var boneCopyData = new SpriteBoneCopyData()
  211. {
  212. spriteBone = new SpriteBone()
  213. {
  214. name = currentBone.name,
  215. guid = currentBone.guid,
  216. color = currentBone.bindPoseColor,
  217. parentId = parentIndex
  218. },
  219. order = boneCache.FindIndex(x => x == currentBone)
  220. };
  221. if (boneCopyData.order < 0)
  222. {
  223. boneCopyData.order = boneCache.Count;
  224. boneCache.Add(currentBone);
  225. }
  226. if (parentIndex == -1 && currentBone.parentBone != null)
  227. {
  228. boneCopyData.spriteBone.position = currentBone.position;
  229. boneCopyData.spriteBone.rotation = currentBone.rotation;
  230. }
  231. else
  232. {
  233. boneCopyData.spriteBone.position = currentBone.localPosition;
  234. boneCopyData.spriteBone.rotation = currentBone.localRotation;
  235. }
  236. boneCopyData.spriteBone.position = new Vector3(boneCopyData.spriteBone.position.x, boneCopyData.spriteBone.position.y, currentBone.depth);
  237. boneCopyData.spriteBone.length = currentBone.localLength;
  238. bones.Add(boneCopyData);
  239. foreach (var child in currentBone)
  240. {
  241. var childBone = child as BoneCache;
  242. if (childBone != null)
  243. AppendSpriteBoneDataRecursively(bones, childBone, currentParentIndex, boneCache);
  244. }
  245. }
  246. public void OnPasteActivated(bool shouldPasteBones, bool shouldPasteMesh, bool shouldFlipX, bool shouldFlipY)
  247. {
  248. var copyBuffer = m_CopyToolStringStore.stringStore;
  249. if (!IsValidCopyData(copyBuffer))
  250. return;
  251. var skinningCopyData = SkinningCopyUtility.DeserializeStringToSkinningCopyData(copyBuffer);
  252. if (skinningCopyData == null || skinningCopyData.copyData.Count == 0)
  253. return;
  254. var doesCopyContainMultipleSprites = skinningCopyData.copyData.Count > 1;
  255. var sprites = skinningCache.GetSprites();
  256. if (doesCopyContainMultipleSprites && skinningCopyData.copyData.Count != sprites.Length && shouldPasteMesh)
  257. {
  258. Debug.Log(string.Format(TextContent.copyIncorrectNumberOfSprites, skinningCopyData.copyData.Count, sprites.Length));
  259. return;
  260. }
  261. var selectedSprite = skinningCache.selectedSprite;
  262. using (skinningCache.UndoScope(TextContent.pasteData))
  263. {
  264. var scale = skinningCopyData.pixelsPerUnit > 0f ? pixelsPerUnit / skinningCopyData.pixelsPerUnit : 1f;
  265. var pastedBonesToSelect = new HashSet<BoneCache>();
  266. var characterBones = Array.Empty<BoneCache>();
  267. var replaceCharacterSkeleton = shouldPasteBones && skinningCache.hasCharacter && skinningCopyData.isCharacterData;
  268. if (replaceCharacterSkeleton)
  269. {
  270. var spriteBones = skinningCopyData.characterBones;
  271. characterBones = PasteBonesInCharacter(skinningCache, spriteBones, shouldFlipX, shouldFlipY, scale);
  272. foreach (var newBone in characterBones)
  273. pastedBonesToSelect.Add(newBone);
  274. }
  275. var pastedToSprites = new List<SpriteCache>();
  276. foreach (var copySpriteData in skinningCopyData.copyData)
  277. {
  278. SpriteCache sprite = null;
  279. if (selectedSprite != null && !doesCopyContainMultipleSprites)
  280. sprite = selectedSprite;
  281. if (sprite == null && !string.IsNullOrEmpty(copySpriteData.spriteName))
  282. sprite = FindSpriteWithName(sprites.Except(pastedToSprites).ToList(), copySpriteData.spriteName) ?? FindSpriteWithName(sprites, copySpriteData.spriteName);
  283. if (sprite == null)
  284. continue;
  285. pastedToSprites.Add(sprite);
  286. var boneMapping = new Dictionary<string, string>();
  287. if (shouldPasteBones && !replaceCharacterSkeleton)
  288. {
  289. var bonesToPaste = GetBonesInCorrectOrder(copySpriteData.spriteBones);
  290. var boneStorage = PasteBonesInSprite(skinningCache, sprite, bonesToPaste, characterBones, shouldFlipX, shouldFlipY, scale);
  291. if (boneStorage != null)
  292. {
  293. boneMapping = boneStorage.boneMapping;
  294. if (skinningCache.hasCharacter || sprite == selectedSprite)
  295. {
  296. foreach (var newBone in boneStorage.bones)
  297. pastedBonesToSelect.Add(newBone);
  298. }
  299. }
  300. }
  301. if (shouldPasteMesh)
  302. PasteMeshInSprite(meshTool, sprite, copySpriteData, shouldFlipX, shouldFlipY, scale, boneMapping);
  303. }
  304. var refreshSelection = skinningCache.hasCharacter || skinningCache.selectedSprite != null;
  305. if (refreshSelection)
  306. {
  307. var newBoneSelection = new BoneCache[pastedBonesToSelect.Count];
  308. pastedBonesToSelect.CopyTo(newBoneSelection);
  309. meshTool.SetupSprite(selectedSprite); // This is to refresh the selected Sprite in meshTool.
  310. skinningCache.skeletonSelection.elements = newBoneSelection;
  311. skinningCache.events.boneSelectionChanged.Invoke();
  312. }
  313. }
  314. skinningCache.events.paste.Invoke(shouldPasteBones, shouldPasteMesh, shouldFlipX, shouldFlipY);
  315. }
  316. static bool IsValidCopyData(string copyBuffer)
  317. {
  318. return SkinningCopyUtility.CanDeserializeStringToSkinningCopyData(copyBuffer);
  319. }
  320. static Vector3 GetFlippedBonePosition(BoneCache bone, Vector2 startPosition, Rect spriteRect, bool flipX, bool flipY)
  321. {
  322. Vector3 position = startPosition;
  323. if (flipX)
  324. position.x += spriteRect.width - bone.position.x;
  325. else
  326. position.x += bone.position.x;
  327. if (flipY)
  328. position.y += spriteRect.height - bone.position.y;
  329. else
  330. position.y += bone.position.y;
  331. position.z = bone.position.z;
  332. return position;
  333. }
  334. static Quaternion GetFlippedBoneRotation(BoneCache bone, bool flipX, bool flipY)
  335. {
  336. var euler = bone.rotation.eulerAngles;
  337. if (flipX)
  338. {
  339. if (euler.z <= 180)
  340. euler.z = 180 - euler.z;
  341. else
  342. euler.z = 540 - euler.z;
  343. }
  344. if (flipY)
  345. euler.z = 360 - euler.z;
  346. return Quaternion.Euler(euler);
  347. }
  348. static void SetBonePositionAndRotation(BoneCache[] boneCache, TransformCache bone, Vector3[] position, Quaternion[] rotation)
  349. {
  350. var index = Array.FindIndex(boneCache, x => x == bone);
  351. if (index >= 0)
  352. {
  353. bone.position = position[index];
  354. bone.rotation = rotation[index];
  355. }
  356. foreach (var child in bone.children)
  357. {
  358. SetBonePositionAndRotation(boneCache, child, position, rotation);
  359. }
  360. }
  361. static BoneCache[] PasteBonesInCharacter(SkinningCache skinningCache, SpriteBone[] spriteBones, bool shouldFlipX, bool shouldFlipY, float scale)
  362. {
  363. if (!skinningCache.hasCharacter)
  364. return null;
  365. var boneCache = skinningCache.CreateBoneCacheFromSpriteBones(spriteBones, scale);
  366. if (shouldFlipX || shouldFlipY)
  367. {
  368. var characterRect = new Rect(Vector2.zero, skinningCache.character.dimension);
  369. var newPositions = new Vector3[boneCache.Length];
  370. var newRotations = new Quaternion[boneCache.Length];
  371. for (var i = 0; i < boneCache.Length; ++i)
  372. {
  373. newPositions[i] = GetFlippedBonePosition(boneCache[i], Vector2.zero, characterRect, shouldFlipX, shouldFlipY);
  374. newRotations[i] = GetFlippedBoneRotation(boneCache[i], shouldFlipX, shouldFlipY);
  375. }
  376. for (var i = 0; i < boneCache.Length; ++i)
  377. {
  378. boneCache[i].position = newPositions[i];
  379. boneCache[i].rotation = newRotations[i];
  380. }
  381. }
  382. var skeleton = skinningCache.character.skeleton;
  383. skeleton.SetBones(boneCache);
  384. skinningCache.events.skeletonTopologyChanged.Invoke(skeleton);
  385. return boneCache;
  386. }
  387. static BoneStorage PasteBonesInSprite(SkinningCache skinningCache, SpriteCache sprite, SpriteBone[] newBones, BoneCache[] characterBones, bool shouldFlipX, bool shouldFlipY, float scale)
  388. {
  389. if (sprite == null || skinningCache.mode == SkinningMode.SpriteSheet && skinningCache.hasCharacter)
  390. return null;
  391. var spriteRect = sprite.textureRect;
  392. var skeleton = skinningCache.GetEffectiveSkeleton(sprite);
  393. var newBonesCache = skinningCache.CreateBoneCacheFromSpriteBones(newBones, scale);
  394. if (newBonesCache.Length == 0)
  395. return null;
  396. Vector2 rectPosition;
  397. if (skinningCache.mode == SkinningMode.Character)
  398. {
  399. var characterPart = sprite.GetCharacterPart();
  400. if (characterPart == null)
  401. return null;
  402. rectPosition = characterPart.position;
  403. }
  404. else
  405. rectPosition = spriteRect.position;
  406. var newPositions = new Vector3[newBonesCache.Length];
  407. var newRotations = new Quaternion[newBonesCache.Length];
  408. for (var i = 0; i < newBonesCache.Length; ++i)
  409. {
  410. newPositions[i] = GetFlippedBonePosition(newBonesCache[i], rectPosition, spriteRect, shouldFlipX, shouldFlipY);
  411. newRotations[i] = GetFlippedBoneRotation(newBonesCache[i], shouldFlipX, shouldFlipY);
  412. }
  413. foreach (var bone in newBonesCache)
  414. {
  415. if (bone.parent == null)
  416. {
  417. SetBonePositionAndRotation(newBonesCache, bone, newPositions, newRotations);
  418. if (skinningCache.mode == SkinningMode.Character)
  419. bone.SetParent(skeleton);
  420. }
  421. }
  422. var boneNameMapping = new Dictionary<string, string>();
  423. if (skinningCache.mode == SkinningMode.SpriteSheet)
  424. {
  425. skeleton.SetBones(newBonesCache);
  426. skeleton.SetDefaultPose();
  427. }
  428. else
  429. {
  430. boneNameMapping = AddBonesToSkeletonWithUniqueNames(characterBones, newBonesCache, skeleton);
  431. skeleton.SetDefaultPose();
  432. }
  433. skinningCache.events.skeletonTopologyChanged.Invoke(skeleton);
  434. return new BoneStorage(newBonesCache, boneNameMapping);
  435. }
  436. static Dictionary<string, string> AddBonesToSkeletonWithUniqueNames(IList<BoneCache> characterBones, IList<BoneCache> newBones, SkeletonCache skeleton)
  437. {
  438. var nameMapping = new Dictionary<string, string>();
  439. var existingBoneGuids = new HashSet<string>();
  440. var existingBoneNames = new HashSet<string>(skeleton.boneCount);
  441. for (var i = 0; i < characterBones.Count; i++)
  442. {
  443. if(!string.IsNullOrEmpty(characterBones[i].guid))
  444. existingBoneGuids.Add(characterBones[i].guid);
  445. }
  446. for (var i = 0; i < skeleton.boneCount; i++)
  447. existingBoneNames.Add(skeleton.bones[i].name);
  448. foreach (var newBone in newBones)
  449. {
  450. var guid = newBone.guid;
  451. if (string.IsNullOrEmpty(guid) || existingBoneGuids.Contains(guid))
  452. continue;
  453. var boneName = newBone.name;
  454. if (existingBoneNames.Contains(boneName))
  455. newBone.name = SkeletonController.AutoNameBoneCopy(boneName, skeleton.bones);
  456. existingBoneGuids.Add(newBone.guid);
  457. existingBoneNames.Add(newBone.name);
  458. nameMapping[boneName] = newBone.name;
  459. skeleton.AddBone(newBone);
  460. }
  461. return nameMapping;
  462. }
  463. static void PasteMeshInSprite(MeshTool meshTool, SpriteCache sprite, SkinningCopySpriteData copySpriteData, bool shouldFlipX, bool shouldFlipY, float scale, Dictionary<string, string> boneMapping)
  464. {
  465. if (meshTool == null || sprite == null)
  466. return;
  467. var vertices = copySpriteData.vertices ?? Array.Empty<Vector2>();
  468. var vertexWeights = copySpriteData.vertexWeights ?? Array.Empty<EditableBoneWeight>();
  469. meshTool.SetupSprite(sprite);
  470. meshTool.mesh.SetVertices(vertices, vertexWeights);
  471. if (!Mathf.Approximately(scale, 1f) || shouldFlipX || shouldFlipY)
  472. {
  473. var spriteRect = sprite.textureRect;
  474. for (var i = 0; i < meshTool.mesh.vertexCount; ++i)
  475. {
  476. var position = meshTool.mesh.vertices[i];
  477. if (!Mathf.Approximately(scale, 1f))
  478. position *= scale;
  479. if (shouldFlipX)
  480. position.x = spriteRect.width - meshTool.mesh.vertices[i].x;
  481. if (shouldFlipY)
  482. position.y = spriteRect.height - meshTool.mesh.vertices[i].y;
  483. meshTool.mesh.vertices[i] = position;
  484. }
  485. }
  486. meshTool.mesh.SetIndices(copySpriteData.indices);
  487. meshTool.mesh.SetEdges(copySpriteData.edges);
  488. var skinningCache = meshTool.skinningCache;
  489. var skeleton = skinningCache.GetEffectiveSkeleton(sprite);
  490. var hasGuids = copySpriteData.boneWeightGuids.Count > 0;
  491. for (var i = 0; i < copySpriteData.boneWeightGuids.Count; i++)
  492. {
  493. if (string.IsNullOrEmpty(copySpriteData.boneWeightGuids[i]))
  494. {
  495. hasGuids = false;
  496. break;
  497. }
  498. }
  499. var skeletonBones = skeleton.bones;
  500. var influenceBones = hasGuids ? GetBonesFromGuids(copySpriteData, skeletonBones, boneMapping) : GetBonesFromNames(copySpriteData, skeletonBones, boneMapping);
  501. // Update associated bones for mesh
  502. meshTool.mesh.SetCompatibleBoneSet(influenceBones);
  503. meshTool.mesh.bones = influenceBones; // Fixes weights for bones that do not exist
  504. // Update associated bones for character
  505. if (skinningCache.hasCharacter)
  506. {
  507. var characterPart = sprite.GetCharacterPart();
  508. if (characterPart != null)
  509. {
  510. characterPart.bones = influenceBones;
  511. skinningCache.events.characterPartChanged.Invoke(characterPart);
  512. }
  513. }
  514. meshTool.UpdateMesh();
  515. }
  516. static BoneCache[] GetBonesFromGuids(SkinningCopySpriteData copySpriteData, IList<BoneCache> skeletonBones, Dictionary<string, string> boneMapping)
  517. {
  518. var spriteBones = new List<BoneCache>();
  519. for (var i = 0; i < copySpriteData.boneWeightGuids.Count; i++)
  520. {
  521. var bone = FindBoneWithGuid(skeletonBones, copySpriteData.boneWeightGuids[i]);
  522. if (bone == null)
  523. continue;
  524. if (boneMapping != null && boneMapping.ContainsKey(bone.name))
  525. {
  526. bone = FindBoneWithName(skeletonBones, boneMapping[bone.name]);
  527. if (bone == null)
  528. continue;
  529. }
  530. spriteBones.Add(bone);
  531. }
  532. return spriteBones.ToArray();
  533. }
  534. static BoneCache[] GetBonesFromNames(SkinningCopySpriteData copySpriteData, IList<BoneCache> skeletonBones, Dictionary<string, string> boneMapping)
  535. {
  536. var spriteBones = new List<BoneCache>();
  537. for (var i = 0; i < copySpriteData.boneWeightNames.Count; ++i)
  538. {
  539. var boneName = copySpriteData.boneWeightNames[i];
  540. if (boneMapping != null && boneMapping.ContainsKey(boneName))
  541. boneName = boneMapping[boneName];
  542. var bone = FindBoneWithName(skeletonBones, boneName);
  543. if (bone == null)
  544. continue;
  545. spriteBones.Add(bone);
  546. }
  547. return spriteBones.ToArray();
  548. }
  549. static SpriteBone[] GetBonesInCorrectOrder(IList<SpriteBoneCopyData> spriteBones)
  550. {
  551. var orderedBones = new SpriteBone[spriteBones.Count];
  552. for (var i = 0; i < spriteBones.Count; ++i)
  553. {
  554. var order = spriteBones[i].order;
  555. if (order >= 0)
  556. {
  557. orderedBones[order] = spriteBones[i].spriteBone;
  558. var parentId = orderedBones[order].parentId;
  559. if (parentId >= 0)
  560. orderedBones[order].parentId = spriteBones[parentId].order;
  561. }
  562. else
  563. {
  564. orderedBones[i] = spriteBones[i].spriteBone;
  565. }
  566. }
  567. return orderedBones;
  568. }
  569. static SpriteCache FindSpriteWithName(IList<SpriteCache> sprites, string spriteName)
  570. {
  571. for (var i = 0; i < sprites.Count; i++)
  572. {
  573. var sprite = sprites[i];
  574. if (sprite.name == spriteName)
  575. return sprite;
  576. }
  577. return null;
  578. }
  579. static BoneCache FindBoneWithName(IList<BoneCache> bones, string boneName)
  580. {
  581. for (var i = 0; i < bones.Count; i++)
  582. {
  583. var bone = bones[i];
  584. if (bone.name == boneName)
  585. return bone;
  586. }
  587. return null;
  588. }
  589. static BoneCache FindBoneWithGuid(IList<BoneCache> bones, string guid)
  590. {
  591. for (var i = 0; i < bones.Count; i++)
  592. {
  593. var bone = bones[i];
  594. if (bone.guid == guid)
  595. return bone;
  596. }
  597. return null;
  598. }
  599. }
  600. internal class CopyToolView
  601. {
  602. PastePanel m_PastePanel;
  603. public event Action<bool, bool, bool, bool> onPasteActivated = (bone, mesh, flipX, flipY) => {};
  604. public void Show(bool readonlyBone)
  605. {
  606. m_PastePanel.SetHiddenFromLayout(false);
  607. m_PastePanel.BonePasteEnable(!readonlyBone);
  608. }
  609. public void Hide()
  610. {
  611. m_PastePanel.SetHiddenFromLayout(true);
  612. }
  613. public void Initialize(LayoutOverlay layoutOverlay)
  614. {
  615. m_PastePanel = PastePanel.GenerateFromUXML();
  616. BindElements();
  617. layoutOverlay.rightOverlay.Add(m_PastePanel);
  618. m_PastePanel.SetHiddenFromLayout(true);
  619. }
  620. void BindElements()
  621. {
  622. m_PastePanel.onPasteActivated += OnPasteActivated;
  623. }
  624. void OnPasteActivated(bool bone, bool mesh, bool flipX, bool flipY)
  625. {
  626. onPasteActivated(bone, mesh, flipX, flipY);
  627. }
  628. }
  629. }