94 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			94 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | 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); | ||
|  |         } | ||
|  |     } | ||
|  | } |