//============================================================================================ /** * @brief Constructor for the MxMLayer class which takes a playable instead of an animation clip. * Sets up all initial values and creates the layer's mixer. * * @param [int] a_id - the layer id (lowest layer value is 2 for MxMLayers) * @param [int] a_maxClips - the maximum number of clips that can be blended on this layer * @param [ref PlayableGraph] a_playableGraph - the playable graph that this layer lives on * @param [Playable] a_playable - the playable to use for this layer * @param [AvatarMask] a_mask - the mask to use with this player (Default null) * @param [float] a_weight - the starting weight of this layer (Default 0) * @param [bool] a_additive - whether the layer is additive or not (Default false) * *********************************************************************************************/ public MxMLayer(int a_id, ref AnimationLayerMixerPlayable a_layerMixer, Playable a_playable, AvatarMask a_mask = null, float a_weight = 0f, bool a_additive = false) { if (!a_playable.IsValid()) Debug.LogError("Error: Attempting to create an MxMLayer with an invalid playable"); if (!a_layerMixer.IsValid()) Debug.LogError("Error: Attempting to create an MxMLayer with an invalid layerMixer."); m_layerMixer = a_layerMixer; m_playableGraph = m_layerMixer.GetGraph(); Id = a_id; PrimaryInputId = 0; MaxClips = 1; m_layerMixer.ConnectInput(Id, a_playable, 0); Mask = a_mask; m_layerMixer.SetLayerAdditive((uint)Id, a_additive); m_layerMixer.SetInputWeight(Id, Mathf.Clamp01(a_weight)); SubLayerWeights = new float[1]; SubLayerWeights[0] = 1f; }
//============================================================================================ /** * @brief Constructor for the MxMLayer class. Sets up all initial values and creates the layer's * mixer * * @param [int] a_id - the layer id (lowest layer value is 2 for MxMLayers) * @param [int] a_maxClips - the maximum number of clips that can be blended on this layer * @param [ref PlayableGraph] a_playableGraph - the playable graph that this layer lives on * @param [AnimationClip] a_clip - the starting animation clip to use for this layer. * @param [AvatarMask] a_mask - the mask to use with this player (Default null) * @param [float] a_weight - the starting weight of this layer (Default 0) * @param [bool] a_additive - whether the layer is additive or not (Default false) * *********************************************************************************************/ public MxMLayer(int a_id, int a_maxClips, ref AnimationLayerMixerPlayable a_layerMixer, AnimationClip a_clip, AvatarMask a_mask = null, float a_weight = 0f, bool a_additive = false) { Assert.IsNotNull(a_clip, "Error: Attempting to create an MxMLayer with null AnimationClip"); if (!a_layerMixer.IsValid()) Debug.LogError("Error: Attempting to create an MxMLayer with an invalid layerMixer."); m_playableGraph = a_layerMixer.GetGraph(); m_layerMixer = a_layerMixer; PrimaryClip = a_clip; Id = a_id; MaxClips = a_maxClips; PrimaryInputId = 0; Mixer = AnimationMixerPlayable.Create(m_playableGraph, a_maxClips, true); var clipPlayable = AnimationClipPlayable.Create(m_playableGraph, PrimaryClip); m_layerMixer.ConnectInput(Id, Mixer, 0); Mixer.ConnectInput(0, clipPlayable, 0); Mixer.SetInputWeight(0, 1f); Mask = a_mask; m_layerMixer.SetLayerAdditive((uint)Id, a_additive); m_layerMixer.SetInputWeight(Id, Mathf.Clamp01(a_weight)); SubLayerWeights = new float[MaxClips]; SubLayerWeights[0] = 1f; }
/// <summary> /// If the first state gets added after Initialize and InitializeLayerBlending has run, we disconnect and destroy the empty state mixer, and then /// re-initialize. /// </summary> private void HandleAddedFirstStateAfterStartup(AnimationPlayerState state, Dictionary <string, float> blendVariableValues) { states.Add(state); // layerMixer.IsValid => there's more than 1 layer. if (layerMixer.IsValid()) { containingGraph.Disconnect(layerMixer, layerIndex); } stateMixer.Destroy(); InitializeSelf(containingGraph, defaultTransition, clipSwapCollections, blendVariableValues); if (layerMixer.IsValid()) { InitializeLayerBlending(containingGraph, layerIndex, layerMixer); } }
void FindMixers() { m_Mixers.Clear(); m_PoseMixer = AnimationLayerMixerPlayable.Null; m_LayerMixer = AnimationLayerMixerPlayable.Null; m_MotionXPlayable = AnimationMotionXToDeltaPlayable.Null; var playable = m_Output.GetSourcePlayable(); var outputPort = m_Output.GetSourceOutputPort(); if (!playable.IsValid() || outputPort < 0 || outputPort >= playable.GetInputCount()) { return; } var mixer = FindFirstAnimationPlayable(playable.GetInput(outputPort)); Playable motionXPlayable = mixer; if (motionXPlayable.IsPlayableOfType <AnimationMotionXToDeltaPlayable>()) { m_MotionXPlayable = (AnimationMotionXToDeltaPlayable)motionXPlayable; mixer = m_MotionXPlayable.GetInput(0); } #if UNITY_EDITOR // Default pose mixer if (!Application.isPlaying) { if (mixer.IsValid() && mixer.IsPlayableOfType <AnimationLayerMixerPlayable>()) { m_PoseMixer = (AnimationLayerMixerPlayable)mixer; mixer = m_PoseMixer.GetInput(1); } } #endif // Track mixer if (mixer.IsValid() && mixer.IsPlayableOfType <AnimationLayerMixerPlayable>()) { m_LayerMixer = (AnimationLayerMixerPlayable)mixer; } if (!m_LayerMixer.IsValid()) { return; } var count = m_LayerMixer.GetInputCount(); for (var i = 0; i < count; i++) { FindMixers(m_LayerMixer, i, m_LayerMixer.GetInput(i)); } }
void FindMixers() { m_Mixers.Clear(); m_PoseMixer = AnimationMixerPlayable.Null; m_LayerMixer = AnimationLayerMixerPlayable.Null; m_MotionXPlayable = AnimationMotionXToDeltaPlayable.Null; var playable = m_Output.GetSourcePlayable(); var outputPort = m_Output.GetSourceOutputPort(); if (!playable.IsValid() || outputPort < 0 || outputPort >= playable.GetInputCount()) { return; } var mixer = FindFirstAnimationPlayable(playable.GetInput(outputPort)); Playable motionXPlayable = mixer; if (motionXPlayable.IsPlayableOfType <AnimationMotionXToDeltaPlayable>()) { m_MotionXPlayable = (AnimationMotionXToDeltaPlayable)motionXPlayable; mixer = m_MotionXPlayable.GetInput(0); } if (mixer.IsValid() && mixer.IsPlayableOfType <AnimationMixerPlayable>()) { m_PoseMixer = (AnimationMixerPlayable)mixer; Playable layerMixer = m_PoseMixer.GetInput(0); if (layerMixer.IsValid() && layerMixer.IsPlayableOfType <AnimationLayerMixerPlayable>()) { m_LayerMixer = (AnimationLayerMixerPlayable)layerMixer; } } else if (mixer.IsValid() && mixer.IsPlayableOfType <AnimationLayerMixerPlayable>()) { m_LayerMixer = (AnimationLayerMixerPlayable)mixer; } if (!m_LayerMixer.IsValid()) { return; } var count = m_LayerMixer.GetInputCount(); for (var i = 0; i < count; i++) { FindMixers(m_LayerMixer, i, m_LayerMixer.GetInput(i)); } }
public static bool TryInjectMixer(this PlayableDirector dir, Playable timelinePlayable, Animator animator, out AnimationLayerMixerPlayable mixerPlayable) { mixerPlayable = AnimationLayerMixerPlayable.Null; if (timelinePlayable.IsValid() == false) { Debug.LogError("Timeline Playable is not valid"); return(false); } if (!dir) { Debug.LogError("PlayableDirector is null"); return(false); } if (!dir.playableAsset) { Debug.LogError("PlayableDirector has no TimelineAsset assigned", dir); return(false); } if (!animator) { Debug.LogError("Animator is null"); return(false); } var tracks = new List <TrackAsset>(); if (!TryGetTracks(dir, tracks)) { Debug.LogError("No AnimationTracks found", dir); return(false); } var animatorIndex = 0; var found = false; // try find the timeline graph index for this animator // we do this by looping bindings for all animation tracks // and check if the binding maps to the animator we want to inject a mixer for foreach (var track in tracks) { if (found) { break; } if (track.isEmpty || track.muted || !track.hasClips) { continue; } var trackOutputs = track.outputs; foreach (var to in trackOutputs) { var trackBinding = dir.GetGenericBinding(to.sourceObject); if (trackBinding && trackBinding == animator) { found = true; break; } animatorIndex++; } } if (!found) { Debug.LogWarning("Animator " + animator + " is not bound to " + dir, dir); return(false); } if (PrintDebugInfo) { Debug.Log("found: " + animatorIndex); } var playable = timelinePlayable.GetInput(animatorIndex); var prevOutput = playable.GetOutput(0); var prevInput = prevOutput.GetInput(animatorIndex); // Debug.Log(prevOutput.GetPlayableType() + ", " + prevInput.GetPlayableType()); // return false; mixerPlayable = AnimationLayerMixerPlayable.Create(dir.playableGraph, 1); // var pWeight = o.GetInputWeight(0); prevOutput.DisconnectInput(animatorIndex); prevOutput.ConnectInput(animatorIndex, mixerPlayable, 0); mixerPlayable.ConnectInput(0, prevInput, 0, 1); return(mixerPlayable.IsValid()); }