Restructured for new direction.
This commit is contained in:
249
Assets/Scripts/Framework/Effects/UILightGlow.cs
Normal file
249
Assets/Scripts/Framework/Effects/UILightGlow.cs
Normal file
@@ -0,0 +1,249 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using PrimeTween;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BriarQueen.Framework.Effects
|
||||
{
|
||||
[RequireComponent(typeof(Image))]
|
||||
public class UILightGlow : MonoBehaviour
|
||||
{
|
||||
private const string _lightShaderName = "BriarQueen/UI/Light Glow";
|
||||
|
||||
private static readonly int _lightColorId = Shader.PropertyToID("_LightColor");
|
||||
private static readonly int _intensityId = Shader.PropertyToID("_Intensity");
|
||||
private static readonly int _flickerOffsetId = Shader.PropertyToID("_FlickerOffset");
|
||||
|
||||
[Header("References")]
|
||||
[SerializeField]
|
||||
private Image _image;
|
||||
|
||||
[SerializeField]
|
||||
private Material _lightMaterialTemplate;
|
||||
|
||||
[Header("Light")]
|
||||
[SerializeField]
|
||||
private Color _startingColor = new(1f, 0.78f, 0.35f, 1f);
|
||||
|
||||
[SerializeField]
|
||||
private float _startingIntensity = 1.5f;
|
||||
|
||||
[SerializeField]
|
||||
private bool _randomizeFlickerOffset = true;
|
||||
|
||||
[Header("Tween")]
|
||||
[SerializeField]
|
||||
private float _defaultTweenDuration = 0.35f;
|
||||
|
||||
[SerializeField]
|
||||
private Ease _ease = Ease.InOutSine;
|
||||
|
||||
[SerializeField]
|
||||
private bool _useUnscaledTime = true;
|
||||
|
||||
private Material _runtimeMaterial;
|
||||
private Sequence _lightSequence;
|
||||
private CancellationTokenSource _lightCts;
|
||||
|
||||
public Color LightColor
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_runtimeMaterial == null)
|
||||
{
|
||||
return _startingColor;
|
||||
}
|
||||
|
||||
return _runtimeMaterial.GetColor(_lightColorId);
|
||||
}
|
||||
}
|
||||
|
||||
public float Intensity
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_runtimeMaterial == null)
|
||||
{
|
||||
return _startingIntensity;
|
||||
}
|
||||
|
||||
return _runtimeMaterial.GetFloat(_intensityId);
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_image == null)
|
||||
{
|
||||
_image = GetComponent<Image>();
|
||||
}
|
||||
|
||||
CreateRuntimeMaterial();
|
||||
SetLightColor(_startingColor);
|
||||
SetIntensity(_startingIntensity);
|
||||
|
||||
if (_randomizeFlickerOffset && _runtimeMaterial != null)
|
||||
{
|
||||
_runtimeMaterial.SetFloat(_flickerOffsetId, UnityEngine.Random.Range(0f, 100f));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
CancelTween();
|
||||
|
||||
if (_runtimeMaterial != null)
|
||||
{
|
||||
Destroy(_runtimeMaterial);
|
||||
_runtimeMaterial = null;
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask ChangeColor(Color targetColor)
|
||||
{
|
||||
return ChangeColor(targetColor, _defaultTweenDuration);
|
||||
}
|
||||
|
||||
public UniTask ChangeColor(Color targetColor, float duration)
|
||||
{
|
||||
return TweenTo(targetColor, Intensity, duration);
|
||||
}
|
||||
|
||||
public UniTask ChangeIntensity(float targetIntensity)
|
||||
{
|
||||
return ChangeIntensity(targetIntensity, _defaultTweenDuration);
|
||||
}
|
||||
|
||||
public UniTask ChangeIntensity(float targetIntensity, float duration)
|
||||
{
|
||||
return TweenTo(LightColor, targetIntensity, duration);
|
||||
}
|
||||
|
||||
public UniTask TurnOff()
|
||||
{
|
||||
return ChangeIntensity(0f, _defaultTweenDuration);
|
||||
}
|
||||
|
||||
public UniTask TurnOn()
|
||||
{
|
||||
return ChangeIntensity(_startingIntensity, _defaultTweenDuration);
|
||||
}
|
||||
|
||||
public async UniTask TweenTo(Color targetColor, float targetIntensity, float duration)
|
||||
{
|
||||
if (_runtimeMaterial == null)
|
||||
{
|
||||
CreateRuntimeMaterial();
|
||||
}
|
||||
|
||||
CancelTween();
|
||||
|
||||
var fromColor = LightColor;
|
||||
var fromIntensity = Intensity;
|
||||
var safeDuration = Mathf.Max(0f, duration);
|
||||
|
||||
_lightCts = new CancellationTokenSource();
|
||||
|
||||
_lightSequence = Sequence.Create(useUnscaledTime: _useUnscaledTime)
|
||||
.Group(Tween.Custom(
|
||||
0f,
|
||||
1f,
|
||||
safeDuration,
|
||||
progress =>
|
||||
{
|
||||
SetLightColor(Color.LerpUnclamped(fromColor, targetColor, progress));
|
||||
SetIntensity(Mathf.LerpUnclamped(fromIntensity, targetIntensity, progress));
|
||||
},
|
||||
_ease,
|
||||
useUnscaledTime: _useUnscaledTime));
|
||||
|
||||
try
|
||||
{
|
||||
await _lightSequence.ToUniTask(cancellationToken: _lightCts.Token);
|
||||
SetLightColor(targetColor);
|
||||
SetIntensity(targetIntensity);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// Interrupted by another light tween or object destruction.
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lightSequence = default;
|
||||
|
||||
if (_lightCts != null)
|
||||
{
|
||||
_lightCts.Dispose();
|
||||
_lightCts = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLightColor(Color color)
|
||||
{
|
||||
if (_runtimeMaterial == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_runtimeMaterial.SetColor(_lightColorId, color);
|
||||
}
|
||||
|
||||
public void SetIntensity(float intensity)
|
||||
{
|
||||
if (_runtimeMaterial == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_runtimeMaterial.SetFloat(_intensityId, Mathf.Max(0f, intensity));
|
||||
}
|
||||
|
||||
public void CancelTween()
|
||||
{
|
||||
if (_lightSequence.isAlive)
|
||||
{
|
||||
_lightSequence.Stop();
|
||||
_lightSequence = default;
|
||||
}
|
||||
|
||||
if (_lightCts != null)
|
||||
{
|
||||
_lightCts.Cancel();
|
||||
_lightCts.Dispose();
|
||||
_lightCts = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateRuntimeMaterial()
|
||||
{
|
||||
if (_image == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_lightMaterialTemplate != null)
|
||||
{
|
||||
_runtimeMaterial = Instantiate(_lightMaterialTemplate);
|
||||
_image.material = _runtimeMaterial;
|
||||
return;
|
||||
}
|
||||
|
||||
var shader = Shader.Find(_lightShaderName);
|
||||
if (shader == null)
|
||||
{
|
||||
Debug.LogWarning($"[{nameof(UILightGlow)}] Could not find shader '{_lightShaderName}'.");
|
||||
return;
|
||||
}
|
||||
|
||||
_runtimeMaterial = new Material(shader)
|
||||
{
|
||||
name = $"{nameof(UILightGlow)} Runtime Material"
|
||||
};
|
||||
|
||||
_image.material = _runtimeMaterial;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user