File size: 3,304 Bytes
18a519f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | using System.Collections.Generic;
using UnityEngine.Animations;
using UnityEngine.Playables;
namespace UnityEngine.Timeline
{
// Does a post processing of the weights on an animation track to properly normalize
// the mixer weights so that blending does not bring default poses and subtracks, layers and
// layer graphs blend correctly
class AnimationOutputWeightProcessor : ITimelineEvaluateCallback
{
struct WeightInfo
{
public Playable mixer;
public Playable parentMixer;
public int port;
}
AnimationPlayableOutput m_Output;
AnimationMotionXToDeltaPlayable m_MotionXPlayable;
readonly List<WeightInfo> m_Mixers = new List<WeightInfo>();
public AnimationOutputWeightProcessor(AnimationPlayableOutput output)
{
m_Output = output;
output.SetWeight(0);
FindMixers();
}
void FindMixers()
{
var playable = m_Output.GetSourcePlayable();
var outputPort = m_Output.GetSourceOutputPort();
m_Mixers.Clear();
// only write the final output in playmode. it should always be 1 in editor because we blend to the defaults
FindMixers(playable, outputPort, playable.GetInput(outputPort));
}
// Recursively accumulates mixers.
void FindMixers(Playable parent, int port, Playable node)
{
if (!node.IsValid())
return;
var type = node.GetPlayableType();
if (type == typeof(AnimationMixerPlayable) || type == typeof(AnimationLayerMixerPlayable))
{
// use post fix traversal so children come before parents
int subCount = node.GetInputCount();
for (int j = 0; j < subCount; j++)
{
FindMixers(node, j, node.GetInput(j));
}
// if we encounter a layer mixer, we assume there is nesting occuring
// and we modulate the weight instead of overwriting it.
var weightInfo = new WeightInfo
{
parentMixer = parent,
mixer = node,
port = port,
};
m_Mixers.Add(weightInfo);
}
else
{
var count = node.GetInputCount();
for (var i = 0; i < count; i++)
{
FindMixers(parent, port, node.GetInput(i));
}
}
}
public void Evaluate()
{
float weight = 1;
m_Output.SetWeight(1);
for (int i = 0; i < m_Mixers.Count; i++)
{
var mixInfo = m_Mixers[i];
weight = WeightUtility.NormalizeMixer(mixInfo.mixer);
mixInfo.parentMixer.SetInputWeight(mixInfo.port, weight);
}
// only write the final weight in player/playmode. In editor, we are blending to the appropriate defaults
// the last mixer in the list is the final blend, since the list is composed post-order.
if (Application.isPlaying)
m_Output.SetWeight(weight);
}
}
}
|