You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
3.2 KiB
93 lines
3.2 KiB
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); |
|
} |
|
} |
|
}
|
|
|