/************************************************************************************************************************/
        #endregion
        /************************************************************************************************************************/
        #region Public API
        /************************************************************************************************************************/

        /// <summary>
        /// Constructs a new <see cref="ControllerState"/> to play the `animatorController` without connecting
        /// it to the <see cref="PlayableGraph"/>.
        /// </summary>
        protected ControllerState(AnimancerPlayable root, RuntimeAnimatorController animatorController,
            bool keepStateOnStop = false)
            : base(root)
        {
            KeepStateOnStop = keepStateOnStop;
            CreatePlayable(animatorController);
        }
Beispiel #2
0
        /************************************************************************************************************************/

        /// <summary>
        /// Invokes the <see cref="AnimancerEvent.Sequence.OnEnd"/> callback of the state that is playing the animation
        /// which triggered the event. Returns true if such a state exists (even if it doesn't have a callback).
        /// </summary>
        private static bool OnEndEventReceived(AnimancerPlayable animancer, AnimationEvent animationEvent)
        {
            var layers = animancer.Layers;
            var count  = layers.Count;

            // Try targeting the current state on each layer first.
            for (int i = 0; i < count; i++)
            {
                if (TryInvokeOnEndEventRecursive(layers[i].CurrentState, animationEvent))
                {
                    return(true);
                }
            }

            // Otherwise try every state.
            for (int i = 0; i < count; i++)
            {
                if (TryInvokeOnEndEventRecursive(layers[i], animationEvent))
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #3
0
        /************************************************************************************************************************/

        /// <summary>Creates a new <see cref="AnimancerPlayable"/> if it doesn't already exist.</summary>
        private void InitialisePlayable()
        {
            if (IsPlayableInitialised)
            {
                return;
            }

#if UNITY_EDITOR
            var currentEvent = Event.current;
            if (currentEvent != null && (currentEvent.type == EventType.Layout || currentEvent.type == EventType.Repaint))
            {
                Debug.LogWarning("Creating an AnimancerPlayable during a " + currentEvent.type + " event is likely undesirable.");
            }
#endif

            if (_Animator == null)
            {
                _Animator = GetComponent <Animator>();
            }

            AnimancerPlayable.SetNextGraphName(name + ".Animancer");
            _Playable = AnimancerPlayable.Create();
            _Playable.SetOutput(_Animator, this);

#if UNITY_EDITOR
            if (_Animator != null)
            {
                InitialUpdateMode = UpdateMode;
            }
#endif
        }
        /************************************************************************************************************************/

        /// <summary>
        /// Constructs a new <see cref="Float1ControllerState"/> to play the `controller` without connecting
        /// it to the <see cref="PlayableGraph"/>.
        /// </summary>
        private Float1ControllerState(AnimancerPlayable root, RuntimeAnimatorController controller, Parameter parameter,
                                      bool resetStatesOnStop = true)
            : base(root, controller, resetStatesOnStop)
        {
            _Parameter = parameter;
            _Parameter.ValidateHasParameter(controller, AnimatorControllerParameterType.Float);
        }
Beispiel #5
0
            /************************************************************************************************************************/

            /// <summary>[Internal] Creates a new <see cref="LayerList"/>.</summary>
            internal LayerList(AnimancerPlayable root, out Playable layerMixer)
            {
                Root       = root;
                _Layers    = new AnimancerLayer[DefaultCapacity];
                layerMixer = LayerMixer = AnimationLayerMixerPlayable.Create(root._Graph, 1);
                Root._Graph.Connect(layerMixer, 0, Root._RootPlayable, 0);
            }
Beispiel #6
0
        /************************************************************************************************************************/

        /// <summary>
        /// Called by Unity when this component is destroyed.
        /// Ensures that the <see cref="Playable"/> is properly cleaned up.
        /// </summary>
        protected virtual void OnDestroy()
        {
            if (IsPlayableInitialised)
            {
                _Playable.Destroy();
                _Playable = null;
            }
        }
Beispiel #7
0
        /************************************************************************************************************************/
        #region Graph
        /************************************************************************************************************************/

        /// <summary>The <see cref="AnimancerPlayable"/> at the root of the graph.</summary>
        public void SetRoot(AnimancerPlayable root)
        {
            if (Root == root)
            {
                return;
            }

            if (Root != null)
            {
                Root.CancelPreUpdate(this);
                Root.States.Unregister(this);

                if (_EventDispatcher != null)
                {
                    Root.CancelPostUpdate(_EventDispatcher);
                }

                if (_Parent != null)
                {
                    _Parent.OnRemoveChild(this);
                    _Parent = null;
                }

                Index = -1;

                DestroyPlayable();
            }

            Root = root;

            if (root != null)
            {
#if UNITY_ASSERTIONS
                GC.SuppressFinalize(this);
#endif

                root.States.Register(this);

                if (_EventDispatcher != null)
                {
                    root.RequirePostUpdate(_EventDispatcher);
                }

                CreatePlayable();
            }

            for (int i = ChildCount - 1; i >= 0; i--)
            {
                GetChild(i)?.SetRoot(root);
            }

            if (_Parent != null)
            {
                CopyIKFlags(_Parent);
            }
        }
Beispiel #8
0
        /************************************************************************************************************************/

        /// <summary>Constructs a new <see cref="AnimancerNode"/>.</summary>
        public AnimancerNode(AnimancerPlayable root)
        {
            if (root == null)
            {
                throw new ArgumentNullException("root");
            }

            PortIndex = -1;
            Root      = root;
        }
Beispiel #9
0
        /************************************************************************************************************************/

        /// <summary>
        /// Constructs a new <see cref="Vector2ControllerState"/> to play the 'controller' without connecting
        /// it to the <see cref="PlayableGraph"/>. You must call <see cref="AnimancerState.SetParent(AnimancerLayer)"/>
        /// or it won't actually do anything.
        /// </summary>
        private Vector2ControllerState(AnimancerPlayable root, RuntimeAnimatorController controller,
                                       Parameter parameterX, Parameter parameterY)
            : base(root, controller)
        {
            _ParameterX = parameterX;
            _ParameterX.Validate(Controller, AnimatorControllerParameterType.Float);

            _ParameterY = parameterY;
            _ParameterY.Validate(Controller, AnimatorControllerParameterType.Float);
        }
        /************************************************************************************************************************/

        /// <summary>Constructs a new <see cref="AnimancerNode"/>.</summary>
        protected AnimancerNode(AnimancerPlayable root)
        {
            if (root == null)
            {
                throw new ArgumentNullException("root");
            }

            Index = -1;
            Root  = root;
        }
        /************************************************************************************************************************/

        /// <summary>
        /// Constructs a new <see cref="Float2ControllerState"/> to play the `controller` without connecting
        /// it to the <see cref="PlayableGraph"/>.
        /// </summary>
        private Float2ControllerState(AnimancerPlayable root, RuntimeAnimatorController controller,
                                      Parameter parameterX, Parameter parameterY, bool resetStatesOnStop = true)
            : base(root, controller, resetStatesOnStop)
        {
            _ParameterX = parameterX;
            _ParameterX.ValidateHasParameter(Controller, AnimatorControllerParameterType.Float);

            _ParameterY = parameterY;
            _ParameterY.ValidateHasParameter(Controller, AnimatorControllerParameterType.Float);
        }
Beispiel #12
0
        public static void AssertRoot(AnimancerNode node, AnimancerPlayable root)
        {
#if UNITY_ASSERTIONS
            if (node.Root != root)
            {
                throw new ArgumentException($"{nameof(AnimancerNode)}.{nameof(AnimancerNode.Root)} mismatch:" +
                                            $" cannot use a node in an {nameof(AnimancerPlayable)} that is not its {nameof(AnimancerNode.Root)}: " +
                                            node.GetDescription());
            }
#endif
        }
Beispiel #13
0
        /************************************************************************************************************************/

        /// <summary>
        /// Invokes the <see cref="AnimancerEvent.Sequence.OnEnd"/> callback of the state that is playing the animation
        /// which triggered the event. Returns true if such a state exists (even if it doesn't have a callback).
        /// </summary>
        internal bool TryInvokeOnEndEvent(AnimationEvent animationEvent)
        {
            for (int i = States.Count - 1; i >= 0; i--)
            {
                if (AnimancerPlayable.TryInvokeOnEndEvent(animationEvent, States[i]))
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #14
0
        public static void Root(AnimancerNode node, AnimancerPlayable root)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (node.Root != root)
            {
                throw new ArgumentException("AnimancerNode.Root mismatch:" +
                                            " you are attempting to use a node in an AnimancerPlayable that is not it's root: " + node);
            }
        }
Beispiel #15
0
        /************************************************************************************************************************/

        /// <summary>
        /// Invokes the <see cref="AnimancerEvent.Sequence.OnEnd"/> callback of the state that is playing the animation
        /// which triggered the event. Returns true if such a state exists (even if it doesn't have a callback).
        /// </summary>
        internal bool TryInvokeOnEndEvent(AnimationEvent animationEvent)
        {
            var count = States.Count;

            for (int i = 0; i < count; i++)
            {
                if (AnimancerPlayable.TryInvokeOnEndEvent(animationEvent, States[i]))
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #16
0
        /************************************************************************************************************************/

        /// <summary>Removes a registered <see cref="ExitEvent"/> and returns true if there was one.</summary>
        public static bool Unregister(AnimancerPlayable animancer)
        {
            for (int i = animancer.PostUpdatableCount - 1; i >= 0; i--)
            {
                if (animancer.GetPostUpdatable(i) is ExitEvent exit)
                {
                    animancer.CancelPostUpdate(exit);
                    exit.Release();
                    return(true);
                }
            }

            return(false);
        }
Beispiel #17
0
        /************************************************************************************************************************/

        /// <summary>Calls <see cref="AnimancerPlayable.Play(AnimationClip)"/> or <see cref="AnimancerPlayable.Play(ITransition)"/>.</summary>
        /// <remarks>Returns null if the `clipOrTransition` is null or an unsupported type.</remarks>
        public static AnimancerState TryPlay(AnimancerPlayable animancer, Object clipOrTransition)
        {
            if (clipOrTransition is AnimationClip clip)
            {
                return(animancer.Play(clip));
            }
            else if (clipOrTransition is ITransitionDetailed transition)
            {
                return(animancer.Play(transition));
            }
            else
            {
                return(null);
            }
        }
Beispiel #18
0
        public static void Root(AnimancerNode node, AnimancerPlayable root)
        {
#if UNITY_ASSERTIONS
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (node.Root != root)
            {
                throw new ArgumentException("AnimancerNode.Root mismatch:" +
                                            " cannot use a node in an AnimancerPlayable that is not its Root: " + node.GetDescription());
            }
#endif
        }
Beispiel #19
0
        /************************************************************************************************************************/
        #region Fields and Properties
        /************************************************************************************************************************/

        /// <summary>[Internal] Creates a new <see cref="AnimancerLayer"/>.</summary>
        internal AnimancerLayer(AnimancerPlayable root, int index)
        {
            Root  = root;
            Index = index;
            CreatePlayable();

            if (ApplyParentAnimatorIK)
            {
                _ApplyAnimatorIK = root.ApplyAnimatorIK;
            }
            if (ApplyParentFootIK)
            {
                _ApplyFootIK = root.ApplyFootIK;
            }
        }
Beispiel #20
0
        /// <summary>
        /// Called by Unity when this component becomes disabled or inactive. Acts according to the
        /// <see cref="ActionOnDisable"/>.
        /// </summary>
        protected virtual void OnDisable()
        {
            if (!IsPlayableInitialised)
            {
                return;
            }

            switch (_ActionOnDisable)
            {
            case DisableAction.Stop:
                Stop();
                _Playable.PauseGraph();
                break;

            case DisableAction.Pause:
                _Playable.PauseGraph();
                break;

            case DisableAction.Continue:
                break;

            case DisableAction.Reset:
                Debug.Assert(_Animator.isActiveAndEnabled,
                             "DisableAction.Reset failed because the Animator is not enabled." +
                             " This most likely means you are disabling the GameObject and the Animator is above the" +
                             " AnimancerComponent in the Inspector so it got disabled right before this method was called." +
                             " See the Inspector of " + this + " to fix the issue or use DisableAction.Stop and call Animator.Rebind" +
                             " manually before disabling the GameObject.",
                             this);

                Stop();
                _Animator.Rebind();
                _Playable.PauseGraph();
                break;

            case DisableAction.Destroy:
                _Playable.Destroy();
                _Playable = null;
                break;

            default:
                throw new ArgumentOutOfRangeException("ActionOnDisable");
            }
        }
            /// <summary>[Pro-Only]
            /// Sets this list as the <see cref="Layers"/> and the <see cref="Playable"/> used to mix them.
            /// </summary>
            protected void Activate(AnimancerPlayable root, Playable mixer)
            {
#if UNITY_ASSERTIONS
                if (Root != root)
                {
                    throw new ArgumentException(
                              $"{nameof(AnimancerPlayable)}.{nameof(LayerList)}.{nameof(Root)} mismatch:" +
                              $" cannot use a list in an {nameof(AnimancerPlayable)} that is not its {nameof(Root)}");
                }
#endif

                _Layers = root.Layers._Layers;
                _Count  = root.Layers._Count;

                root._RootPlayable.DisconnectInput(0);
                root.Graph.Connect(mixer, 0, root._RootPlayable, 0);
                root.Layers      = this;
                root._LayerMixer = mixer;
            }
Beispiel #22
0
        /************************************************************************************************************************/
        #region Fields and Properties
        /************************************************************************************************************************/

        /// <summary>[Internal] Creates a new <see cref="AnimancerLayer"/>.</summary>
        internal AnimancerLayer(AnimancerPlayable root, int index)
        {
#if UNITY_ASSERTIONS
            GC.SuppressFinalize(this);
#endif

            Root  = root;
            Index = index;
            CreatePlayable();

            if (ApplyParentAnimatorIK)
            {
                _ApplyAnimatorIK = root.ApplyAnimatorIK;
            }
            if (ApplyParentFootIK)
            {
                _ApplyFootIK = root.ApplyFootIK;
            }
        }
Beispiel #23
0
        /************************************************************************************************************************/

        /// <summary>
        /// Constructs a new <see cref="LinearMixerState"/> without connecting it to the <see cref="PlayableGraph"/>.
        /// You must call <see cref="AnimancerState.SetParent(AnimancerLayer)"/> or it won't actually do anything.
        /// </summary>
        private LinearMixerState(AnimancerPlayable root) : base(root)
        {
        }
        /************************************************************************************************************************/

        /// <summary>
        /// Constructs a new <see cref="DirectionalMixerState"/> without connecting it to the <see cref="PlayableGraph"/>.
        /// You must call <see cref="AnimancerState.SetParent(AnimancerLayer)"/> or it won't actually do anything.
        /// </summary>
        protected DirectionalMixerState(AnimancerPlayable root) : base(root)
        {
        }
        /************************************************************************************************************************/
        #region Fields and Properties
        /************************************************************************************************************************/

        /// <summary>[Internal] Constructs a new <see cref="AnimancerLayer"/>.</summary>
        internal AnimancerLayer(AnimancerPlayable root, int index)
        {
            Root  = root;
            Index = index;
            CreatePlayable();
        }
Beispiel #26
0
            /************************************************************************************************************************/

            /// <summary>[Internal] Creates a new <see cref="StateDictionary"/>.</summary>
            internal StateDictionary(AnimancerPlayable root) => Root = root;
Beispiel #27
0
        /************************************************************************************************************************/
        #endregion
        /************************************************************************************************************************/
        #endregion
        /************************************************************************************************************************/
        #region Public Methods
        /************************************************************************************************************************/

        /// <summary>Constructs a new <see cref="AnimancerState"/>.</summary>
        public AnimancerState(AnimancerPlayable root) : base(root)
        {
        }
Beispiel #28
0
        /************************************************************************************************************************/
        #endregion
        /************************************************************************************************************************/
        #region Initialisation
        /************************************************************************************************************************/

        /// <summary>
        /// Constructs a new <see cref="LinearMixerState"/> without connecting it to the <see cref="PlayableGraph"/>.
        /// </summary>
        protected ManualMixerState(AnimancerPlayable root) : base(root)
        {
        }
Beispiel #29
0
            /************************************************************************************************************************/

            /// <summary>[Internal] Creates a new <see cref="LayerList"/>.</summary>
            internal LayerList(AnimancerPlayable root, out Playable layerMixer)
            {
                Root       = root;
                layerMixer = LayerMixer = AnimationLayerMixerPlayable.Create(root._Graph, 1);
                Root._Graph.Connect(layerMixer, 0, Root._RootPlayable, 0);
            }
Beispiel #30
0
        /************************************************************************************************************************/

        /// <summary>Calls <see cref="ITransition.CreateState"/> and <see cref="ITransition.Apply"/>.</summary>
        public static AnimancerState CreateStateAndApply(this ITransition transition, AnimancerPlayable root = null)
        {
            var state = transition.CreateState();

            state.SetRoot(root);
            transition.Apply(state);
            return(state);
        }