89 lines
3.2 KiB
C#
89 lines
3.2 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.Animations;
|
|
using UnityEngine.Playables;
|
|
|
|
namespace RebootKit.Engine.Animations {
|
|
[Serializable]
|
|
public class LayerMixerNode : IReAnimatorNode {
|
|
[Serializable]
|
|
struct LayerState {
|
|
[SerializeReference] public IReAnimatorNode node;
|
|
|
|
public AvatarMask mask;
|
|
public bool isAdditive;
|
|
|
|
[Range(0.0f, 1.0f)] public float targetWeight;
|
|
[NonSerialized] public float CurrentWeight;
|
|
}
|
|
|
|
[field: SerializeField] public string Name { get; private set; }
|
|
|
|
AnimationLayerMixerPlayable m_LayerMixer;
|
|
|
|
[SerializeField] float m_TransitionSpeed = 5.0f;
|
|
[SerializeField] LayerState[] m_Layers;
|
|
|
|
public void Tick(float deltaTime) {
|
|
for (int i = 0; i < m_Layers.Length; ++i){
|
|
if (m_TransitionSpeed > 0.0f) {
|
|
m_Layers[i].CurrentWeight = Mathf.MoveTowards(m_Layers[i].CurrentWeight,
|
|
m_Layers[i].targetWeight,
|
|
m_TransitionSpeed * deltaTime);
|
|
} else {
|
|
m_Layers[i].CurrentWeight = m_Layers[i].targetWeight;
|
|
}
|
|
|
|
m_LayerMixer.SetInputWeight(i, m_Layers[i].CurrentWeight);
|
|
|
|
m_Layers[i].node.Tick(deltaTime);
|
|
}
|
|
}
|
|
|
|
public IPlayable Build(PlayableGraph graph) {
|
|
m_LayerMixer = AnimationLayerMixerPlayable.Create(graph, m_Layers.Length);
|
|
|
|
for (int i = 0; i < m_Layers.Length; ++i) {
|
|
IPlayable playable = m_Layers[i].node.Build(graph);
|
|
|
|
if (playable is AnimationMixerPlayable mixerPlayable) {
|
|
m_LayerMixer.ConnectInput(i, mixerPlayable, 0, m_Layers[i].targetWeight);
|
|
} else if (playable is AnimationClipPlayable clipPlayable) {
|
|
m_LayerMixer.ConnectInput(i, clipPlayable, 0, m_Layers[i].targetWeight);
|
|
} else if (playable is AnimationLayerMixerPlayable layerMixerPlayable) {
|
|
m_LayerMixer.ConnectInput(i, layerMixerPlayable, 0, m_Layers[i].targetWeight);
|
|
}
|
|
|
|
m_LayerMixer.SetLayerAdditive((uint)i, m_Layers[i].isAdditive);
|
|
|
|
if (m_Layers[i].mask != null) {
|
|
m_LayerMixer.SetLayerMaskFromAvatarMask((uint)i, m_Layers[i].mask);
|
|
}
|
|
}
|
|
|
|
return m_LayerMixer;
|
|
}
|
|
|
|
public bool TryFindChild(string name, out IReAnimatorNode node) {
|
|
for (int i = 0; i < m_Layers.Length; i++) {
|
|
if (m_Layers[i].node.Name.Equals(name, StringComparison.Ordinal)) {
|
|
node = m_Layers[i].node;
|
|
return true;
|
|
}
|
|
|
|
if (m_Layers[i].node.TryFindChild(name, out IReAnimatorNode childNode)) {
|
|
node = childNode;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
node = null;
|
|
return false;
|
|
}
|
|
|
|
public void SetLayerWeight(int index, float weight) {
|
|
m_Layers[index].targetWeight = weight;
|
|
}
|
|
}
|
|
}
|