123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- namespace UnityEditor.U2D.Animation
- {
- internal class TransformCache : SkinningObject, IEnumerable<TransformCache>
- {
- [SerializeField]
- private TransformCache m_Parent;
- [SerializeField]
- private List<TransformCache> m_Children = new List<TransformCache>();
- [SerializeField]
- private Vector3 m_LocalPosition;
- [SerializeField]
- private Quaternion m_LocalRotation = Quaternion.identity;
- [SerializeField]
- private Vector3 m_LocalScale = Vector3.one;
- [SerializeField]
- private Matrix4x4 m_LocalToWorldMatrix = Matrix4x4.identity;
- public TransformCache parent
- {
- get { return m_Parent; }
- }
- public TransformCache[] children
- {
- get { return m_Children.ToArray(); }
- }
- internal virtual int siblingIndex
- {
- get { return GetSiblingIndex(); }
- set { SetSiblingIndex(value); }
- }
- public int ChildCount
- {
- get { return m_Children.Count; }
- }
- public Vector3 localPosition
- {
- get { return m_LocalPosition; }
- set
- {
- m_LocalPosition = value;
- Update();
- }
- }
- public Quaternion localRotation
- {
- get { return m_LocalRotation; }
- set
- {
- m_LocalRotation = MathUtility.NormalizeQuaternion(value);
- Update();
- }
- }
- public Vector3 localScale
- {
- get { return m_LocalScale; }
- set
- {
- m_LocalScale = value;
- Update();
- }
- }
- public Vector3 position
- {
- get { return parentMatrix.MultiplyPoint3x4(localPosition); }
- set { localPosition = parentMatrix.inverse.MultiplyPoint3x4(value); }
- }
- public Quaternion rotation
- {
- get { return GetGlobalRotation(); }
- set { SetGlobalRotation(value); }
- }
- public Vector3 right
- {
- get { return localToWorldMatrix.MultiplyVector(Vector3.right).normalized; }
- set { MatchDirection(Vector3.right, value); }
- }
- public Vector3 up
- {
- get { return localToWorldMatrix.MultiplyVector(Vector3.up).normalized; }
- set { MatchDirection(Vector3.up, value); }
- }
- public Vector3 forward
- {
- get { return localToWorldMatrix.MultiplyVector(Vector3.forward).normalized; }
- set { MatchDirection(Vector3.forward, value); }
- }
- public Matrix4x4 localToWorldMatrix
- {
- get { return m_LocalToWorldMatrix; }
- }
- public Matrix4x4 worldToLocalMatrix
- {
- get { return localToWorldMatrix.inverse; }
- }
- private Matrix4x4 parentMatrix
- {
- get
- {
- var parentMatrix = Matrix4x4.identity;
- if (parent != null)
- parentMatrix = parent.localToWorldMatrix;
- return parentMatrix;
- }
- }
- internal override void OnDestroy()
- {
- if (parent != null)
- parent.RemoveChild(this);
- m_Parent = null;
- m_Children.Clear();
- }
- private void Update()
- {
- m_LocalToWorldMatrix = parentMatrix * Matrix4x4.TRS(localPosition, localRotation, localScale);
- foreach (var child in m_Children)
- child.Update();
- }
- private void AddChild(TransformCache transform)
- {
- m_Children.Add(transform);
- }
- private void InsertChildAt(int index, TransformCache transform)
- {
- m_Children.Insert(index, transform);
- }
- private void RemoveChild(TransformCache transform)
- {
- m_Children.Remove(transform);
- }
- private void RemoveChildAt(int index)
- {
- m_Children.RemoveAt(index);
- }
- private int GetSiblingIndex()
- {
- if (parent == null)
- return -1;
- return parent.m_Children.IndexOf(this);
- }
- private void SetSiblingIndex(int index)
- {
- if (parent != null)
- {
- 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)
- {
- SetParent(newParent, true);
- }
- public void SetParent(TransformCache newParent, bool worldPositionStays)
- {
- 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();
- }
- }
- private Quaternion GetGlobalRotation()
- {
- var globalRotation = localRotation;
- var currentParent = parent;
- while (currentParent != null)
- {
- globalRotation = ScaleMulQuat(currentParent.localScale, globalRotation);
- globalRotation = currentParent.localRotation * globalRotation;
- currentParent = currentParent.parent;
- }
- return globalRotation;
- }
- private void SetGlobalRotation(Quaternion r)
- {
- if (parent != null)
- r = parent.InverseTransformRotation(r);
- localRotation = r;
- }
- private Quaternion InverseTransformRotation(Quaternion r)
- {
- if (parent != null)
- r = parent.InverseTransformRotation(r);
- r = Quaternion.Inverse(localRotation) * r;
- r = ScaleMulQuat(localScale, r);
- return r;
- }
- private Quaternion ScaleMulQuat(Vector3 scale, Quaternion q)
- {
- var s = new Vector3(Chgsign(1f, scale.x), Chgsign(1f, scale.y), Chgsign(1f, scale.z));
- q.x = Chgsign(q.x, s.y * s.z);
- q.y = Chgsign(q.y, s.x * s.z);
- q.z = Chgsign(q.z, s.x * s.y);
- return q;
- }
- private float Chgsign(float x, float y)
- {
- return y < 0f ? -x : x;
- }
- private 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();
- }
- }
- }
|