123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- namespace UnityEditor.U2D.Animation
- {
- internal class TransformCache : SkinningObject, IEnumerable<TransformCache>
- {
- [SerializeField]
- TransformCache m_Parent;
- [SerializeField]
- List<TransformCache> m_Children = new List<TransformCache>();
- [SerializeField]
- Vector3 m_LocalPosition;
- [SerializeField]
- Quaternion m_LocalRotation = Quaternion.identity;
- [SerializeField]
- Vector3 m_LocalScale = Vector3.one;
- [SerializeField]
- Matrix4x4 m_LocalToWorldMatrix = Matrix4x4.identity;
-
- public TransformCache parent => m_Parent;
-
- public TransformCache[] children => m_Children.ToArray();
-
- internal int siblingIndex
- {
- get => GetSiblingIndex();
- set => SetSiblingIndex(value);
- }
-
- public int childCount => m_Children.Count;
-
- public Vector3 localPosition
- {
- get => m_LocalPosition;
- set
- {
- m_LocalPosition = value;
- Update();
- }
- }
-
- public Quaternion localRotation
- {
- get => m_LocalRotation;
- set
- {
- m_LocalRotation = MathUtility.NormalizeQuaternion(value);
- Update();
- }
- }
-
- public Vector3 localScale
- {
- get => m_LocalScale;
- set
- {
- m_LocalScale = value;
- Update();
- }
- }
-
- public Vector3 position
- {
- get => parentMatrix.MultiplyPoint3x4(localPosition);
- set => localPosition = parentMatrix.inverse.MultiplyPoint3x4(value);
- }
-
- public Quaternion rotation
- {
- get => GetGlobalRotation();
- set => SetGlobalRotation(value);
- }
-
- public Vector3 right
- {
- get => localToWorldMatrix.MultiplyVector(Vector3.right).normalized;
- set => MatchDirection(Vector3.right, value);
- }
-
- public Vector3 up
- {
- get => localToWorldMatrix.MultiplyVector(Vector3.up).normalized;
- set => MatchDirection(Vector3.up, value);
- }
-
- public Vector3 forward
- {
- get => localToWorldMatrix.MultiplyVector(Vector3.forward).normalized;
- set => MatchDirection(Vector3.forward, value);
- }
-
- public Matrix4x4 localToWorldMatrix => m_LocalToWorldMatrix;
-
- public Matrix4x4 worldToLocalMatrix => localToWorldMatrix.inverse;
-
- Matrix4x4 parentMatrix
- {
- get
- {
- var matrix = Matrix4x4.identity;
- if (parent != null)
- matrix = parent.localToWorldMatrix;
- return matrix;
- }
- }
-
- internal override void OnDestroy()
- {
- if (parent != null)
- parent.RemoveChild(this);
-
- m_Parent = null;
- m_Children.Clear();
- }
-
- void Update()
- {
- m_LocalToWorldMatrix = parentMatrix * Matrix4x4.TRS(localPosition, localRotation, localScale);
-
- foreach (var child in m_Children)
- child.Update();
- }
-
- void AddChild(TransformCache transform)
- {
- m_Children.Add(transform);
- }
-
- void InsertChildAt(int index, TransformCache transform)
- {
- m_Children.Insert(index, transform);
- }
-
- void RemoveChild(TransformCache transform)
- {
- m_Children.Remove(transform);
- }
-
- void RemoveChildAt(int index)
- {
- m_Children.RemoveAt(index);
- }
-
- int GetSiblingIndex()
- {
- if (parent == null)
- return -1;
-
- return parent.m_Children.IndexOf(this);
- }
- void SetSiblingIndex(int index)
- {
- if (parent == null)
- return;
-
- var currentIndex = parent.m_Children.IndexOf(this);
- var indexToRemove = index < currentIndex ? currentIndex + 1 : currentIndex;
- parent.InsertChildAt(index, this);
- parent.RemoveChildAt(indexToRemove);
- }
-
- public void SetParent(TransformCache newParent, bool worldPositionStays = true)
- {
- if (m_Parent == newParent)
- return;
-
- var oldPosition = position;
- var oldRotation = rotation;
-
- if (m_Parent != null)
- m_Parent.RemoveChild(this);
-
- m_Parent = newParent;
-
- if (m_Parent != null)
- m_Parent.AddChild(this);
-
- if (worldPositionStays)
- {
- position = oldPosition;
- rotation = oldRotation;
- }
- else
- {
- Update();
- }
- }
-
- Quaternion GetGlobalRotation()
- {
- var globalRotation = localRotation;
- var currentParent = parent;
-
- while (currentParent != null)
- {
- globalRotation = ScaleMulQuaternion(currentParent.localScale, globalRotation);
- globalRotation = currentParent.localRotation * globalRotation;
- currentParent = currentParent.parent;
- }
-
- return globalRotation;
- }
-
- void SetGlobalRotation(Quaternion r)
- {
- if (parent != null)
- r = parent.InverseTransformRotation(r);
- localRotation = r;
- }
-
- Quaternion InverseTransformRotation(Quaternion r)
- {
- if (parent != null)
- r = parent.InverseTransformRotation(r);
-
- r = Quaternion.Inverse(localRotation) * r;
- r = ScaleMulQuaternion(localScale, r);
-
- return r;
- }
-
- static Quaternion ScaleMulQuaternion(Vector3 scale, Quaternion q)
- {
- var s = new Vector3(ChangeSign(1f, scale.x), ChangeSign(1f, scale.y), ChangeSign(1f, scale.z));
- q.x = ChangeSign(q.x, s.y * s.z);
- q.y = ChangeSign(q.y, s.x * s.z);
- q.z = ChangeSign(q.z, s.x * s.y);
- return q;
- }
-
- static float ChangeSign(float x, float y)
- {
- return y < 0f ? -x : x;
- }
-
- void MatchDirection(Vector3 localDirection, Vector3 worldDirection)
- {
- var direction = worldToLocalMatrix.MultiplyVector(worldDirection);
- direction = Matrix4x4.TRS(Vector3.zero, localRotation, localScale).MultiplyVector(direction);
- var scaledLocalDirection = Vector3.Scale(localDirection, localScale);
- var deltaRotation = Quaternion.identity;
-
- if (scaledLocalDirection.sqrMagnitude > 0f)
- {
- var axis = Vector3.Cross(scaledLocalDirection, direction);
- var angle = Vector3.SignedAngle(scaledLocalDirection, direction, axis);
- deltaRotation = Quaternion.AngleAxis(angle, axis);
- }
-
- localRotation = deltaRotation;
- }
-
- IEnumerator<TransformCache> IEnumerable<TransformCache>.GetEnumerator()
- {
- return m_Children.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return (IEnumerator)m_Children.GetEnumerator();
- }
- }
- }
|