123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.Playables;
- namespace Animancer
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [AddComponentMenu(Strings.MenuPrefix + "Animancer Component")]
- [HelpURL(Strings.DocsURLs.APIDocumentation + "/" + nameof(AnimancerComponent))]
- [DefaultExecutionOrder(DefaultExecutionOrder)]
- public class AnimancerComponent : MonoBehaviour,
- IAnimancerComponent, IEnumerator, IAnimationClipSource, IAnimationClipCollection
- {
-
- #region Fields and Properties
-
-
- public const int DefaultExecutionOrder = -5000;
-
- [SerializeField, Tooltip("The Animator component which this script controls")]
- private Animator _Animator;
-
-
-
- public Animator Animator
- {
- get => _Animator;
- set
- {
- _Animator = value;
- if (IsPlayableInitialized)
- {
- _Playable.DestroyOutput();
- _Playable.CreateOutput(value, this);
- }
- }
- }
- #if UNITY_EDITOR
-
- string IAnimancerComponent.AnimatorFieldName => nameof(_Animator);
- #endif
-
- private AnimancerPlayable _Playable;
-
-
-
-
- public AnimancerPlayable Playable
- {
- get
- {
- InitializePlayable();
- return _Playable;
- }
- }
-
- public bool IsPlayableInitialized => _Playable != null && _Playable.IsValid;
-
-
- public AnimancerPlayable.StateDictionary States => Playable.States;
-
- public AnimancerPlayable.LayerList Layers => Playable.Layers;
-
- public static implicit operator AnimancerPlayable(AnimancerComponent animancer) => animancer.Playable;
-
- public static implicit operator AnimancerLayer(AnimancerComponent animancer) => animancer.Playable.Layers[0];
-
- [SerializeField, Tooltip("Determines what happens when this component is disabled" +
- " or its " + nameof(GameObject) + " becomes inactive (i.e. in " + nameof(OnDisable) + "):" +
- "\n• " + nameof(DisableAction.Stop) + " all animations" +
- "\n• " + nameof(DisableAction.Pause) + " all animations" +
- "\n• " + nameof(DisableAction.Continue) + " playing" +
- "\n• " + nameof(DisableAction.Reset) + " to the original values" +
- "\n• " + nameof(DisableAction.Destroy) + " all layers and states")]
- private DisableAction _ActionOnDisable;
- #if UNITY_EDITOR
-
- string IAnimancerComponent.ActionOnDisableFieldName => nameof(_ActionOnDisable);
- #endif
-
-
-
-
-
- public ref DisableAction ActionOnDisable => ref _ActionOnDisable;
-
- bool IAnimancerComponent.ResetOnDisable => _ActionOnDisable == DisableAction.Reset;
-
-
-
- public enum DisableAction
- {
-
-
-
-
-
- Stop,
-
-
- Pause,
-
- Continue,
-
-
-
-
-
-
-
-
-
-
- Reset,
-
-
-
-
-
-
- Destroy,
- }
-
- #region Update Mode
-
-
-
-
-
-
-
- public AnimatorUpdateMode UpdateMode
- {
- get => _Animator.updateMode;
- set
- {
- _Animator.updateMode = value;
- if (!IsPlayableInitialized)
- return;
-
-
- _Playable.UpdateMode = value == AnimatorUpdateMode.UnscaledTime ?
- DirectorUpdateMode.UnscaledGameTime :
- DirectorUpdateMode.GameTime;
- #if UNITY_EDITOR
- if (InitialUpdateMode == null)
- {
- InitialUpdateMode = value;
- }
- else if (UnityEditor.EditorApplication.isPlaying)
- {
- if (AnimancerPlayable.HasChangedToOrFromAnimatePhysics(InitialUpdateMode, value))
- Debug.LogWarning($"Changing the {nameof(Animator)}.{nameof(Animator.updateMode)}" +
- $" to or from {nameof(AnimatorUpdateMode.AnimatePhysics)} at runtime will have no effect." +
- " You must set it in the Unity Editor or on startup.", this);
- }
- #endif
- }
- }
-
- #if UNITY_EDITOR
-
- public AnimatorUpdateMode? InitialUpdateMode { get; private set; }
- #endif
-
- #endregion
-
- #endregion
-
- #region Initialization
-
- #if UNITY_EDITOR
-
-
-
-
- protected virtual void Reset()
- {
- OnDestroy();
- gameObject.GetComponentInParentOrChildren(ref _Animator);
- }
- #endif
-
-
- protected virtual void OnEnable()
- {
- if (IsPlayableInitialized)
- _Playable.UnpauseGraph();
- }
-
- protected virtual void OnDisable()
- {
- if (!IsPlayableInitialized)
- 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,
- $"{nameof(DisableAction)}.{nameof(DisableAction.Reset)} failed because the {nameof(Animator)} is not enabled." +
- $" This most likely means you are disabling the {nameof(GameObject)} and the {nameof(Animator)} is above the" +
- $" {nameof(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 {nameof(DisableAction)}.{nameof(DisableAction.Stop)}" +
- $" and call {nameof(Animator)}.{nameof(Animator.Rebind)} manually" +
- $" before disabling the {nameof(GameObject)}.",
- this);
- Stop();
- _Animator.Rebind();
- _Playable.PauseGraph();
- break;
- case DisableAction.Destroy:
- _Playable.DestroyGraph();
- _Playable = null;
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(ActionOnDisable));
- }
- }
-
-
- public void InitializePlayable()
- {
- if (IsPlayableInitialized)
- return;
- if (_Animator == null)
- _Animator = GetComponent<Animator>();
- #if UNITY_ASSERTIONS
- ValidatePlayableInitialization();
- #endif
- AnimancerPlayable.SetNextGraphName(name + " (Animancer)");
- _Playable = AnimancerPlayable.Create();
- _Playable.CreateOutput(_Animator, this);
- #if UNITY_EDITOR
- if (_Animator != null)
- InitialUpdateMode = UpdateMode;
- #endif
- }
-
-
-
-
-
-
- public void InitializePlayable(PlayableGraph graph)
- {
- if (IsPlayableInitialized)
- throw new InvalidOperationException($"The {nameof(AnimancerPlayable)} is already initialized." +
- $" Either call this method before anything else uses it or call" +
- $" animancerComponent.{nameof(Playable)}.{nameof(AnimancerPlayable.DestroyGraph)} before re-initializing it.");
- if (_Animator == null)
- _Animator = GetComponent<Animator>();
- #if UNITY_ASSERTIONS
- ValidatePlayableInitialization();
- #endif
- _Playable = AnimancerPlayable.Create(graph);
- _Playable.CreateOutput(_Animator, this);
- #if UNITY_EDITOR
- if (_Animator != null)
- InitialUpdateMode = UpdateMode;
- #endif
- }
-
- #if UNITY_ASSERTIONS
-
- private void ValidatePlayableInitialization()
- {
- #if UNITY_EDITOR
- if (OptionalWarning.CreateGraphDuringGuiEvent.IsEnabled())
- {
- var currentEvent = Event.current;
- if (currentEvent != null && (currentEvent.type == EventType.Layout || currentEvent.type == EventType.Repaint))
- OptionalWarning.CreateGraphDuringGuiEvent.Log(
- $"An {nameof(AnimancerPlayable)} is being created during a {currentEvent.type} event" +
- $" which is likely undesirable.", this);
- }
- if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
- #endif
- {
- if (!gameObject.activeInHierarchy)
- OptionalWarning.CreateGraphWhileDisabled.Log($"An {nameof(AnimancerPlayable)} is being created for '{this}'" +
- $" which is attached to an inactive {nameof(GameObject)}." +
- $" If that object is never activated then Unity will not call {nameof(OnDestroy)}" +
- $" so {nameof(AnimancerPlayable)}.{nameof(AnimancerPlayable.DestroyGraph)} will need to be called manually.", this);
- }
- if (_Animator != null && _Animator.isHuman && _Animator.runtimeAnimatorController != null)
- OptionalWarning.NativeControllerHumanoid.Log($"An Animator Controller is assigned to the" +
- $" {nameof(Animator)} component but the Rig is Humanoid so it can't be blended with Animancer." +
- $" See the documentation for more information: {Strings.DocsURLs.AnimatorControllersNative}", this);
- }
- #endif
-
-
- protected virtual void OnDestroy()
- {
- if (IsPlayableInitialized)
- {
- _Playable.DestroyGraph();
- _Playable = null;
- }
- }
-
- #if UNITY_EDITOR
-
-
-
-
- ~AnimancerComponent()
- {
- if (_Playable != null)
- {
- UnityEditor.EditorApplication.delayCall += () =>
- {
- if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
- OnDestroy();
- };
- }
- }
- #endif
-
- #endregion
-
- #region Play Management
-
-
-
-
-
-
- public virtual object GetKey(AnimationClip clip) => clip;
-
-
-
-
-
-
-
-
-
-
- public AnimancerState Play(AnimationClip clip)
- => Playable.Play(States.GetOrCreate(clip));
-
-
-
-
-
-
-
- public AnimancerState Play(AnimancerState state)
- => Playable.Play(state);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public AnimancerState Play(AnimationClip clip, float fadeDuration, FadeMode mode = default)
- => Playable.Play(States.GetOrCreate(clip), fadeDuration, mode);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public AnimancerState Play(AnimancerState state, float fadeDuration, FadeMode mode = default)
- => Playable.Play(state, fadeDuration, mode);
-
-
-
-
-
-
-
-
-
-
-
- public AnimancerState Play(ITransition transition)
- => Playable.Play(transition);
-
-
-
-
-
-
-
-
- public AnimancerState Play(ITransition transition, float fadeDuration, FadeMode mode = default)
- => Playable.Play(transition, fadeDuration, mode);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public AnimancerState TryPlay(object key)
- => Playable.TryPlay(key);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public AnimancerState TryPlay(object key, float fadeDuration, FadeMode mode = default)
- => Playable.TryPlay(key, fadeDuration, mode);
-
-
-
-
- public AnimancerState Stop(AnimationClip clip) => Stop(GetKey(clip));
-
-
-
-
- public AnimancerState Stop(IHasKey hasKey) => _Playable?.Stop(hasKey);
-
-
-
- public AnimancerState Stop(object key) => _Playable?.Stop(key);
-
-
-
- public void Stop()
- {
- if (_Playable != null)
- _Playable.Stop();
- }
-
-
-
-
-
-
- public bool IsPlaying(AnimationClip clip) => IsPlaying(GetKey(clip));
-
-
-
- public bool IsPlaying(IHasKey hasKey) => _Playable != null && _Playable.IsPlaying(hasKey);
-
-
-
- public bool IsPlaying(object key) => _Playable != null && _Playable.IsPlaying(key);
-
-
-
- public bool IsPlaying() => _Playable != null && _Playable.IsPlaying();
-
-
-
-
-
-
-
- public bool IsPlayingClip(AnimationClip clip) => _Playable != null && _Playable.IsPlayingClip(clip);
-
-
-
-
- public void Evaluate() => Playable.Evaluate();
-
-
-
-
- public void Evaluate(float deltaTime) => Playable.Evaluate(deltaTime);
-
- #region Key Error Methods
- #if UNITY_EDITOR
-
-
-
-
-
-
-
-
- [Obsolete("You should not use an AnimancerState as a key. Just call AnimancerState.Stop().", true)]
- public AnimancerState Stop(AnimancerState key)
- {
- key.Stop();
- return key;
- }
-
-
-
-
- [Obsolete("You should not use an AnimancerState as a key. Just check AnimancerState.IsPlaying.", true)]
- public bool IsPlaying(AnimancerState key) => key.IsPlaying;
-
- #endif
- #endregion
-
- #endregion
-
- #region Enumeration
-
-
-
-
-
-
- bool IEnumerator.MoveNext()
- {
- if (!IsPlayableInitialized)
- return false;
- return ((IEnumerator)_Playable).MoveNext();
- }
-
- object IEnumerator.Current => null;
-
- void IEnumerator.Reset() { }
-
-
-
-
- public void GetAnimationClips(List<AnimationClip> clips)
- {
- var set = ObjectPool.AcquireSet<AnimationClip>();
- set.UnionWith(clips);
- GatherAnimationClips(set);
- clips.Clear();
- clips.AddRange(set);
- ObjectPool.Release(set);
- }
-
-
-
-
-
-
- public virtual void GatherAnimationClips(ICollection<AnimationClip> clips)
- {
- if (IsPlayableInitialized)
- _Playable.GatherAnimationClips(clips);
- #if UNITY_EDITOR
- Editor.AnimationGatherer.GatherFromGameObject(gameObject, clips);
- if (_Animator != null && _Animator.gameObject != gameObject)
- Editor.AnimationGatherer.GatherFromGameObject(_Animator.gameObject, clips);
- #endif
- }
-
- #endregion
-
- }
- }
|