コード例 #1
0
        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));
            }
        }
コード例 #3
0
        internal override Playable OnCreatePlayableGraph(PlayableGraph graph, GameObject go, IntervalTree <RuntimeElement> tree)
        {
            if (base.isSubTrack)
            {
                throw new InvalidOperationException("Nested animation tracks should never be asked to create a graph directly");
            }
            List <AnimationTrack> list = new List <AnimationTrack>();

            if (this.compilableIsolated)
            {
                list.Add(this);
            }
            foreach (TrackAsset trackAsset in base.GetChildTracks())
            {
                AnimationTrack animationTrack = trackAsset as AnimationTrack;
                if (animationTrack != null && animationTrack.compilable)
                {
                    list.Add(animationTrack);
                }
            }
            AnimationMotionXToDeltaPlayable animationMotionXToDeltaPlayable = AnimationMotionXToDeltaPlayable.Create(graph);
            AnimationLayerMixerPlayable     animationLayerMixerPlayable     = AnimationTrack.CreateGroupMixer(graph, go, list.Count);

            graph.Connect <AnimationLayerMixerPlayable, AnimationMotionXToDeltaPlayable>(animationLayerMixerPlayable, 0, animationMotionXToDeltaPlayable, 0);
            animationMotionXToDeltaPlayable.SetInputWeight(0, 1f);
            for (int i = 0; i < list.Count; i++)
            {
                Playable source = (!list[i].inClipMode) ? list[i].CreateInfiniteTrackPlayable(graph, go, tree) : this.CompileTrackPlayable(graph, list[i], go, tree);
                graph.Connect <Playable, AnimationLayerMixerPlayable>(source, 0, animationLayerMixerPlayable, i);
                animationLayerMixerPlayable.SetInputWeight(i, (float)((!list[i].inClipMode) ? 1 : 0));
                if (list[i].applyAvatarMask && list[i].avatarMask != null)
                {
                    animationLayerMixerPlayable.SetLayerMaskFromAvatarMask((uint)i, list[i].avatarMask);
                }
            }
            return(animationMotionXToDeltaPlayable);
        }
コード例 #4
0
        internal override Playable OnCreateClipPlayableGraph(PlayableGraph graph, GameObject go, IntervalTree <RuntimeElement> tree)
        {
            if (isSubTrack)
            {
                throw new InvalidOperationException("Nested animation tracks should never be asked to create a graph directly");
            }

            List <AnimationTrack> flattenTracks = new List <AnimationTrack>();

            if (CanCompileClips())
            {
                flattenTracks.Add(this);
            }

            var genericRoot = GetGenericRootNode(go);
            var animatesRootTransformNoMask = AnimatesRootTransform();
            var animatesRootTransform       = animatesRootTransformNoMask && !IsRootTransformDisabledByMask(go, genericRoot);

            foreach (var subTrack in GetChildTracks())
            {
                var child = subTrack as AnimationTrack;
                if (child != null && child.CanCompileClips())
                {
                    var childAnimatesRoot = child.AnimatesRootTransform();
                    animatesRootTransformNoMask |= child.AnimatesRootTransform();
                    animatesRootTransform       |= (childAnimatesRoot && !child.IsRootTransformDisabledByMask(go, genericRoot));
                    flattenTracks.Add(child);
                }
            }

            // figure out which mode to apply
            AppliedOffsetMode mode = GetOffsetMode(go, animatesRootTransform);
            int defaultBlendCount  = GetDefaultBlendCount();
            var layerMixer         = CreateGroupMixer(graph, go, flattenTracks.Count + defaultBlendCount);

            for (int c = 0; c < flattenTracks.Count; c++)
            {
                int blendIndex = c + defaultBlendCount;
                // if the child is masking the root transform, compile it as if we are non-root mode
                var childMode = mode;
                if (mode != AppliedOffsetMode.NoRootTransform && flattenTracks[c].IsRootTransformDisabledByMask(go, genericRoot))
                {
                    childMode = AppliedOffsetMode.NoRootTransform;
                }

                var compiledTrackPlayable = flattenTracks[c].inClipMode ?
                                            CompileTrackPlayable(graph, flattenTracks[c], go, tree, childMode) :
                                            flattenTracks[c].CreateInfiniteTrackPlayable(graph, go, tree, childMode);
                graph.Connect(compiledTrackPlayable, 0, layerMixer, blendIndex);
                layerMixer.SetInputWeight(blendIndex, flattenTracks[c].inClipMode ? 0 : 1);
                if (flattenTracks[c].applyAvatarMask && flattenTracks[c].avatarMask != null)
                {
                    layerMixer.SetLayerMaskFromAvatarMask((uint)blendIndex, flattenTracks[c].avatarMask);
                }
            }

            var requiresMotionXPlayable = RequiresMotionXPlayable(mode, go);

            // In the editor, we may require the motion X playable if we are animating the root transform but it is masked out, because the default poses
            //  need to properly update root motion
            requiresMotionXPlayable |= (defaultBlendCount > 0 && RequiresMotionXPlayable(GetOffsetMode(go, animatesRootTransformNoMask), go));

            // Attach the default poses
            AttachDefaultBlend(graph, layerMixer, requiresMotionXPlayable);

            // motionX playable not required in scene offset mode, or root transform mode
            Playable mixer = layerMixer;

            if (requiresMotionXPlayable)
            {
                // If we are animating a root transform, add the motionX to delta playable as the root node
                var motionXToDelta = AnimationMotionXToDeltaPlayable.Create(graph);
                graph.Connect(mixer, 0, motionXToDelta, 0);
                motionXToDelta.SetInputWeight(0, 1.0f);
                motionXToDelta.SetAbsoluteMotion(UsesAbsoluteMotion(mode));
                mixer = (Playable)motionXToDelta;
            }


#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                var animator = GetBinding(go != null ? go.GetComponent <PlayableDirector>() : null);
                if (animator != null)
                {
                    GameObject targetGO = animator.gameObject;
                    IAnimationWindowPreview[] previewComponents = targetGO.GetComponents <IAnimationWindowPreview>();

                    m_HasPreviewComponents = previewComponents.Length > 0;
                    if (m_HasPreviewComponents)
                    {
                        foreach (var component in previewComponents)
                        {
                            mixer = component.BuildPreviewGraph(graph, mixer);
                        }
                    }
                }
            }
#endif

            return(mixer);
        }
コード例 #5
0
        internal override Playable OnCreateClipPlayableGraph(PlayableGraph graph, GameObject go, IntervalTree <RuntimeElement> tree)
        {
            if (isSubTrack)
            {
                throw new InvalidOperationException("Nested animation tracks should never be asked to create a graph directly");
            }

            List <AnimationTrack> flattenTracks = new List <AnimationTrack>();

            if (CanCompileClips())
            {
                flattenTracks.Add(this);
            }


            bool animatesRootTransform = AnimatesRootTransform();

            foreach (var subTrack in GetChildTracks())
            {
                var child = subTrack as AnimationTrack;
                if (child != null && child.CanCompileClips())
                {
                    animatesRootTransform |= child.AnimatesRootTransform();
                    flattenTracks.Add(child);
                }
            }

            // figure out which mode to apply
            AppliedOffsetMode mode = GetOffsetMode(go, animatesRootTransform);
            var layerMixer         = CreateGroupMixer(graph, go, flattenTracks.Count);

            for (int c = 0; c < flattenTracks.Count; c++)
            {
                var compiledTrackPlayable = flattenTracks[c].inClipMode ?
                                            CompileTrackPlayable(graph, flattenTracks[c], go, tree, mode) :
                                            flattenTracks[c].CreateInfiniteTrackPlayable(graph, go, tree, mode);
                graph.Connect(compiledTrackPlayable, 0, layerMixer, c);
                layerMixer.SetInputWeight(c, flattenTracks[c].inClipMode ? 0 : 1);
                if (flattenTracks[c].applyAvatarMask && flattenTracks[c].avatarMask != null)
                {
                    layerMixer.SetLayerMaskFromAvatarMask((uint)c, flattenTracks[c].avatarMask);
                }
            }

            bool requiresMotionXPlayable = RequiresMotionXPlayable(mode, go);

            Playable mixer = layerMixer;

            mixer = CreateDefaultBlend(graph, go, mixer, requiresMotionXPlayable);

            // motionX playable not required in scene offset mode, or root transform mode
            if (requiresMotionXPlayable)
            {
                // If we are animating a root transform, add the motionX to delta playable as the root node
                var motionXToDelta = AnimationMotionXToDeltaPlayable.Create(graph);
                graph.Connect(mixer, 0, motionXToDelta, 0);
                motionXToDelta.SetInputWeight(0, 1.0f);
                motionXToDelta.SetAbsoluteMotion(UsesAbsoluteMotion(mode));
                mixer = (Playable)motionXToDelta;
            }



#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                var animator = GetBinding(go != null ? go.GetComponent <PlayableDirector>() : null);
                if (animator != null)
                {
                    GameObject targetGO = animator.gameObject;
                    IAnimationWindowPreview[] previewComponents = targetGO.GetComponents <IAnimationWindowPreview>();

                    m_HasPreviewComponents = previewComponents.Length > 0;
                    if (m_HasPreviewComponents)
                    {
                        foreach (var component in previewComponents)
                        {
                            mixer = component.BuildPreviewGraph(graph, mixer);
                        }
                    }
                }
            }
#endif

            return(mixer);
        }
コード例 #6
0
        internal override Playable OnCreateClipPlayableGraph(PlayableGraph graph, GameObject go, IntervalTree <RuntimeElement> tree)
        {
            if (isSubTrack)
            {
                throw new InvalidOperationException("Nested animation tracks should never be asked to create a graph directly");
            }

            List <AnimationTrack> flattenTracks = new List <AnimationTrack>();

            if (CanCompileClips())
            {
                flattenTracks.Add(this);
            }


            bool animatesRootTransform = AnimatesRootTransform();

            foreach (var subTrack in GetChildTracks())
            {
                var child = subTrack as AnimationTrack;
                if (child != null && child.CanCompileClips())
                {
                    animatesRootTransform |= child.AnimatesRootTransform();
                    flattenTracks.Add(child);
                }
            }

            // figure out which mode to apply
            AppliedOffsetMode mode = GetOffsetMode(go, animatesRootTransform);
            var layerMixer         = CreateGroupMixer(graph, go, flattenTracks.Count);

            for (int c = 0; c < flattenTracks.Count; c++)
            {
                var compiledTrackPlayable = flattenTracks[c].inClipMode ?
                                            CompileTrackPlayable(graph, flattenTracks[c], go, tree, mode) :
                                            flattenTracks[c].CreateInfiniteTrackPlayable(graph, go, tree, mode);
                graph.Connect(compiledTrackPlayable, 0, layerMixer, c);
                layerMixer.SetInputWeight(c, flattenTracks[c].inClipMode ? 0 : 1);
                if (flattenTracks[c].applyAvatarMask && flattenTracks[c].avatarMask != null)
                {
                    layerMixer.SetLayerMaskFromAvatarMask((uint)c, flattenTracks[c].avatarMask);
                }
            }

            Playable mixer = (Playable)layerMixer;

#if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                var motionXMixer = AnimationMixerPlayable.Create(graph, 2);

                var      animator     = GetBinding(go != null ? go.GetComponent <PlayableDirector>() : null);
                Playable blendDefault = Playable.Null;
                if (animator != null && animator.isHuman)
                {
                    blendDefault = AnimationClipPlayable.Create(graph, GetDefaultHumanoidClip());
                }
                else
                {
                    blendDefault = AnimationPosePlayable.Create(graph);
                    ((AnimationPosePlayable)blendDefault).SetReadDefaultPose(true);
                }

                var offsetPlayable = AnimationOffsetPlayable.Create(graph, m_SceneOffsetPosition, Quaternion.Euler(m_SceneOffsetRotation), 1);

                graph.Connect(blendDefault, 0, offsetPlayable, 0);
                graph.Connect(layerMixer, 0, motionXMixer, 0);
                graph.Connect(offsetPlayable, 0, motionXMixer, 1);

                offsetPlayable.SetInputWeight(0, 1.0f);
                motionXMixer.SetInputWeight(1, 1.0f);
                motionXMixer.SetInputWeight(0, 0.0f);

                mixer = (Playable)motionXMixer;
            }
#endif

            // motionX playable not required in scene offset mode, or root transform mode
            if (!RequiresMotionXPlayable(mode, go))
            {
                return(mixer);
            }

            // If we are animating a root transform, add the motionX to delta playable as the root node
            var motionXToDelta = AnimationMotionXToDeltaPlayable.Create(graph);
            graph.Connect(mixer, 0, motionXToDelta, 0);
            motionXToDelta.SetInputWeight(0, 1.0f);
            motionXToDelta.SetAbsoluteMotion(UsesAbsoluteMotion(mode));
            return(motionXToDelta);
        }
コード例 #7
0
        private void RebuildGraph(Animator animator)
        {
            DestroyGraph();

            m_Graph = PlayableGraph.Create("PreviewGraph");
            m_Graph.SetTimeUpdateMode(DirectorUpdateMode.Manual);

            m_ClipPlayable = AnimationClipPlayable.Create(m_Graph, state.activeAnimationClip);
            m_ClipPlayable.SetOverrideLoopTime(true);
            m_ClipPlayable.SetLoopTime(false);
            m_ClipPlayable.SetApplyFootIK(false);

            m_CandidateClipPlayable = AnimationClipPlayable.Create(m_Graph, m_CandidateClip);
            m_CandidateClipPlayable.SetApplyFootIK(false);

            IAnimationWindowPreview[] previewComponents = FetchPostProcessComponents();
            bool requiresDefaultPose = previewComponents != null && previewComponents.Length > 0;
            int  nInputs             = requiresDefaultPose ? 3 : 2;

            // Create a layer mixer if necessary, we'll connect playable nodes to it after having populated AnimationStream.
            AnimationLayerMixerPlayable mixer = AnimationLayerMixerPlayable.Create(m_Graph, nInputs);

            m_GraphRoot = (Playable)mixer;

            // Populate custom playable preview graph.
            if (previewComponents != null)
            {
                foreach (var component in previewComponents)
                {
                    m_GraphRoot = component.BuildPreviewGraph(m_Graph, m_GraphRoot);
                }
            }

            // Finish hooking up mixer.
            int inputIndex = 0;

            if (requiresDefaultPose)
            {
                AnimationMode.RevertPropertyModificationsForGameObject(state.activeRootGameObject);

                EditorCurveBinding[] streamBindings = AnimationUtility.GetAnimationStreamBindings(state.activeRootGameObject);

                m_DefaultPose = new AnimationClip()
                {
                    name = "DefaultPose"
                };

                AnimationWindowUtility.CreateDefaultCurves(state, m_DefaultPose, streamBindings);

                m_DefaultPosePlayable = AnimationClipPlayable.Create(m_Graph, m_DefaultPose);
                m_DefaultPosePlayable.SetApplyFootIK(false);

                mixer.ConnectInput(inputIndex++, m_DefaultPosePlayable, 0, 1.0f);
            }

            mixer.ConnectInput(inputIndex++, m_ClipPlayable, 0, 1.0f);
            mixer.ConnectInput(inputIndex++, m_CandidateClipPlayable, 0, 1.0f);

            if (animator.applyRootMotion)
            {
                var motionX = AnimationMotionXToDeltaPlayable.Create(m_Graph);
                motionX.SetAbsoluteMotion(true);
                motionX.SetInputWeight(0, 1.0f);

                m_Graph.Connect(m_GraphRoot, 0, motionX, 0);

                m_GraphRoot = (Playable)motionX;
            }

            var output = AnimationPlayableOutput.Create(m_Graph, "ouput", animator);

            output.SetSourcePlayable(m_GraphRoot);
            output.SetWeight(0.0f);
        }