123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- 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);
- }
- }
- }
|