// --------------------------------------------------------------------------------------------------------------------
//
// Copyright (c) VRMADA, All rights reserved.
//
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using UltimateXR.Core.Components;
using UltimateXR.Extensions.Unity;
using UnityEngine;
namespace UltimateXR.Animation.GameObjects
{
///
/// Component that allows to fade an object out by making the material progressively more transparent.
///
public partial class UxrObjectFade : UxrComponent
{
#region Inspector Properties/Serialized Fields
[SerializeField] private bool _recursively = true;
[SerializeField] private float _delaySeconds;
[SerializeField] private float _duration = 1.0f;
[SerializeField] private float _startQuantity = 1.0f;
[SerializeField] private float _endQuantity;
[SerializeField] private bool _useUnscaledTime;
#endregion
#region Public Methods
///
/// Starts a fade animation.
///
/// GameObject whose material transparency will be enabled and animated.
/// Start alpha
/// End alpha
/// Seconds to wait before the animation starts
/// Fade duration in seconds
/// Whether to also process all other child objects in the hierarchy
///
/// Whether to use unscaled time () or not (
/// )
///
/// Optional callback executed when the animation finished
/// Animation component
public static UxrObjectFade Fade(GameObject gameObject,
float startAlphaQuantity,
float endFadeQuantity,
float delaySeconds,
float durationSeconds,
bool recursively = true,
bool useUnscaledTime = false,
Action finishedCallback = null)
{
UxrObjectFade objectFade = gameObject.GetOrAddComponent();
objectFade._startQuantity = startAlphaQuantity;
objectFade._endQuantity = endFadeQuantity;
objectFade._delaySeconds = delaySeconds;
objectFade._duration = durationSeconds;
objectFade._recursively = recursively;
objectFade._useUnscaledTime = useUnscaledTime;
objectFade._finishedCallback = finishedCallback;
objectFade.CheckInitialize(true);
return objectFade;
}
#endregion
#region Unity
///
/// Initializes the component.
///
protected override void Awake()
{
base.Awake();
CheckInitialize();
}
///
/// Starts or re-starts the animation.
///
protected override void OnEnable()
{
base.OnEnable();
_fadeStartTime = CurrentTime;
_finished = false;
}
///
/// Stops the animation and restores the material.
///
protected override void OnDisable()
{
base.OnDisable();
foreach (ObjectEntry objectEntry in _objects)
{
objectEntry.Restore();
}
}
///
/// Updates the animation.
///
private void Update()
{
if (_finished)
{
return;
}
float fadeTime = CurrentTime - _fadeStartTime - _delaySeconds;
if (fadeTime <= 0)
{
return;
}
float fadeT = Mathf.Clamp01(fadeTime / _duration);
foreach (ObjectEntry entry in _objects)
{
entry.Fade(_startQuantity, _endQuantity, fadeT);
}
if (fadeTime > _duration)
{
_finishedCallback?.Invoke();
_finished = true;
}
}
#endregion
#region Private Methods
///
/// Initializes the component if necessary.
///
/// Forces initializing the component even if it already may have been initialized
private void CheckInitialize(bool forceInitialize = false)
{
if (_objects.Count == 0 || forceInitialize)
{
Renderer[] objectRenderers = _recursively ? gameObject.GetComponentsInChildren() : new[] { gameObject.GetComponent() };
foreach (Renderer renderer in objectRenderers)
{
_objects.Add(new ObjectEntry(renderer));
}
}
}
#endregion
#region Private Types & Data
private float CurrentTime => _useUnscaledTime ? Time.unscaledTime : Time.time;
private readonly List _objects = new List();
private float _fadeStartTime;
private bool _finished;
private Action _finishedCallback;
#endregion
}
}