using System.Collections.Generic; using SLSUtilities.Feedback; using SLSUtilities.Rendering.PostProcessing; using UnityEngine; namespace Cielonos.MainGame.Effects.Feedback { /// /// 色散震动事件。 /// 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); } } /// /// 色散震动实例。 /// 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; } } /// /// AdvancedChromaticAberration 的震动聚合器。 /// [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; private readonly List _activeShakes = new List(); 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; _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(); } } }