暫無描述
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

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