// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2023 Kybernetik // using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Playables; using Object = UnityEngine.Object; namespace Animancer { /// /// An which uses the s of s /// so they can be referenced using strings as well as the clips themselves. /// /// /// /// It also has fields to automatically register animations on startup and play the first one automatically without /// needing another script to control it, much like Unity's Legacy component. /// /// Documentation: Component Types /// /// /// Named Animations /// /// https://kybernetik.com.au/animancer/api/Animancer/NamedAnimancerComponent /// [AddComponentMenu(Strings.MenuPrefix + "Named Animancer Component")] [HelpURL(Strings.DocsURLs.APIDocumentation + "/" + nameof(NamedAnimancerComponent))] public class NamedAnimancerComponent : AnimancerComponent { /************************************************************************************************************************/ #region Fields and Properties /************************************************************************************************************************/ [SerializeField, Tooltip("If true, the 'Default Animation' will be automatically played by " + nameof(OnEnable))] private bool _PlayAutomatically = true; /// [] /// If true, the first clip in the array will be automatically played by /// . /// public ref bool PlayAutomatically => ref _PlayAutomatically; /************************************************************************************************************************/ [SerializeField, Tooltip("Animations in this array will be automatically registered by " + nameof(Awake) + " as states that can be retrieved using their name")] private AnimationClip[] _Animations; /// [] /// Animations in this array will be automatically registered by as states that can be /// retrieved using their name and the first element will be played by if /// is true. /// public AnimationClip[] Animations { get => _Animations; set { _Animations = value; States.CreateIfNew(value); } } /************************************************************************************************************************/ /// /// The first element in the array. It will be automatically played by /// if is true. /// public AnimationClip DefaultAnimation { get => _Animations.IsNullOrEmpty() ? null : _Animations[0]; set { if (_Animations.IsNullOrEmpty()) _Animations = new AnimationClip[] { value }; else _Animations[0] = value; } } /************************************************************************************************************************/ #endregion /************************************************************************************************************************/ #region Methods /************************************************************************************************************************/ #if UNITY_EDITOR /// [Editor-Only] /// Uses to ensure that all of the clips in the /// array are supported by the system and removes any others. /// /// Called in Edit Mode whenever this script is loaded or a value is changed in the Inspector. protected virtual void OnValidate() { if (_Animations == null) return; for (int i = 0; i < _Animations.Length; i++) { var clip = _Animations[i]; if (clip == null) continue; try { Validate.AssertNotLegacy(clip); continue; } catch (Exception exception) { Debug.LogException(exception, clip); } Array.Copy(_Animations, i + 1, _Animations, i, _Animations.Length - (i + 1)); Array.Resize(ref _Animations, _Animations.Length - 1); i--; } } #endif /************************************************************************************************************************/ /// Creates a state for each clip in the array. protected virtual void Awake() { if (!TryGetAnimator()) return; States.CreateIfNew(_Animations); } /************************************************************************************************************************/ /// /// Plays the first clip in the array if is true. /// /// This method also ensures that the is playing. protected override void OnEnable() { if (!TryGetAnimator()) return; base.OnEnable(); if (_PlayAutomatically && !_Animations.IsNullOrEmpty()) { var clip = _Animations[0]; if (clip != null) Play(clip); } } /************************************************************************************************************************/ /// Returns the clip's name. /// /// This method is used to determine the dictionary key to use for an animation when none is specified by the /// caller, such as in . /// public override object GetKey(AnimationClip clip) => clip.name; /************************************************************************************************************************/ /// public override void GatherAnimationClips(ICollection clips) { base.GatherAnimationClips(clips); clips.Gather(_Animations); } /************************************************************************************************************************/ #endregion /************************************************************************************************************************/ } }