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