using System;
using System.Collections;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
namespace LitMotion
{
///
/// Provides methods for manipulating the motion entity pointed to by MotionHandle.
///
public static class MotionHandleExtensions
{
///
/// Checks if a motion is currently playing.
///
/// This motion handle
/// True if motion is active, otherwise false.
public static bool IsActive(this MotionHandle handle)
{
return MotionStorageManager.IsActive(handle);
}
///
/// Complete motion.
///
/// This motion handle
public static void Complete(this MotionHandle handle)
{
MotionStorageManager.CompleteMotion(handle);
}
///
/// Cancel motion.
///
/// This motion handle
public static void Cancel(this MotionHandle handle)
{
MotionStorageManager.CancelMotion(handle);
}
///
/// Add this motion handle to CompositeMotionHandle.
///
/// This motion handle
/// target CompositeMotionHandle
public static MotionHandle AddTo(this MotionHandle handle, CompositeMotionHandle compositeMotionHandle)
{
compositeMotionHandle.Add(handle);
return handle;
}
///
/// Link the motion lifecycle to the target object.
///
/// This motion handle
/// Target object
public static MotionHandle AddTo(this MotionHandle handle, GameObject target)
{
GetOrAddComponent(target).Register(handle, LinkBehaviour.CancelOnDestroy);
return handle;
}
///
/// Link the motion lifecycle to the target object.
///
/// This motion handle
/// Target object
/// Link behaviour
public static MotionHandle AddTo(this MotionHandle handle, GameObject target, LinkBehaviour linkBehaviour)
{
GetOrAddComponent(target).Register(handle, linkBehaviour);
return handle;
}
///
/// Link the motion lifecycle to the target object.
///
/// This motion handle
/// Target object
public static MotionHandle AddTo(this MotionHandle handle, Component target)
{
GetOrAddComponent(target.gameObject).Register(handle, LinkBehaviour.CancelOnDestroy);
return handle;
}
///
/// Link the motion lifecycle to the target object.
///
/// This motion handle
/// Target object
/// Link behaviour
public static MotionHandle AddTo(this MotionHandle handle, Component target, LinkBehaviour linkBehaviour)
{
GetOrAddComponent(target.gameObject).Register(handle, linkBehaviour);
return handle;
}
#if UNITY_2022_2_OR_NEWER
///
/// Link the motion lifecycle to the target object.
///
/// This motion handle
/// Target object
public static MotionHandle AddTo(this MotionHandle handle, MonoBehaviour target)
{
target.destroyCancellationToken.Register(() =>
{
if (handle.IsActive()) handle.Cancel();
}, false);
return handle;
}
#endif
static TComponent GetOrAddComponent(GameObject target) where TComponent : Component
{
if (!target.TryGetComponent(out var component))
{
component = target.AddComponent();
}
return component;
}
///
/// Convert MotionHandle to IDisposable.
///
/// This motion handle
///
public static IDisposable ToDisposable(this MotionHandle handle)
{
return new MotionHandleDisposable(handle);
}
///
/// Wait for the motion to finish in a coroutine.
///
/// This motion handle
///
public static IEnumerator ToYieldInteraction(this MotionHandle handle)
{
while (handle.IsActive())
{
yield return null;
}
}
public static MotionAwaiter GetAwaiter(this MotionHandle handle)
{
return new MotionAwaiter(handle);
}
///
/// Convert motion handle to ValueTask.
///
/// This motion handle
/// CancellationToken
///
public static ValueTask ToValueTask(this MotionHandle handle, CancellationToken cancellationToken = default)
{
if (!handle.IsActive()) return default;
var source = ValueTaskMotionConfiguredSource.Create(handle, CancelBehaviour.CancelAndCancelAwait, cancellationToken, out var token);
return new ValueTask(source, token);
}
///
/// Convert motion handle to ValueTask.
///
/// This motion handle
/// Behavior when canceling
/// CancellationToken
///
public static ValueTask ToValueTask(this MotionHandle handle, CancelBehaviour cancelBehaviour, CancellationToken cancellationToken = default)
{
if (!handle.IsActive()) return default;
var source = ValueTaskMotionConfiguredSource.Create(handle, cancelBehaviour, cancellationToken, out var token);
return new ValueTask(source, token);
}
#if UNITY_2023_1_OR_NEWER
///
/// Convert motion handle to Awaitable.
///
/// This motion handle
/// CancellationToken
///
public static Awaitable ToAwaitable(this MotionHandle handle, CancellationToken cancellationToken = default)
{
if (!handle.IsActive()) return AwaitableMotionConfiguredSource.CompletedSource.Awaitable;
return AwaitableMotionConfiguredSource.Create(handle, CancelBehaviour.CancelAndCancelAwait, cancellationToken).Awaitable;
}
///
/// Convert motion handle to Awaitable.
///
/// This motion handle
/// Behavior when canceling
/// CancellationToken
///
public static Awaitable ToAwaitable(this MotionHandle handle, CancelBehaviour cancelBehaviour, CancellationToken cancellationToken = default)
{
if (!handle.IsActive()) return AwaitableMotionConfiguredSource.CompletedSource.Awaitable;
return AwaitableMotionConfiguredSource.Create(handle, cancelBehaviour, cancellationToken).Awaitable;
}
#endif
}
internal sealed class MotionHandleDisposable : IDisposable
{
public MotionHandleDisposable(MotionHandle handle) => this.handle = handle;
public readonly MotionHandle handle;
public void Dispose()
{
if (handle.IsActive()) handle.Cancel();
}
}
}