A game about forced loneliness, made by TACStudios
at master 318 lines 8.6 kB view raw
1using System; 2using UnityEngine; 3 4namespace UnityEditor.U2D.Animation 5{ 6 [Serializable] 7 internal struct Pose 8 { 9 public Vector3 position; 10 public Quaternion rotation; 11 public Matrix4x4 matrix => Matrix4x4.TRS(position, rotation, Vector3.one); 12 13 public static Pose Create(Vector3 p, Quaternion r) 14 { 15 var pose = new Pose() 16 { 17 position = p, 18 rotation = r 19 }; 20 21 return pose; 22 } 23 24 public override bool Equals(object other) 25 { 26 return other is Pose && this == (Pose)other; 27 } 28 29 public override int GetHashCode() 30 { 31 return position.GetHashCode() ^ rotation.GetHashCode(); 32 } 33 34 public static bool operator ==(Pose p1, Pose p2) 35 { 36 return p1.position == p2.position && p1.rotation == p2.rotation; 37 } 38 39 public static bool operator !=(Pose p1, Pose p2) 40 { 41 return !(p1 == p2); 42 } 43 } 44 45 [Serializable] 46 internal struct BonePose 47 { 48 public Pose pose; 49 public float length; 50 public static BonePose Create(Pose p, float l) 51 { 52 var pose = new BonePose() 53 { 54 pose = p, 55 length = l 56 }; 57 58 return pose; 59 } 60 61 public override bool Equals(object other) 62 { 63 return other is BonePose && this == (BonePose)other; 64 } 65 66 public override int GetHashCode() 67 { 68 return pose.GetHashCode() ^ length.GetHashCode(); 69 } 70 71 public static bool operator ==(BonePose p1, BonePose p2) 72 { 73 return p1.pose == p2.pose && Mathf.Abs(p1.length - p2.length) < Mathf.Epsilon; 74 } 75 76 public static bool operator !=(BonePose p1, BonePose p2) 77 { 78 return !(p1 == p2); 79 } 80 } 81 82 internal class BoneCache : TransformCache 83 { 84 [SerializeField] 85 Color32 m_BindPoseColor; 86 [SerializeField] 87 Pose m_BindPose; 88 [SerializeField] 89 BonePose m_DefaultPose; 90 [SerializeField] 91 BoneCache m_ChainedChild; 92 [SerializeField] 93 float m_Depth; 94 [SerializeField] 95 float m_LocalLength = 1f; 96 [SerializeField] 97 bool m_IsVisible = true; 98 [SerializeField] 99 string m_Guid; 100 101 public bool NotInDefaultPose() 102 { 103 return localPosition != m_DefaultPose.pose.position 104 || localRotation != m_DefaultPose.pose.rotation 105 || Mathf.Abs(localLength - m_DefaultPose.length) > Mathf.Epsilon; 106 } 107 108 public bool isVisible 109 { 110 get => m_IsVisible; 111 set => m_IsVisible = value; 112 } 113 114 public Color bindPoseColor 115 { 116 get => m_BindPoseColor; 117 set => m_BindPoseColor = value; 118 } 119 120 public virtual BoneCache parentBone => parent as BoneCache; 121 122 public SkeletonCache skeleton 123 { 124 get 125 { 126 var parentSkeleton = parent as SkeletonCache; 127 if (parentSkeleton != null) 128 return parentSkeleton; 129 130 return parentBone != null ? parentBone.skeleton : null; 131 } 132 } 133 134 public virtual BoneCache chainedChild 135 { 136 get 137 { 138 if (m_ChainedChild != null && m_ChainedChild.parentBone == this) 139 return m_ChainedChild; 140 141 return null; 142 } 143 set 144 { 145 if (m_ChainedChild != value) 146 { 147 if (value == null || value.parentBone == this) 148 { 149 m_ChainedChild = value; 150 if (m_ChainedChild != null) 151 OrientToChainedChild(false); 152 } 153 } 154 } 155 } 156 157 Vector3 localEndPosition => Vector3.right * localLength; 158 159 public Vector3 endPosition 160 { 161 get => localToWorldMatrix.MultiplyPoint3x4(localEndPosition); 162 set 163 { 164 if (chainedChild != null) 165 return; 166 167 var direction = value - position; 168 right = direction; 169 length = direction.magnitude; 170 } 171 } 172 173 public BonePose localPose 174 { 175 get => BonePose.Create(Pose.Create(localPosition, localRotation), localLength); 176 set 177 { 178 localPosition = value.pose.position; 179 localRotation = value.pose.rotation; 180 localLength = value.length; 181 } 182 } 183 184 public BonePose worldPose 185 { 186 get => BonePose.Create(Pose.Create(position, rotation), length); 187 set 188 { 189 position = value.pose.position; 190 rotation = value.pose.rotation; 191 length = value.length; 192 } 193 } 194 195 public Pose bindPose => m_BindPose; 196 197 public string guid 198 { 199 get => m_Guid; 200 set => m_Guid = value; 201 } 202 203 public float depth 204 { 205 get => m_Depth; 206 set => m_Depth = value; 207 } 208 public float localLength 209 { 210 get => m_LocalLength; 211 set => m_LocalLength = Mathf.Max(0f, value); 212 } 213 214 public float length 215 { 216 get => localToWorldMatrix.MultiplyVector(localEndPosition).magnitude; 217 set => m_LocalLength = worldToLocalMatrix.MultiplyVector(right * Mathf.Max(0f, value)).magnitude; 218 } 219 220 internal Pose[] GetChildrenWoldPose() 221 { 222 return Array.ConvertAll(children, c => Pose.Create(c.position, c.rotation)); 223 } 224 225 internal void SetChildrenWorldPose(Pose[] worldPoses) 226 { 227 var childrenArray = children; 228 229 Debug.Assert(childrenArray.Length == worldPoses.Length); 230 231 for (var i = 0; i < childrenArray.Length; ++i) 232 { 233 var child = childrenArray[i]; 234 var pose = worldPoses[i]; 235 236 child.position = pose.position; 237 child.rotation = pose.rotation; 238 } 239 } 240 241 internal override void OnDestroy() 242 { 243 base.OnDestroy(); 244 m_ChainedChild = null; 245 } 246 247 public new void SetParent(TransformCache newParent, bool worldPositionStays = true) 248 { 249 if (parentBone != null && parentBone.chainedChild == this) 250 parentBone.chainedChild = null; 251 252 base.SetParent(newParent, worldPositionStays); 253 254 if (parentBone != null && parentBone.chainedChild == null && (parentBone.endPosition - position).sqrMagnitude < 0.001f) 255 parentBone.chainedChild = this; 256 } 257 258 public void OrientToChainedChild(bool freezeChildren) 259 { 260 Debug.Assert(chainedChild != null); 261 262 var childPosition = chainedChild.position; 263 var childRotation = chainedChild.rotation; 264 265 Pose[] childrenWorldPose = null; 266 267 if (freezeChildren) 268 childrenWorldPose = GetChildrenWoldPose(); 269 270 right = childPosition - position; 271 272 if (freezeChildren) 273 { 274 SetChildrenWorldPose(childrenWorldPose); 275 } 276 else 277 { 278 chainedChild.position = childPosition; 279 chainedChild.rotation = childRotation; 280 } 281 282 length = (childPosition - position).magnitude; 283 } 284 285 public void SetDefaultPose() 286 { 287 m_DefaultPose = localPose; 288 289 if (IsUnscaled()) 290 m_BindPose = worldPose.pose; 291 else 292 throw new Exception("BindPose cannot be set under global scale"); 293 } 294 295 public void RestoreDefaultPose() 296 { 297 localPose = m_DefaultPose; 298 } 299 300 bool IsUnscaled() 301 { 302 var currentTransform = this as TransformCache; 303 304 while (currentTransform != null) 305 { 306 var scale = currentTransform.localScale; 307 var isUnscaled = Mathf.Approximately(scale.x, 1f) && Mathf.Approximately(scale.y, 1f) && Mathf.Approximately(scale.z, 1f); 308 309 if (!isUnscaled) 310 return false; 311 312 currentTransform = currentTransform.parent; 313 } 314 315 return true; 316 } 317 } 318}