// 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
/************************************************************************************************************************/
}
}