// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
using System;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Playables;
using Object = UnityEngine.Object;
namespace Animancer
{
/// An which plays an .
///
/// Documentation:
///
/// States
///
/// https://kybernetik.com.au/animancer/api/Animancer/ClipState
///
public class ClipState : AnimancerState
{
/************************************************************************************************************************/
#region Fields and Properties
/************************************************************************************************************************/
private AnimationClip _Clip;
/// The which this state plays.
public override AnimationClip Clip
{
get => _Clip;
set
{
Validate.AssertAnimationClip(value, true, $"set {nameof(ClipState)}.{nameof(Clip)}");
if (ChangeMainObject(ref _Clip, value))
{
_Length = value.length;
var isLooping = value.isLooping;
if (_IsLooping != isLooping)
{
_IsLooping = isLooping;
OnIsLoopingChangedRecursive(isLooping);
}
}
}
}
/// The which this state plays.
public override Object MainObject
{
get => _Clip;
set => Clip = (AnimationClip)value;
}
#if UNITY_EDITOR
///
public override Type MainObjectType
=> typeof(AnimationClip);
#endif
/************************************************************************************************************************/
private float _Length;
/// The .
public override float Length
=> _Length;
/************************************************************************************************************************/
private bool _IsLooping;
/// The .
public override bool IsLooping
=> _IsLooping;
/************************************************************************************************************************/
///
public override void GetEventDispatchInfo(
out float length,
out float normalizedTime,
out bool isLooping)
{
length = _Length;
normalizedTime = length != 0
? Time / length
: 0;
isLooping = _IsLooping;
}
/************************************************************************************************************************/
///
public override Vector3 AverageVelocity
=> _Clip.averageSpeed;
/************************************************************************************************************************/
#region Inverse Kinematics
/************************************************************************************************************************/
///
public override bool ApplyAnimatorIK
{
get => _Playable.IsValid() && ((AnimationClipPlayable)_Playable).GetApplyPlayableIK();
set
{
Validate.AssertPlayable(this);
((AnimationClipPlayable)_Playable).SetApplyPlayableIK(value);
}
}
/************************************************************************************************************************/
///
public override bool ApplyFootIK
{
get => _Playable.IsValid() && ((AnimationClipPlayable)_Playable).GetApplyFootIK();
set
{
Validate.AssertPlayable(this);
((AnimationClipPlayable)_Playable).SetApplyFootIK(value);
}
}
/************************************************************************************************************************/
#endregion
/************************************************************************************************************************/
#endregion
/************************************************************************************************************************/
#region Methods
/************************************************************************************************************************/
/// Creates a new and sets its .
/// The `clip` is null.
public ClipState(AnimationClip clip)
{
Validate.AssertAnimationClip(clip, true, $"create {nameof(ClipState)}");
_Clip = clip;
_Length = clip.length;
_IsLooping = clip.isLooping;
}
/************************************************************************************************************************/
/// Creates and assigns the managed by this node.
protected override void CreatePlayable(out Playable playable)
{
playable = AnimationClipPlayable.Create(Graph._PlayableGraph, _Clip);
}
/************************************************************************************************************************/
///
public override void RecreatePlayable()
{
var playable = (AnimationClipPlayable)_Playable;
var footIK = playable.GetApplyFootIK();
var playableIK = playable.GetApplyPlayableIK();
base.RecreatePlayable();
playable = (AnimationClipPlayable)_Playable;
playable.SetApplyFootIK(footIK);
playable.SetApplyPlayableIK(playableIK);
}
/************************************************************************************************************************/
///
public override void Destroy()
{
_Clip = null;
base.Destroy();
}
/************************************************************************************************************************/
///
public override AnimancerState Clone(CloneContext context)
{
var clip = context.GetCloneOrOriginal(_Clip);
var clone = new ClipState(clip);
clone.CopyFrom(this, context);
return clone;
}
/************************************************************************************************************************/
#endregion
/************************************************************************************************************************/
}
}