A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3
4namespace UnityEngine.U2D.Animation
5{
6 internal static class SpriteSkinHelpers
7 {
8 public static void CacheChildren(Transform current, Dictionary<int, List<SpriteSkin.TransformData>> cache)
9 {
10 var nameHash = current.name.GetHashCode();
11 var entry = new SpriteSkin.TransformData()
12 {
13 fullName = string.Empty,
14 transform = current
15 };
16 if (cache.TryGetValue(nameHash, out var value))
17 value.Add(entry);
18 else
19 cache.Add(nameHash, new List<SpriteSkin.TransformData>(1) { entry });
20
21 for (var i = 0; i < current.childCount; ++i)
22 CacheChildren(current.GetChild(i), cache);
23 }
24
25 public static string GenerateTransformPath(Transform rootBone, Transform child)
26 {
27 var path = child.name;
28 if (child == rootBone)
29 return path;
30 var parent = child.parent;
31 do
32 {
33 path = parent.name + "/" + path;
34 parent = parent.parent;
35 } while (parent != rootBone && parent != null);
36
37 return path;
38 }
39
40 public static bool GetSpriteBonesTransforms(SpriteSkin spriteSkin, out Transform[] outTransform)
41 {
42 var rootBone = spriteSkin.rootBone;
43 var spriteBones = spriteSkin.sprite.GetBones();
44
45 if (rootBone == null)
46 throw new ArgumentException("rootBone parameter cannot be null");
47 if (spriteBones == null)
48 throw new ArgumentException("spriteBones parameter cannot be null");
49
50 outTransform = new Transform[spriteBones.Length];
51
52 var boneObjects = rootBone.GetComponentsInChildren<Bone>();
53 if (boneObjects != null && boneObjects.Length >= spriteBones.Length)
54 {
55 using (SpriteSkin.Profiling.getSpriteBonesTransformFromGuid.Auto())
56 {
57 var i = 0;
58 for (; i < spriteBones.Length; ++i)
59 {
60 var boneHash = spriteBones[i].guid;
61 var boneTransform = Array.Find(boneObjects, x => (x.guid == boneHash));
62 if (boneTransform == null)
63 break;
64
65 outTransform[i] = boneTransform.transform;
66 }
67
68 if (i >= spriteBones.Length)
69 return true;
70 }
71 }
72
73 var hierarchyCache = spriteSkin.hierarchyCache;
74 if (hierarchyCache.Count == 0)
75 spriteSkin.CacheHierarchy();
76
77 // If unable to successfully map via guid, fall back to path
78 return GetSpriteBonesTransformFromPath(spriteBones, hierarchyCache, outTransform);
79 }
80
81 static bool GetSpriteBonesTransformFromPath(SpriteBone[] spriteBones, Dictionary<int, List<SpriteSkin.TransformData>> hierarchyCache, Transform[] outNewBoneTransform)
82 {
83 using (SpriteSkin.Profiling.getSpriteBonesTransformFromPath.Auto())
84 {
85 string[] bonePath = null;
86 var foundBones = true;
87 for (var i = 0; i < spriteBones.Length; ++i)
88 {
89 var nameHash = spriteBones[i].name.GetHashCode();
90 if (!hierarchyCache.TryGetValue(nameHash, out var children))
91 {
92 outNewBoneTransform[i] = null;
93 foundBones = false;
94 continue;
95 }
96
97 if (children.Count == 1)
98 outNewBoneTransform[i] = children[0].transform;
99 else
100 {
101 if (bonePath == null)
102 bonePath = new string[spriteBones.Length];
103 if (bonePath[i] == null)
104 CalculateBoneTransformsPath(i, spriteBones, bonePath);
105
106 var m = 0;
107 for (; m < children.Count; ++m)
108 {
109 if (children[m].fullName.Contains(bonePath[i]))
110 {
111 outNewBoneTransform[i] = children[m].transform;
112 break;
113 }
114 }
115
116 if (m >= children.Count)
117 {
118 outNewBoneTransform[i] = null;
119 foundBones = false;
120 }
121 }
122 }
123
124 return foundBones;
125 }
126 }
127
128 static void CalculateBoneTransformsPath(int index, SpriteBone[] spriteBones, string[] paths)
129 {
130 var spriteBone = spriteBones[index];
131 var parentId = spriteBone.parentId;
132 var bonePath = spriteBone.name;
133 if (parentId != -1)
134 {
135 if (paths[parentId] == null)
136 CalculateBoneTransformsPath(spriteBone.parentId, spriteBones, paths);
137 paths[index] = $"{paths[parentId]}/{bonePath}";
138 }
139 else
140 paths[index] = bonePath;
141 }
142 }
143}