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