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