Nessuna descrizione
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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  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. {
  251. Debug.LogError(TextContent.copyError1);
  252. return;
  253. }
  254. var skinningCopyData = SkinningCopyUtility.DeserializeStringToSkinningCopyData(copyBuffer);
  255. if (skinningCopyData == null || skinningCopyData.copyData.Count == 0)
  256. {
  257. Debug.LogError(TextContent.copyError2);
  258. return;
  259. }
  260. var doesCopyContainMultipleSprites = skinningCopyData.copyData.Count > 1;
  261. var sprites = skinningCache.GetSprites();
  262. if (doesCopyContainMultipleSprites && skinningCopyData.copyData.Count != sprites.Length && shouldPasteMesh)
  263. {
  264. Debug.LogError(string.Format(TextContent.copyError3, sprites.Length, skinningCopyData.copyData.Count));
  265. return;
  266. }
  267. var selectedSprite = skinningCache.selectedSprite;
  268. using (skinningCache.UndoScope(TextContent.pasteData))
  269. {
  270. var scale = skinningCopyData.pixelsPerUnit > 0f ? pixelsPerUnit / skinningCopyData.pixelsPerUnit : 1f;
  271. var pastedBonesToSelect = new HashSet<BoneCache>();
  272. var characterBones = Array.Empty<BoneCache>();
  273. var replaceCharacterSkeleton = shouldPasteBones && skinningCache.hasCharacter && skinningCopyData.isCharacterData;
  274. if (replaceCharacterSkeleton)
  275. {
  276. var spriteBones = skinningCopyData.characterBones;
  277. characterBones = PasteBonesInCharacter(skinningCache, spriteBones, shouldFlipX, shouldFlipY, scale);
  278. foreach (var newBone in characterBones)
  279. pastedBonesToSelect.Add(newBone);
  280. }
  281. var pastedToSprites = new List<SpriteCache>();
  282. foreach (var copySpriteData in skinningCopyData.copyData)
  283. {
  284. SpriteCache sprite = null;
  285. if (selectedSprite != null && !doesCopyContainMultipleSprites)
  286. sprite = selectedSprite;
  287. if (sprite == null && !string.IsNullOrEmpty(copySpriteData.spriteName))
  288. sprite = FindSpriteWithName(sprites.Except(pastedToSprites).ToList(), copySpriteData.spriteName) ?? FindSpriteWithName(sprites, copySpriteData.spriteName);
  289. if (sprite == null)
  290. continue;
  291. pastedToSprites.Add(sprite);
  292. var boneMapping = new Dictionary<string, string>();
  293. if (shouldPasteBones && !replaceCharacterSkeleton)
  294. {
  295. var bonesToPaste = GetBonesInCorrectOrder(copySpriteData.spriteBones);
  296. var boneStorage = PasteBonesInSprite(skinningCache, sprite, bonesToPaste, characterBones, shouldFlipX, shouldFlipY, scale);
  297. if (boneStorage != null)
  298. {
  299. boneMapping = boneStorage.boneMapping;
  300. if (skinningCache.hasCharacter || sprite == selectedSprite)
  301. {
  302. foreach (var newBone in boneStorage.bones)
  303. pastedBonesToSelect.Add(newBone);
  304. }
  305. }
  306. }
  307. if (shouldPasteMesh)
  308. PasteMeshInSprite(meshTool, sprite, copySpriteData, shouldFlipX, shouldFlipY, scale, boneMapping);
  309. }
  310. var refreshSelection = skinningCache.hasCharacter || skinningCache.selectedSprite != null;
  311. if (refreshSelection)
  312. {
  313. var newBoneSelection = new BoneCache[pastedBonesToSelect.Count];
  314. pastedBonesToSelect.CopyTo(newBoneSelection);
  315. meshTool.SetupSprite(selectedSprite); // This is to refresh the selected Sprite in meshTool.
  316. skinningCache.skeletonSelection.elements = newBoneSelection;
  317. skinningCache.events.boneSelectionChanged.Invoke();
  318. }
  319. }
  320. skinningCache.events.paste.Invoke(shouldPasteBones, shouldPasteMesh, shouldFlipX, shouldFlipY);
  321. }
  322. static bool IsValidCopyData(string copyBuffer)
  323. {
  324. return SkinningCopyUtility.CanDeserializeStringToSkinningCopyData(copyBuffer);
  325. }
  326. static Vector3 GetFlippedBonePosition(BoneCache bone, Vector2 startPosition, Rect spriteRect, bool flipX, bool flipY)
  327. {
  328. Vector3 position = startPosition;
  329. if (flipX)
  330. position.x += spriteRect.width - bone.position.x;
  331. else
  332. position.x += bone.position.x;
  333. if (flipY)
  334. position.y += spriteRect.height - bone.position.y;
  335. else
  336. position.y += bone.position.y;
  337. position.z = bone.position.z;
  338. return position;
  339. }
  340. static Quaternion GetFlippedBoneRotation(BoneCache bone, bool flipX, bool flipY)
  341. {
  342. var euler = bone.rotation.eulerAngles;
  343. if (flipX)
  344. {
  345. if (euler.z <= 180)
  346. euler.z = 180 - euler.z;
  347. else
  348. euler.z = 540 - euler.z;
  349. }
  350. if (flipY)
  351. euler.z = 360 - euler.z;
  352. return Quaternion.Euler(euler);
  353. }
  354. static void SetBonePositionAndRotation(BoneCache[] boneCache, TransformCache bone, Vector3[] position, Quaternion[] rotation)
  355. {
  356. var index = Array.FindIndex(boneCache, x => x == bone);
  357. if (index >= 0)
  358. {
  359. bone.position = position[index];
  360. bone.rotation = rotation[index];
  361. }
  362. foreach (var child in bone.children)
  363. {
  364. SetBonePositionAndRotation(boneCache, child, position, rotation);
  365. }
  366. }
  367. static BoneCache[] PasteBonesInCharacter(SkinningCache skinningCache, SpriteBone[] spriteBones, bool shouldFlipX, bool shouldFlipY, float scale)
  368. {
  369. if (!skinningCache.hasCharacter)
  370. return null;
  371. var boneCache = skinningCache.CreateBoneCacheFromSpriteBones(spriteBones, scale);
  372. if (shouldFlipX || shouldFlipY)
  373. {
  374. var characterRect = new Rect(Vector2.zero, skinningCache.character.dimension);
  375. var newPositions = new Vector3[boneCache.Length];
  376. var newRotations = new Quaternion[boneCache.Length];
  377. for (var i = 0; i < boneCache.Length; ++i)
  378. {
  379. newPositions[i] = GetFlippedBonePosition(boneCache[i], Vector2.zero, characterRect, shouldFlipX, shouldFlipY);
  380. newRotations[i] = GetFlippedBoneRotation(boneCache[i], shouldFlipX, shouldFlipY);
  381. }
  382. for (var i = 0; i < boneCache.Length; ++i)
  383. {
  384. boneCache[i].position = newPositions[i];
  385. boneCache[i].rotation = newRotations[i];
  386. }
  387. }
  388. var skeleton = skinningCache.character.skeleton;
  389. skeleton.SetBones(boneCache);
  390. skinningCache.events.skeletonTopologyChanged.Invoke(skeleton);
  391. return boneCache;
  392. }
  393. static BoneStorage PasteBonesInSprite(SkinningCache skinningCache, SpriteCache sprite, SpriteBone[] newBones, BoneCache[] characterBones, bool shouldFlipX, bool shouldFlipY, float scale)
  394. {
  395. if (sprite == null || skinningCache.mode == SkinningMode.SpriteSheet && skinningCache.hasCharacter)
  396. return null;
  397. var spriteRect = sprite.textureRect;
  398. var skeleton = skinningCache.GetEffectiveSkeleton(sprite);
  399. var newBonesCache = skinningCache.CreateBoneCacheFromSpriteBones(newBones, scale);
  400. if (newBonesCache.Length == 0)
  401. return null;
  402. Vector2 rectPosition;
  403. if (skinningCache.mode == SkinningMode.Character)
  404. {
  405. var characterPart = sprite.GetCharacterPart();
  406. if (characterPart == null)
  407. return null;
  408. rectPosition = characterPart.position;
  409. }
  410. else
  411. rectPosition = spriteRect.position;
  412. var newPositions = new Vector3[newBonesCache.Length];
  413. var newRotations = new Quaternion[newBonesCache.Length];
  414. for (var i = 0; i < newBonesCache.Length; ++i)
  415. {
  416. newPositions[i] = GetFlippedBonePosition(newBonesCache[i], rectPosition, spriteRect, shouldFlipX, shouldFlipY);
  417. newRotations[i] = GetFlippedBoneRotation(newBonesCache[i], shouldFlipX, shouldFlipY);
  418. }
  419. foreach (var bone in newBonesCache)
  420. {
  421. if (bone.parent == null)
  422. {
  423. SetBonePositionAndRotation(newBonesCache, bone, newPositions, newRotations);
  424. if (skinningCache.mode == SkinningMode.Character)
  425. bone.SetParent(skeleton);
  426. }
  427. }
  428. var boneNameMapping = new Dictionary<string, string>();
  429. if (skinningCache.mode == SkinningMode.SpriteSheet)
  430. {
  431. skeleton.SetBones(newBonesCache);
  432. skeleton.SetDefaultPose();
  433. }
  434. else
  435. {
  436. boneNameMapping = AddBonesToSkeletonWithUniqueNames(characterBones, newBonesCache, skeleton);
  437. skeleton.SetDefaultPose();
  438. }
  439. skinningCache.events.skeletonTopologyChanged.Invoke(skeleton);
  440. return new BoneStorage(newBonesCache, boneNameMapping);
  441. }
  442. static Dictionary<string, string> AddBonesToSkeletonWithUniqueNames(IList<BoneCache> characterBones, IList<BoneCache> newBones, SkeletonCache skeleton)
  443. {
  444. var nameMapping = new Dictionary<string, string>();
  445. var existingBoneGuids = new HashSet<string>();
  446. var existingBoneNames = new HashSet<string>(skeleton.boneCount);
  447. for (var i = 0; i < characterBones.Count; i++)
  448. {
  449. if(!string.IsNullOrEmpty(characterBones[i].guid))
  450. existingBoneGuids.Add(characterBones[i].guid);
  451. }
  452. for (var i = 0; i < skeleton.boneCount; i++)
  453. existingBoneNames.Add(skeleton.bones[i].name);
  454. foreach (var newBone in newBones)
  455. {
  456. var guid = newBone.guid;
  457. if (string.IsNullOrEmpty(guid) || existingBoneGuids.Contains(guid))
  458. continue;
  459. var boneName = newBone.name;
  460. if (existingBoneNames.Contains(boneName))
  461. newBone.name = SkeletonController.AutoNameBoneCopy(boneName, skeleton.bones);
  462. existingBoneGuids.Add(newBone.guid);
  463. existingBoneNames.Add(newBone.name);
  464. nameMapping[boneName] = newBone.name;
  465. skeleton.AddBone(newBone);
  466. }
  467. return nameMapping;
  468. }
  469. static void PasteMeshInSprite(MeshTool meshTool, SpriteCache sprite, SkinningCopySpriteData copySpriteData, bool shouldFlipX, bool shouldFlipY, float scale, Dictionary<string, string> boneMapping)
  470. {
  471. if (meshTool == null || sprite == null)
  472. return;
  473. var vertices = copySpriteData.vertices ?? Array.Empty<Vector2>();
  474. var vertexWeights = copySpriteData.vertexWeights ?? Array.Empty<EditableBoneWeight>();
  475. meshTool.SetupSprite(sprite);
  476. meshTool.mesh.SetVertices(vertices, vertexWeights);
  477. if (!Mathf.Approximately(scale, 1f) || shouldFlipX || shouldFlipY)
  478. {
  479. var spriteRect = sprite.textureRect;
  480. for (var i = 0; i < meshTool.mesh.vertexCount; ++i)
  481. {
  482. var position = meshTool.mesh.vertices[i];
  483. if (!Mathf.Approximately(scale, 1f))
  484. position *= scale;
  485. if (shouldFlipX)
  486. position.x = spriteRect.width - meshTool.mesh.vertices[i].x;
  487. if (shouldFlipY)
  488. position.y = spriteRect.height - meshTool.mesh.vertices[i].y;
  489. meshTool.mesh.vertices[i] = position;
  490. }
  491. }
  492. meshTool.mesh.SetIndices(copySpriteData.indices);
  493. meshTool.mesh.SetEdges(copySpriteData.edges);
  494. var skinningCache = meshTool.skinningCache;
  495. var skeleton = skinningCache.GetEffectiveSkeleton(sprite);
  496. var hasGuids = copySpriteData.boneWeightGuids.Count > 0;
  497. for (var i = 0; i < copySpriteData.boneWeightGuids.Count; i++)
  498. {
  499. if (string.IsNullOrEmpty(copySpriteData.boneWeightGuids[i]))
  500. {
  501. hasGuids = false;
  502. break;
  503. }
  504. }
  505. var skeletonBones = skeleton.bones;
  506. var influenceBones = hasGuids ? GetBonesFromGuids(copySpriteData, skeletonBones, boneMapping) : GetBonesFromNames(copySpriteData, skeletonBones, boneMapping);
  507. // Update associated bones for mesh
  508. meshTool.mesh.SetCompatibleBoneSet(influenceBones);
  509. meshTool.mesh.bones = influenceBones; // Fixes weights for bones that do not exist
  510. // Update associated bones for character
  511. if (skinningCache.hasCharacter)
  512. {
  513. var characterPart = sprite.GetCharacterPart();
  514. if (characterPart != null)
  515. {
  516. characterPart.bones = influenceBones;
  517. skinningCache.events.characterPartChanged.Invoke(characterPart);
  518. }
  519. }
  520. meshTool.UpdateMesh();
  521. }
  522. static BoneCache[] GetBonesFromGuids(SkinningCopySpriteData copySpriteData, IList<BoneCache> skeletonBones, Dictionary<string, string> boneMapping)
  523. {
  524. var spriteBones = new List<BoneCache>();
  525. for (var i = 0; i < copySpriteData.boneWeightGuids.Count; i++)
  526. {
  527. var bone = FindBoneWithGuid(skeletonBones, copySpriteData.boneWeightGuids[i]);
  528. if (bone == null)
  529. continue;
  530. if (boneMapping != null && boneMapping.ContainsKey(bone.name))
  531. {
  532. bone = FindBoneWithName(skeletonBones, boneMapping[bone.name]);
  533. if (bone == null)
  534. continue;
  535. }
  536. spriteBones.Add(bone);
  537. }
  538. return spriteBones.ToArray();
  539. }
  540. static BoneCache[] GetBonesFromNames(SkinningCopySpriteData copySpriteData, IList<BoneCache> skeletonBones, Dictionary<string, string> boneMapping)
  541. {
  542. var spriteBones = new List<BoneCache>();
  543. for (var i = 0; i < copySpriteData.boneWeightNames.Count; ++i)
  544. {
  545. var boneName = copySpriteData.boneWeightNames[i];
  546. if (boneMapping != null && boneMapping.ContainsKey(boneName))
  547. boneName = boneMapping[boneName];
  548. var bone = FindBoneWithName(skeletonBones, boneName);
  549. if (bone == null)
  550. continue;
  551. spriteBones.Add(bone);
  552. }
  553. return spriteBones.ToArray();
  554. }
  555. static SpriteBone[] GetBonesInCorrectOrder(IList<SpriteBoneCopyData> spriteBones)
  556. {
  557. var orderedBones = new SpriteBone[spriteBones.Count];
  558. for (var i = 0; i < spriteBones.Count; ++i)
  559. {
  560. var order = spriteBones[i].order;
  561. if (order >= 0)
  562. {
  563. orderedBones[order] = spriteBones[i].spriteBone;
  564. var parentId = orderedBones[order].parentId;
  565. if (parentId >= 0)
  566. orderedBones[order].parentId = spriteBones[parentId].order;
  567. }
  568. else
  569. {
  570. orderedBones[i] = spriteBones[i].spriteBone;
  571. }
  572. }
  573. return orderedBones;
  574. }
  575. static SpriteCache FindSpriteWithName(IList<SpriteCache> sprites, string spriteName)
  576. {
  577. for (var i = 0; i < sprites.Count; i++)
  578. {
  579. var sprite = sprites[i];
  580. if (sprite.name == spriteName)
  581. return sprite;
  582. }
  583. return null;
  584. }
  585. static BoneCache FindBoneWithName(IList<BoneCache> bones, string boneName)
  586. {
  587. for (var i = 0; i < bones.Count; i++)
  588. {
  589. var bone = bones[i];
  590. if (bone.name == boneName)
  591. return bone;
  592. }
  593. return null;
  594. }
  595. static BoneCache FindBoneWithGuid(IList<BoneCache> bones, string guid)
  596. {
  597. for (var i = 0; i < bones.Count; i++)
  598. {
  599. var bone = bones[i];
  600. if (bone.guid == guid)
  601. return bone;
  602. }
  603. return null;
  604. }
  605. }
  606. internal class CopyToolView
  607. {
  608. PastePanel m_PastePanel;
  609. public event Action<bool, bool, bool, bool> onPasteActivated = (bone, mesh, flipX, flipY) => {};
  610. public void Show(bool readonlyBone)
  611. {
  612. m_PastePanel.SetHiddenFromLayout(false);
  613. m_PastePanel.BonePasteEnable(!readonlyBone);
  614. }
  615. public void Hide()
  616. {
  617. m_PastePanel.SetHiddenFromLayout(true);
  618. }
  619. public void Initialize(LayoutOverlay layoutOverlay)
  620. {
  621. m_PastePanel = PastePanel.GenerateFromUXML();
  622. BindElements();
  623. layoutOverlay.rightOverlay.Add(m_PastePanel);
  624. m_PastePanel.SetHiddenFromLayout(true);
  625. }
  626. void BindElements()
  627. {
  628. m_PastePanel.onPasteActivated += OnPasteActivated;
  629. }
  630. void OnPasteActivated(bool bone, bool mesh, bool flipX, bool flipY)
  631. {
  632. onPasteActivated(bone, mesh, flipX, flipY);
  633. }
  634. }
  635. }