196 lines
3.8 KiB
C#
196 lines
3.8 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Playables;
|
|
using UnityEngine.Animations;
|
|
|
|
namespace MotionFramework.Experimental.Animation
|
|
{
|
|
public sealed class AnimMixer : AnimNode
|
|
{
|
|
private const float HIDE_DURATION = 0.25f;
|
|
private readonly List<AnimState> _states = new List<AnimState>(10);
|
|
private AnimationMixerPlayable _mixer;
|
|
private bool _isQuiting = false;
|
|
|
|
/// <summary>
|
|
/// 动画层级
|
|
/// </summary>
|
|
public int Layer { private set; get; }
|
|
|
|
|
|
public AnimMixer(PlayableGraph graph, int layer) : base(graph)
|
|
{
|
|
Layer = layer;
|
|
|
|
_mixer = AnimationMixerPlayable.Create(graph);
|
|
SetSourcePlayable(_mixer);
|
|
}
|
|
public override void Update(float deltaTime)
|
|
{
|
|
base.Update(deltaTime);
|
|
|
|
for (int i = 0; i < _states.Count; i++)
|
|
{
|
|
var state = _states[i];
|
|
if (state != null)
|
|
state.Update(deltaTime);
|
|
}
|
|
|
|
bool isAllDone = true;
|
|
for (int i = 0; i < _states.Count; i++)
|
|
{
|
|
var state = _states[i];
|
|
if (state != null)
|
|
{
|
|
if (state.IsDone == false)
|
|
isAllDone = false;
|
|
}
|
|
}
|
|
|
|
// 当子节点都已经完成的时候断开连接
|
|
if (isAllDone && _isQuiting == false)
|
|
{
|
|
_isQuiting = true;
|
|
StartWeightFade(0, HIDE_DURATION);
|
|
}
|
|
if (_isQuiting)
|
|
{
|
|
if (Mathf.Approximately(Weight, 0f))
|
|
DisconnectMixer();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 播放指定动画
|
|
/// </summary>
|
|
public void Play(AnimState animState, float fadeDuration)
|
|
{
|
|
// 重新激活混合器
|
|
_isQuiting = false;
|
|
StartWeightFade(1f, 0);
|
|
|
|
if (IsContains(animState) == false)
|
|
{
|
|
// 优先插入到一个空位
|
|
int index = _states.FindIndex(s => s == null);
|
|
if (index == -1)
|
|
{
|
|
// Increase input count
|
|
int inputCount = _mixer.GetInputCount();
|
|
_mixer.SetInputCount(inputCount + 1);
|
|
|
|
animState.Connect(_mixer, inputCount);
|
|
_states.Add(animState);
|
|
}
|
|
else
|
|
{
|
|
animState.Connect(_mixer, index);
|
|
_states[index] = animState;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < _states.Count; i++)
|
|
{
|
|
var state = _states[i];
|
|
if (state == null)
|
|
continue;
|
|
|
|
if (state == animState)
|
|
{
|
|
state.StartWeightFade(1f, fadeDuration);
|
|
state.PlayNode();
|
|
}
|
|
else
|
|
{
|
|
state.StartWeightFade(0f, fadeDuration);
|
|
state.PauseNode();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 停止指定动画,恢复为初始状态
|
|
/// </summary>
|
|
public void Stop(string name)
|
|
{
|
|
AnimState state = FindState(name);
|
|
if (state == null)
|
|
return;
|
|
|
|
state.PauseNode();
|
|
state.ResetNode();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 暂停所有动画
|
|
/// </summary>
|
|
public void PauseAll()
|
|
{
|
|
for (int i = 0; i < _states.Count; i++)
|
|
{
|
|
var state = _states[i];
|
|
if (state == null)
|
|
continue;
|
|
state.PauseNode();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 是否包含该动画
|
|
/// </summary>
|
|
public bool IsContains(AnimNode node)
|
|
{
|
|
foreach (var state in _states)
|
|
{
|
|
if (state == node)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 移除一个动画
|
|
/// </summary>
|
|
public void RemoveState(string name)
|
|
{
|
|
var state = FindState(name);
|
|
if (state == null)
|
|
return;
|
|
|
|
_states[state.InputPort] = null;
|
|
state.Destroy();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取指定的动画
|
|
/// </summary>
|
|
/// <returns>如果没有返回NULL</returns>
|
|
private AnimState FindState(string name)
|
|
{
|
|
foreach (var state in _states)
|
|
{
|
|
if (state != null && state.Name == name)
|
|
return state;
|
|
}
|
|
|
|
MotionLog.Warning($"Animation state doesn't exist : {name}");
|
|
return null;
|
|
}
|
|
|
|
private void DisconnectMixer()
|
|
{
|
|
for (int i = 0; i < _states.Count; i++)
|
|
{
|
|
var state = _states[i];
|
|
if (state == null)
|
|
continue;
|
|
|
|
state.Disconnect();
|
|
_states[i] = null;
|
|
}
|
|
|
|
Disconnect();
|
|
}
|
|
}
|
|
} |