Files
Cielonos/Assets/Scripts/MainGame/Effects/Feedbacks/Shakers/ChromaticAberrationShaker.cs
SoulliesOfficial 9a9e48f8a5
2026-06-27 12:52:03 -04:00

213 lines
7.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections.Generic;
using SLSUtilities.Feedback;
using SLSUtilities.Rendering.PostProcessing;
using UnityEngine;
namespace Cielonos.MainGame.Effects.Feedback
{
/// <summary>
/// 色散震动事件。
/// </summary>
public struct ChromaticAberrationShakeEvent
{
private static event ShakeDelegate OnEvent;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void RuntimeInitialization() { OnEvent = null; }
public delegate void ShakeDelegate(
FeedbackContext feedbackContext,
FloatCurveChannel intensityCurve,
bool modifyCenter,
Vector2CurveChannel center,
bool modifyJitter,
FloatCurveChannel jitterCurve,
bool stop
);
public static void Register(ShakeDelegate callback) { OnEvent += callback; }
public static void Unregister(ShakeDelegate callback) { OnEvent -= callback; }
public static void Trigger(
FeedbackContext feedbackContext,
FloatCurveChannel intensityCurve,
bool modifyCenter = false,
Vector2CurveChannel center = default,
bool modifyJitter = false,
FloatCurveChannel jitterCurve = default,
bool stop = false)
{
OnEvent?.Invoke(feedbackContext, intensityCurve, modifyCenter, center, modifyJitter, jitterCurve, stop);
}
}
/// <summary>
/// 色散震动实例。
/// </summary>
public class ChromaticAberrationShakeInstance : ShakeInstanceBase
{
public readonly FloatCurveChannel intensityCurve;
public readonly bool modifyCenter;
public readonly Vector2CurveChannel center;
public readonly bool modifyJitter;
public readonly FloatCurveChannel jitterCurve;
public ChromaticAberrationShakeInstance(
FeedbackContext feedbackContext,
FloatCurveChannel intensityCurve,
bool modifyCenter,
Vector2CurveChannel center,
bool modifyJitter,
FloatCurveChannel jitterCurve)
: base(feedbackContext.timeSettings, feedbackContext.player.TimeProvider, feedbackContext.duration)
{
this.intensityCurve = intensityCurve;
this.modifyCenter = modifyCenter;
this.center = center;
this.modifyJitter = modifyJitter;
this.jitterCurve = jitterCurve;
}
}
/// <summary>
/// AdvancedChromaticAberration 的震动聚合器。
/// </summary>
[AddComponentMenu("SLS Utilities/Feedback Shakers/Chromatic Aberration Shaker")]
public class ChromaticAberrationShaker : MonoBehaviour
{
private AdvancedChromaticAberration _component;
private float _initialIntensity;
private Vector2 _initialCenter;
private float _initialJitter;
private bool _resolved;
[Tooltip("色散强度的下限")]
public float minIntensity = 0f;
[Tooltip("色散强度的上限Unity默认最高为1")]
public float maxIntensity = 1f;
private readonly List<ChromaticAberrationShakeInstance> _activeShakes = new List<ChromaticAberrationShakeInstance>();
private void Awake()
{
_resolved = TryResolve();
}
private void OnEnable()
{
ChromaticAberrationShakeEvent.Register(OnShakeEvent);
}
private void OnDisable()
{
ChromaticAberrationShakeEvent.Unregister(OnShakeEvent);
StopAll();
}
private void Update()
{
if (!_resolved || _activeShakes.Count == 0) return;
float additiveIntensity = 0f;
float absoluteIntensity = 0f;
bool hasAbsolute = false;
float additiveJitter = 0f;
Vector2 latestCenter = _initialCenter;
bool hasCenter = false;
for (int i = _activeShakes.Count - 1; i >= 0; i--)
{
ChromaticAberrationShakeInstance shake = _activeShakes[i];
shake.timer += shake.timeProvider.GetDeltaTime(shake.timeSettings);
float normalizedTime = shake.timer / shake.duration;
float curveValue = shake.intensityCurve.Evaluate(normalizedTime);
if (shake.intensityCurve.relativeToInitial)
{
additiveIntensity += curveValue;
}
else
{
absoluteIntensity = curveValue;
hasAbsolute = true;
}
if (shake.modifyJitter)
{
additiveJitter += shake.jitterCurve.Evaluate(normalizedTime);
}
if (shake.modifyCenter)
{
latestCenter = shake.center.Evaluate(normalizedTime, _initialCenter);
hasCenter = true;
}
if (shake.IsFinished)
{
_activeShakes.RemoveAt(i);
}
}
float finalIntensity = hasAbsolute ? absoluteIntensity : _initialIntensity + additiveIntensity;
finalIntensity = Mathf.Clamp(finalIntensity, minIntensity, maxIntensity);
_component.intensity.value = finalIntensity;
_component.jitterIntensity.value = _initialJitter + additiveJitter;
if (hasCenter) _component.center.value = latestCenter;
if (_activeShakes.Count == 0)
{
Restore();
}
}
private void OnShakeEvent(
FeedbackContext feedbackContext,
FloatCurveChannel intensityCurve,
bool modifyCenter,
Vector2CurveChannel center,
bool modifyJitter,
FloatCurveChannel jitterCurve,
bool stop)
{
if (stop) { StopAll(); return; }
if (!_resolved) _resolved = TryResolve();
if (!_resolved) return;
var instance = new ChromaticAberrationShakeInstance(
feedbackContext, intensityCurve, modifyCenter, center, modifyJitter, jitterCurve
);
_activeShakes.Add(instance);
}
private bool TryResolve()
{
if (_component != null) return true;
if (PostProcessingManager.Instance == null) return false;
if (!PostProcessingManager.Instance.GetVolumeComponent(out _component)) return false;
_initialIntensity = _component.intensity.value;
_initialCenter = _component.center.value;
_initialJitter = _component.jitterIntensity.value;
return true;
}
private void Restore()
{
if (!_resolved) return;
_component.intensity.value = _initialIntensity;
_component.center.value = _initialCenter;
_component.jitterIntensity.value = _initialJitter;
}
private void StopAll()
{
_activeShakes.Clear();
Restore();
}
}
}