355 lines
13 KiB
C#
355 lines
13 KiB
C#
// --------------------------------------------------------------------------------------------------------------------
|
|
// <copyright file="UxrTween.cs" company="VRMADA">
|
|
// Copyright (c) VRMADA, All rights reserved.
|
|
// </copyright>
|
|
// --------------------------------------------------------------------------------------------------------------------
|
|
using System;
|
|
using System.Linq;
|
|
using UltimateXR.Animation.Interpolation;
|
|
using UltimateXR.Attributes;
|
|
using UltimateXR.Core.Components;
|
|
using UltimateXR.Extensions.System.Collections;
|
|
using UnityEngine;
|
|
|
|
namespace UltimateXR.Animation.UI
|
|
{
|
|
/// <summary>
|
|
/// <para>
|
|
/// Base abstract class to create tweening components to animate Unity UI elements.
|
|
/// </para>
|
|
/// <para>
|
|
/// Tweens are <see cref="UxrComponent" /> components to allow access to the global list of tweens
|
|
/// or filter by type.
|
|
/// </para>
|
|
/// <para>
|
|
/// They are also <see cref="UxrComponent{TP,TC}" /> to allow access to the global list of tweens in a
|
|
/// given parent canvas.
|
|
/// </para>
|
|
/// </summary>
|
|
public abstract class UxrTween : UxrComponent<Canvas, UxrTween>
|
|
{
|
|
#region Inspector Properties/Serialized Fields
|
|
|
|
[SerializeField] [ReadOnly(HideInEditMode = true)] private bool _hasFinished;
|
|
[SerializeField] private UxrInterpolationSettings _interpolationSettings = new UxrInterpolationSettings();
|
|
[SerializeField] private UxrTweenFinishedActions _finishedActions = UxrTweenFinishedActions.None;
|
|
|
|
#endregion
|
|
|
|
#region Public Types & Data
|
|
|
|
/// <summary>
|
|
/// Called when the animation finished.
|
|
/// </summary>
|
|
public event Action Finished;
|
|
|
|
/// <summary>
|
|
/// Gets the current animation time in seconds. The animation time is the scaled or unscaled time relative to the time
|
|
/// the component was enabled.
|
|
/// </summary>
|
|
public float AnimationTime => CurrentTime - _startTime;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the interpolation settings.
|
|
/// </summary>
|
|
public UxrInterpolationSettings InterpolationSettings
|
|
{
|
|
get => _interpolationSettings;
|
|
protected set => _interpolationSettings = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets whether the animation finished.
|
|
/// </summary>
|
|
public bool HasFinished
|
|
{
|
|
get => _hasFinished;
|
|
private set => _hasFinished = value;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Checks if the given behaviour has a running tween of any type.
|
|
/// </summary>
|
|
/// <returns>Whether there is a running tween animation.</returns>
|
|
public static bool HasActiveTween(Behaviour behaviour)
|
|
{
|
|
UxrTween[] tweens = behaviour.GetComponents<UxrTween>();
|
|
return tweens.Length > 0 && tweens.Any(t => !t.HasFinished);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if the given behaviour has a running tween of a specific type.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of <see cref="UxrTween" />s to check for.</typeparam>
|
|
/// <returns>Whether there is a running animation of the given type.</returns>
|
|
public static bool HasActiveTween<T>(Behaviour behaviour) where T : UxrTween
|
|
{
|
|
T tween = behaviour.GetComponent<T>();
|
|
return tween && !tween.HasFinished;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops all enabled tweens.
|
|
/// </summary>
|
|
/// <param name="restoreOriginal">Whether to reset each animated component to the state before its animation started</param>
|
|
public static void StopAll(bool restoreOriginal = true)
|
|
{
|
|
EnabledComponents.ForEach(t => t.Stop(restoreOriginal));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops all enabled tweens of a given type.
|
|
/// </summary>
|
|
/// <param name="restoreOriginal">Whether to reset each animated component to the state before its animation started</param>
|
|
/// <typeparam name="T">Type of <see cref="UxrTween" />s to stop</typeparam>
|
|
public static void StopAll<T>(bool restoreOriginal = true) where T : UxrTween
|
|
{
|
|
EnabledComponents.OfType<T>().ForEach(t => t.Stop(restoreOriginal));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops all enabled tweens that are in a given canvas.
|
|
/// </summary>
|
|
/// <param name="canvas">Canvas to disable all enabled tweens from</param>
|
|
/// <param name="restoreOriginal">Whether to reset each animated component to the state before its animation started</param>
|
|
public static void StopAllInParentCanvas(Canvas canvas, bool restoreOriginal = true)
|
|
{
|
|
GetParentChildren(canvas).ForEach(t => t.Stop(restoreOriginal));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops all enabled tweens of a given type that are in a given canvas.
|
|
/// </summary>
|
|
/// <param name="restoreOriginal">Whether to reset each animated component to the state before its animation started</param>
|
|
/// <param name="canvas">Canvas to disable all enabled tweens from</param>
|
|
/// <typeparam name="T">Type of <see cref="UxrTween" />s to stop</typeparam>
|
|
public static void StopAllInParentCanvas<T>(Canvas canvas, bool restoreOriginal = true) where T : UxrTween
|
|
{
|
|
GetParentChildren(canvas).OfType<T>().ForEach(t => t.Stop(restoreOriginal));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops all the tweening components of a <see cref="Behaviour" />.
|
|
/// </summary>
|
|
/// <param name="behaviour"><see cref="Behaviour" /> whose tweens to stop</param>
|
|
/// <param name="restoreOriginal">Whether to reset each animated component to the state before its animation started</param>
|
|
public static void StopAll(Behaviour behaviour, bool restoreOriginal = true)
|
|
{
|
|
foreach (UxrTween tween in behaviour.gameObject.GetComponents<UxrTween>())
|
|
{
|
|
tween.Stop(restoreOriginal);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops the tweening animation on an object if it has a <typeparamref name="T" /> component currently added.
|
|
/// </summary>
|
|
/// <param name="behaviour">UI Component whose GameObject has the tween added</param>
|
|
/// <param name="restoreOriginal">Whether to reset the animated component to the state before the animation started</param>
|
|
/// <typeparam name="T">Type of <see cref="UxrTween" /> to stop</typeparam>
|
|
public static void Stop<T>(Behaviour behaviour, bool restoreOriginal = true) where T : UxrTween
|
|
{
|
|
T tween = behaviour.GetComponent<T>();
|
|
|
|
if (tween)
|
|
{
|
|
tween.Stop(restoreOriginal);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stops the tweening animation.
|
|
/// </summary>
|
|
/// <param name="restoreOriginal">Whether to reset the animated component to the state before the animation started</param>
|
|
public void Stop(bool restoreOriginal = true)
|
|
{
|
|
HasFinished = true;
|
|
|
|
if (restoreOriginal)
|
|
{
|
|
RestoreOriginalValue();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the actions to perform when the animation finished.
|
|
/// </summary>
|
|
/// <param name="actions">Action flags</param>
|
|
/// <returns>The <see cref="UxrTween" /> component to concatenate additional calls if desired.</returns>
|
|
public UxrTween SetFinishedActions(UxrTweenFinishedActions actions)
|
|
{
|
|
_finishedActions = actions;
|
|
return this;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Unity
|
|
|
|
/// <summary>
|
|
/// Stores the start time each time the component is enabled.
|
|
/// </summary>
|
|
protected override void OnEnable()
|
|
{
|
|
base.OnEnable();
|
|
|
|
_startTime = CurrentTime;
|
|
|
|
if (!HasOriginalValueStored)
|
|
{
|
|
HasOriginalValueStored = true;
|
|
StoreOriginalValue();
|
|
}
|
|
|
|
if (InterpolationSettings != null)
|
|
{
|
|
Interpolate(InterpolationSettings.GetInterpolationFactor(0.0f));
|
|
}
|
|
|
|
HasFinished = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the interpolation.
|
|
/// </summary>
|
|
private void Update()
|
|
{
|
|
if (HasFinished || InterpolationSettings == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Interpolate(InterpolationSettings.GetInterpolationFactor(AnimationTime));
|
|
|
|
if (InterpolationSettings.CheckInterpolationHasFinished(AnimationTime))
|
|
{
|
|
Interpolate(1.0f);
|
|
HasFinished = true;
|
|
OnFinished();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Event Trigger Methods
|
|
|
|
/// <summary>
|
|
/// Event trigger for the <see cref="Finished" /> event.
|
|
/// </summary>
|
|
protected virtual void OnFinished()
|
|
{
|
|
Finished?.Invoke();
|
|
FinishedCallback?.Invoke(this);
|
|
|
|
if (_finishedActions.HasFlag(UxrTweenFinishedActions.RestoreOriginalValue))
|
|
{
|
|
RestoreOriginalValue();
|
|
}
|
|
if (_finishedActions.HasFlag(UxrTweenFinishedActions.DisableTargetComponent) && TargetBehaviour)
|
|
{
|
|
TargetBehaviour.enabled = false;
|
|
}
|
|
if (_finishedActions.HasFlag(UxrTweenFinishedActions.DeactivateGameObject) && TargetBehaviour && TargetBehaviour.gameObject)
|
|
{
|
|
TargetBehaviour.gameObject.SetActive(false);
|
|
}
|
|
if (_finishedActions.HasFlag(UxrTweenFinishedActions.DestroyTween))
|
|
{
|
|
Destroy(this);
|
|
}
|
|
if (_finishedActions.HasFlag(UxrTweenFinishedActions.DestroyTargetComponent) && TargetBehaviour)
|
|
{
|
|
Destroy(TargetBehaviour);
|
|
}
|
|
if (_finishedActions.HasFlag(UxrTweenFinishedActions.DestroyGameObject))
|
|
{
|
|
Destroy(gameObject);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Protected Methods
|
|
|
|
/// <summary>
|
|
/// Restores the animated component to the state before the animation started.
|
|
/// </summary>
|
|
protected abstract void RestoreOriginalValue();
|
|
|
|
/// <summary>
|
|
/// Stores the original value before the animation, in order to be able to restore it later using
|
|
/// <see cref="RestoreOriginalValue" />.
|
|
/// </summary>
|
|
protected abstract void StoreOriginalValue();
|
|
|
|
/// <summary>
|
|
/// Interpolates and assigns the value corresponding to the given LERP value.
|
|
/// </summary>
|
|
/// <param name="t">LERP interpolation t value [0.0, 1.0]</param>
|
|
protected abstract void Interpolate(float t);
|
|
|
|
/// <summary>
|
|
/// Restarts the animation with the current parameters.
|
|
/// It also forces the execution of the first frame.
|
|
/// </summary>
|
|
protected void Restart()
|
|
{
|
|
if (InterpolationSettings != null)
|
|
{
|
|
_startTime = CurrentTime;
|
|
_finishedActions = UxrTweenFinishedActions.None;
|
|
HasFinished = false;
|
|
|
|
Interpolate(InterpolationSettings.GetInterpolationFactor(0.0f));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Protected Types & Data
|
|
|
|
/// <summary>
|
|
/// Gets the <see cref="Behaviour" /> the tween animates.
|
|
/// </summary>
|
|
protected abstract Behaviour TargetBehaviour { get; }
|
|
|
|
/// <summary>
|
|
/// Gets if the tween has gathered the original animated parameter value.
|
|
/// </summary>
|
|
protected bool HasOriginalValueStored { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Optional finished callback assigned by child classes.
|
|
/// </summary>
|
|
protected Action<UxrTween> FinishedCallback { get; set; }
|
|
|
|
#endregion
|
|
|
|
#region Private Types & Data
|
|
|
|
/// <summary>
|
|
/// Gets the current time in seconds. It computes the correct time, either <see cref="Time.unscaledTime" /> or
|
|
/// <see cref="Time.time" />, depending on the animation configuration.
|
|
/// </summary>
|
|
private float CurrentTime
|
|
{
|
|
get
|
|
{
|
|
if (InterpolationSettings != null)
|
|
{
|
|
return InterpolationSettings.UseUnscaledTime ? Time.unscaledTime : Time.time;
|
|
}
|
|
|
|
return Time.time;
|
|
}
|
|
}
|
|
|
|
private float _startTime;
|
|
|
|
#endregion
|
|
}
|
|
} |