A game about forced loneliness, made by TACStudios
1using System.Collections.Generic;
2using System.Linq;
3using UnityEngine;
4
5namespace UnityEditor.U2D.Animation
6{
7 internal class SkeletonCache : TransformCache
8 {
9 [SerializeField]
10 bool m_IsPosePreview = false;
11 [SerializeField]
12 List<BoneCache> m_Bones = new List<BoneCache>();
13
14 public bool isPosePreview => m_IsPosePreview;
15
16 public int boneCount => m_Bones.Count;
17
18 public virtual BoneCache[] bones => m_Bones.ToArray();
19
20 public void AddBone(BoneCache bone, bool worldPositionStays = true)
21 {
22 Debug.Assert(bone != null);
23 Debug.Assert(!Contains(bone));
24
25 if (bone.parent == null)
26 bone.SetParent(this, worldPositionStays);
27
28 m_Bones.Add(bone);
29 }
30
31 public void ReorderBones(IEnumerable<BoneCache> boneCache)
32 {
33 if (boneCache.Count() == m_Bones.Count)
34 {
35 foreach (var b in m_Bones)
36 {
37 if (!boneCache.Contains(b))
38 return;
39 }
40
41 m_Bones = boneCache.ToList();
42 }
43 }
44
45 public void DestroyBone(BoneCache bone)
46 {
47 Debug.Assert(bone != null);
48 Debug.Assert(Contains(bone));
49
50 m_Bones.Remove(bone);
51
52 var boneChildren = bone.children;
53 foreach (var child in boneChildren)
54 child.SetParent(bone.parent);
55
56 skinningCache.Destroy(bone);
57 }
58
59 public void SetDefaultPose()
60 {
61 foreach (var bone in m_Bones)
62 bone.SetDefaultPose();
63
64 m_IsPosePreview = false;
65 }
66
67 public void RestoreDefaultPose()
68 {
69 foreach (var bone in m_Bones)
70 bone.RestoreDefaultPose();
71
72 m_IsPosePreview = false;
73 skinningCache.events.skeletonPreviewPoseChanged.Invoke(this);
74 }
75
76 public void SetPosePreview()
77 {
78 m_IsPosePreview = true;
79 }
80
81 public BonePose[] GetLocalPose()
82 {
83 var pose = new List<BonePose>();
84
85 foreach (var bone in m_Bones)
86 pose.Add(bone.localPose);
87
88 return pose.ToArray();
89 }
90
91 public void SetLocalPose(BonePose[] pose)
92 {
93 Debug.Assert(m_Bones.Count == pose.Length);
94
95 for (var i = 0; i < m_Bones.Count; ++i)
96 m_Bones[i].localPose = pose[i];
97
98 m_IsPosePreview = true;
99 }
100
101 public BonePose[] GetWorldPose()
102 {
103 var pose = new List<BonePose>();
104
105 foreach (var bone in m_Bones)
106 pose.Add(bone.worldPose);
107
108 return pose.ToArray();
109 }
110
111 public void SetWorldPose(BonePose[] pose)
112 {
113 Debug.Assert(m_Bones.Count == pose.Length);
114
115 for (var i = 0; i < m_Bones.Count; ++i)
116 {
117 var bone = m_Bones[i];
118 var childWoldPose = bone.GetChildrenWoldPose();
119 bone.worldPose = pose[i];
120 bone.SetChildrenWorldPose(childWoldPose);
121 }
122
123 m_IsPosePreview = true;
124 }
125
126 public BoneCache GetBone(int index)
127 {
128 return m_Bones[index];
129 }
130
131 public int IndexOf(BoneCache bone)
132 {
133 return m_Bones.IndexOf(bone);
134 }
135
136 public bool Contains(BoneCache bone)
137 {
138 return m_Bones.Contains(bone);
139 }
140
141 public void Clear()
142 {
143 var roots = children;
144
145 foreach (var root in roots)
146 DestroyHierarchy(root);
147
148 m_Bones.Clear();
149 }
150
151 public string GetUniqueName(BoneCache bone)
152 {
153 Debug.Assert(Contains(bone));
154
155 var boneName = bone.name;
156 var names = m_Bones.ConvertAll(b => b.name);
157 var index = IndexOf(bone);
158 var count = 0;
159
160 Debug.Assert(index < names.Count);
161
162 for (var i = 0; i < index; ++i)
163 if (names[i].Equals(boneName))
164 ++count;
165
166 return count == 0 ? boneName : $"{boneName} ({count + 1})";
167 }
168
169 void DestroyHierarchy(TransformCache root)
170 {
171 Debug.Assert(root != null);
172
173 var rootChildren = root.children;
174 foreach (var child in rootChildren)
175 DestroyHierarchy(child);
176
177 skinningCache.Destroy(root);
178 }
179 }
180}