180 lines
4.5 KiB
C#
180 lines
4.5 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
namespace UnityEditor.U2D.Animation
|
|
{
|
|
internal class SkeletonCache : TransformCache
|
|
{
|
|
[SerializeField]
|
|
bool m_IsPosePreview = false;
|
|
[SerializeField]
|
|
List<BoneCache> m_Bones = new List<BoneCache>();
|
|
|
|
public bool isPosePreview => m_IsPosePreview;
|
|
|
|
public int boneCount => m_Bones.Count;
|
|
|
|
public virtual BoneCache[] bones => m_Bones.ToArray();
|
|
|
|
public void AddBone(BoneCache bone, bool worldPositionStays = true)
|
|
{
|
|
Debug.Assert(bone != null);
|
|
Debug.Assert(!Contains(bone));
|
|
|
|
if (bone.parent == null)
|
|
bone.SetParent(this, worldPositionStays);
|
|
|
|
m_Bones.Add(bone);
|
|
}
|
|
|
|
public void ReorderBones(IEnumerable<BoneCache> boneCache)
|
|
{
|
|
if (boneCache.Count() == m_Bones.Count)
|
|
{
|
|
foreach (var b in m_Bones)
|
|
{
|
|
if (!boneCache.Contains(b))
|
|
return;
|
|
}
|
|
m_Bones = boneCache.ToList();
|
|
}
|
|
}
|
|
|
|
public void DestroyBone(BoneCache bone)
|
|
{
|
|
Debug.Assert(bone != null);
|
|
Debug.Assert(Contains(bone));
|
|
|
|
m_Bones.Remove(bone);
|
|
|
|
var boneChildren = bone.children;
|
|
foreach (var child in boneChildren)
|
|
child.SetParent(bone.parent);
|
|
|
|
skinningCache.Destroy(bone);
|
|
}
|
|
|
|
public void SetDefaultPose()
|
|
{
|
|
foreach (var bone in m_Bones)
|
|
bone.SetDefaultPose();
|
|
|
|
m_IsPosePreview = false;
|
|
}
|
|
|
|
public void RestoreDefaultPose()
|
|
{
|
|
foreach (var bone in m_Bones)
|
|
bone.RestoreDefaultPose();
|
|
|
|
m_IsPosePreview = false;
|
|
skinningCache.events.skeletonPreviewPoseChanged.Invoke(this);
|
|
}
|
|
|
|
public void SetPosePreview()
|
|
{
|
|
m_IsPosePreview = true;
|
|
}
|
|
|
|
public BonePose[] GetLocalPose()
|
|
{
|
|
var pose = new List<BonePose>();
|
|
|
|
foreach (var bone in m_Bones)
|
|
pose.Add(bone.localPose);
|
|
|
|
return pose.ToArray();
|
|
}
|
|
|
|
public void SetLocalPose(BonePose[] pose)
|
|
{
|
|
Debug.Assert(m_Bones.Count == pose.Length);
|
|
|
|
for (var i = 0; i < m_Bones.Count; ++i)
|
|
m_Bones[i].localPose = pose[i];
|
|
|
|
m_IsPosePreview = true;
|
|
}
|
|
|
|
public BonePose[] GetWorldPose()
|
|
{
|
|
var pose = new List<BonePose>();
|
|
|
|
foreach (var bone in m_Bones)
|
|
pose.Add(bone.worldPose);
|
|
|
|
return pose.ToArray();
|
|
}
|
|
|
|
public void SetWorldPose(BonePose[] pose)
|
|
{
|
|
Debug.Assert(m_Bones.Count == pose.Length);
|
|
|
|
for (var i = 0; i < m_Bones.Count; ++i)
|
|
{
|
|
var bone = m_Bones[i];
|
|
var childWoldPose = bone.GetChildrenWoldPose();
|
|
bone.worldPose = pose[i];
|
|
bone.SetChildrenWorldPose(childWoldPose);
|
|
}
|
|
|
|
m_IsPosePreview = true;
|
|
}
|
|
|
|
public BoneCache GetBone(int index)
|
|
{
|
|
return m_Bones[index];
|
|
}
|
|
|
|
public int IndexOf(BoneCache bone)
|
|
{
|
|
return m_Bones.IndexOf(bone);
|
|
}
|
|
|
|
public bool Contains(BoneCache bone)
|
|
{
|
|
return m_Bones.Contains(bone);
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
var roots = children;
|
|
|
|
foreach (var root in roots)
|
|
DestroyHierarchy(root);
|
|
|
|
m_Bones.Clear();
|
|
}
|
|
|
|
public string GetUniqueName(BoneCache bone)
|
|
{
|
|
Debug.Assert(Contains(bone));
|
|
|
|
var boneName = bone.name;
|
|
var names = m_Bones.ConvertAll(b => b.name);
|
|
var index = IndexOf(bone);
|
|
var count = 0;
|
|
|
|
Debug.Assert(index < names.Count);
|
|
|
|
for (var i = 0; i < index; ++i)
|
|
if (names[i].Equals(boneName))
|
|
++count;
|
|
|
|
return count == 0 ? boneName : $"{boneName} ({count + 1})";
|
|
}
|
|
|
|
void DestroyHierarchy(TransformCache root)
|
|
{
|
|
Debug.Assert(root != null);
|
|
|
|
var rootChildren = root.children;
|
|
foreach (var child in rootChildren)
|
|
DestroyHierarchy(child);
|
|
|
|
skinningCache.Destroy(root);
|
|
}
|
|
}
|
|
}
|