// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2023 Kybernetik // using Animancer.Units; using System; using System.Collections.Generic; using UnityEngine; using Object = UnityEngine.Object; namespace Animancer { /// /// https://kybernetik.com.au/animancer/api/Animancer/ClipTransitionAsset [CreateAssetMenu(menuName = Strings.MenuPrefix + "Clip Transition", order = Strings.AssetMenuOrder + 1)] [HelpURL(Strings.DocsURLs.APIDocumentation + "/" + nameof(ClipTransitionAsset))] public class ClipTransitionAsset : AnimancerTransitionAsset { /// [Serializable] public new class UnShared : UnShared, ClipState.ITransition { } } /// /// https://kybernetik.com.au/animancer/api/Animancer/ClipTransition [Serializable] public class ClipTransition : AnimancerTransition, ClipState.ITransition, IMotion, IAnimationClipCollection, ICopyable { /************************************************************************************************************************/ /// The name of the serialized backing field of . public const string ClipFieldName = nameof(_Clip); [SerializeField, Tooltip("The animation to play")] private AnimationClip _Clip; /// [] The animation to play. public AnimationClip Clip { get => _Clip; set { #if UNITY_ASSERTIONS if (value != null) Validate.AssertNotLegacy(value); #endif _Clip = value; } } /// public override Object MainObject => _Clip; /// Returns the to use as the . public override object Key => _Clip; /************************************************************************************************************************/ [SerializeField] [Tooltip(Strings.Tooltips.OptionalSpeed)] [AnimationSpeed] [DefaultValue(1f, -1f)] private float _Speed = 1; /// public override float Speed { get => _Speed; set => _Speed = value; } /************************************************************************************************************************/ [SerializeField] [Tooltip(Strings.Tooltips.NormalizedStartTime)] [AnimationTime(AnimationTimeAttribute.Units.Normalized)] [DefaultValue(float.NaN, 0f)] private float _NormalizedStartTime = float.NaN; /// public override float NormalizedStartTime { get => _NormalizedStartTime; set => _NormalizedStartTime = value; } /// /// If this transition will set the , then it needs to use /// . /// public override FadeMode FadeMode => float.IsNaN(_NormalizedStartTime) ? FadeMode.FixedSpeed : FadeMode.FromStart; /************************************************************************************************************************/ /// /// The length of the (in seconds), accounting for the and /// (but not ). /// public virtual float Length { get { if (!IsValid) return 0; var normalizedEndTime = Events.NormalizedEndTime; normalizedEndTime = !float.IsNaN(normalizedEndTime) ? normalizedEndTime : AnimancerEvent.Sequence.GetDefaultNormalizedEndTime(_Speed); var normalizedStartTime = !float.IsNaN(_NormalizedStartTime) ? _NormalizedStartTime : AnimancerEvent.Sequence.GetDefaultNormalizedStartTime(_Speed); return _Clip.length * (normalizedEndTime - normalizedStartTime); } } /************************************************************************************************************************/ /// public override bool IsValid => _Clip != null && !_Clip.legacy; /// [] Is the looping? public override bool IsLooping => _Clip != null && _Clip.isLooping; /// public override float MaximumDuration => _Clip != null ? _Clip.length : 0; /// public virtual float AverageAngularSpeed => _Clip != null ? _Clip.averageAngularSpeed : default; /// public virtual Vector3 AverageVelocity => _Clip != null ? _Clip.averageSpeed : default; /************************************************************************************************************************/ /// public override ClipState CreateState() { #if UNITY_ASSERTIONS if (_Clip == null) throw new ArgumentException( $"Unable to create {nameof(ClipState)} because the {nameof(ClipTransition)}.{nameof(Clip)} is null."); #endif return State = new ClipState(_Clip); } /************************************************************************************************************************/ /// public override void Apply(AnimancerState state) { ApplyDetails(state, _Speed, _NormalizedStartTime); base.Apply(state); } /************************************************************************************************************************/ /// [] Adds the to the collection. public virtual void GatherAnimationClips(ICollection clips) => clips.Gather(_Clip); /************************************************************************************************************************/ /// public virtual void CopyFrom(ClipTransition copyFrom) { CopyFrom((AnimancerTransition)copyFrom); if (copyFrom == null) { _Clip = default; _Speed = 1; _NormalizedStartTime = float.NaN; return; } _Clip = copyFrom._Clip; _Speed = copyFrom._Speed; _NormalizedStartTime = copyFrom._NormalizedStartTime; } /************************************************************************************************************************/ #if UNITY_EDITOR /************************************************************************************************************************/ /// [UnityEditor.CustomPropertyDrawer(typeof(ClipTransition), true)] public class Drawer : Editor.TransitionDrawer { /************************************************************************************************************************/ /// Creates a new . public Drawer() : base(ClipFieldName) { } /************************************************************************************************************************/ } /************************************************************************************************************************/ #endif /************************************************************************************************************************/ } }