Files
Cielonos/Assets/Scripts/MainGame/Effects/Feedbacks/Shakers/VignetteShaker.cs

319 lines
11 KiB
C#
Raw Normal View History

2026-04-18 13:57:19 -04:00
using System.Collections.Generic;
using SLSUtilities.Feedback;
using SLSUtilities.Rendering.PostProcessing;
using UnityEngine;
namespace Cielonos.MainGame.Effects.Feedback
{
/// <summary>
/// 暗角震动事件。
/// </summary>
public struct VignetteShakeEvent
{
private static event ShakeDelegate OnEvent;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void RuntimeInitialization() { OnEvent = null; }
public delegate void ShakeDelegate(
FeedbackContext feedbackContext,
FloatCurveChannel intensityCurve,
bool modifyCenter,
2026-04-28 15:46:32 -04:00
Vector2CurveChannel centerCurve,
2026-04-18 13:57:19 -04:00
Vector2 center,
bool modifyColors,
ColorCurveChannel colorOuter,
ColorCurveChannel colorInner,
2026-04-28 15:46:32 -04:00
Color outColor,
Color innerColor,
2026-04-18 13:57:19 -04:00
bool modifyShape,
FloatCurveChannel smoothnessCurve,
FloatCurveChannel roundnessCurve,
2026-04-28 15:46:32 -04:00
float smoothness,
float roundness,
2026-04-18 13:57:19 -04:00
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,
2026-04-28 15:46:32 -04:00
Vector2CurveChannel centerCurve = default,
2026-04-18 13:57:19 -04:00
Vector2 center = default,
bool modifyColors = false,
ColorCurveChannel colorOuter = default,
ColorCurveChannel colorInner = default,
2026-04-28 15:46:32 -04:00
Color outColor = default,
Color innerColor = default,
2026-04-18 13:57:19 -04:00
bool modifyShape = false,
FloatCurveChannel smoothnessCurve = default,
FloatCurveChannel roundnessCurve = default,
2026-04-28 15:46:32 -04:00
float smoothness = 0f,
float roundness = 0f,
2026-04-18 13:57:19 -04:00
bool stop = false)
{
2026-04-28 15:46:32 -04:00
OnEvent?.Invoke(feedbackContext, intensityCurve, modifyCenter, centerCurve, center,
modifyColors, colorOuter, colorInner, outColor, innerColor, modifyShape,
smoothnessCurve, roundnessCurve, smoothness, roundness, stop);
2026-04-18 13:57:19 -04:00
}
}
/// <summary>
/// 暗角震动实例。
/// </summary>
public class VignetteShakeInstance : ShakeInstanceBase
{
public readonly FloatCurveChannel intensityCurve;
public readonly bool modifyCenter;
2026-04-28 15:46:32 -04:00
public readonly Vector2CurveChannel centerCurve;
2026-04-18 13:57:19 -04:00
public readonly Vector2 center;
public readonly bool modifyColors;
public readonly ColorCurveChannel colorOuter;
public readonly ColorCurveChannel colorInner;
2026-04-28 15:46:32 -04:00
public readonly Color outColor;
public readonly Color innerColor;
2026-04-18 13:57:19 -04:00
public readonly bool modifyShape;
public readonly FloatCurveChannel smoothnessCurve;
public readonly FloatCurveChannel roundnessCurve;
2026-04-28 15:46:32 -04:00
public readonly float smoothness;
public readonly float roundness;
2026-04-18 13:57:19 -04:00
public VignetteShakeInstance(
FeedbackContext feedbackContext,
FloatCurveChannel intensityCurve,
bool modifyCenter,
2026-04-28 15:46:32 -04:00
Vector2CurveChannel centerCurve,
2026-04-18 13:57:19 -04:00
Vector2 center,
bool modifyColors,
ColorCurveChannel colorOuter,
ColorCurveChannel colorInner,
2026-04-28 15:46:32 -04:00
Color outColor,
Color innerColor,
2026-04-18 13:57:19 -04:00
bool modifyShape,
FloatCurveChannel smoothnessCurve,
2026-04-28 15:46:32 -04:00
FloatCurveChannel roundnessCurve,
float smoothness,
float roundness)
2026-04-18 13:57:19 -04:00
: base(feedbackContext.timeSettings, feedbackContext.player.TimeProvider, feedbackContext.duration)
{
this.intensityCurve = intensityCurve;
this.modifyCenter = modifyCenter;
2026-04-28 15:46:32 -04:00
this.centerCurve = centerCurve;
2026-04-18 13:57:19 -04:00
this.center = center;
this.modifyColors = modifyColors;
this.colorOuter = colorOuter;
this.colorInner = colorInner;
2026-04-28 15:46:32 -04:00
this.outColor = outColor;
this.innerColor = innerColor;
2026-04-18 13:57:19 -04:00
this.modifyShape = modifyShape;
this.smoothnessCurve = smoothnessCurve;
this.roundnessCurve = roundnessCurve;
2026-04-28 15:46:32 -04:00
this.smoothness = smoothness;
this.roundness = roundness;
2026-04-18 13:57:19 -04:00
}
}
/// <summary>
/// AdvancedVignette 的震动聚合器。
/// </summary>
[AddComponentMenu("SLS Utilities/Feedback Shakers/Vignette Shaker")]
public class VignetteShaker : MonoBehaviour
{
private AdvancedVignette _component;
private float _initialIntensity;
private Vector2 _initialCenter;
private Color _initialColorOuter;
private Color _initialColorInner;
private float _initialSmoothness;
private float _initialRoundness;
private bool _resolved;
private readonly List<VignetteShakeInstance> _activeShakes = new List<VignetteShakeInstance>();
private void Awake()
{
_resolved = TryResolve();
}
private void OnEnable()
{
VignetteShakeEvent.Register(OnShakeEvent);
}
private void OnDisable()
{
VignetteShakeEvent.Unregister(OnShakeEvent);
StopAll();
}
private void Update()
{
if (!_resolved || _activeShakes.Count == 0) return;
float additiveIntensity = 0f;
float absoluteIntensity = 0f;
bool hasAbsolute = false;
Vector2 latestCenter = _initialCenter;
Color latestColorOuter = _initialColorOuter;
Color latestColorInner = _initialColorInner;
float latestSmoothness = _initialSmoothness;
float latestRoundness = _initialRoundness;
bool hasCenter = false;
bool hasColors = false;
bool hasShape = false;
for (int i = _activeShakes.Count - 1; i >= 0; i--)
{
VignetteShakeInstance shake = _activeShakes[i];
shake.timer += shake.timeProvider.GetDeltaTime(shake.timeSettings);
float normalizedTime = shake.timer / shake.duration;
2026-04-28 15:46:32 -04:00
float curveValue = shake.intensityCurve.Evaluate(normalizedTime);
if (shake.intensityCurve.relativeToInitial)
{
additiveIntensity += curveValue;
}
else
2026-04-18 13:57:19 -04:00
{
2026-04-28 15:46:32 -04:00
absoluteIntensity = curveValue;
hasAbsolute = true;
2026-04-18 13:57:19 -04:00
}
if (shake.modifyCenter)
{
2026-04-28 15:46:32 -04:00
latestCenter = shake.modifyCenter
? shake.centerCurve.Evaluate(normalizedTime, _initialCenter)
: shake.center;
2026-04-18 13:57:19 -04:00
hasCenter = true;
}
if (shake.modifyColors)
{
2026-04-28 15:46:32 -04:00
latestColorOuter = shake.modifyColors
? shake.colorOuter.Evaluate(normalizedTime)
: shake.outColor;
latestColorInner = shake.modifyColors
? shake.colorInner.Evaluate(normalizedTime)
: shake.innerColor;
2026-04-18 13:57:19 -04:00
hasColors = true;
}
if (shake.modifyShape)
{
2026-04-28 15:46:32 -04:00
latestSmoothness = shake.modifyShape
? shake.smoothnessCurve.Evaluate(normalizedTime)
: shake.smoothness;
latestRoundness = shake.modifyShape
? shake.roundnessCurve.Evaluate(normalizedTime)
: shake.roundness;
2026-04-18 13:57:19 -04:00
hasShape = true;
}
if (shake.IsFinished)
{
_activeShakes.RemoveAt(i);
}
}
float finalIntensity = hasAbsolute ? absoluteIntensity : _initialIntensity + additiveIntensity;
_component.intensity.value = finalIntensity;
if (hasCenter) _component.center.value = latestCenter;
if (hasColors)
{
_component.colorOuter.value = latestColorOuter;
_component.colorInner.value = latestColorInner;
}
if (hasShape)
{
_component.smoothness.value = latestSmoothness;
_component.roundness.value = latestRoundness;
}
if (_activeShakes.Count == 0)
{
Restore();
}
}
private void OnShakeEvent(
FeedbackContext feedbackContext,
FloatCurveChannel intensityCurve,
bool modifyCenter,
2026-04-28 15:46:32 -04:00
Vector2CurveChannel centerCurve,
2026-04-18 13:57:19 -04:00
Vector2 center,
bool modifyColors,
ColorCurveChannel colorOuter,
ColorCurveChannel colorInner,
2026-04-28 15:46:32 -04:00
Color outColor,
Color innerColor,
2026-04-18 13:57:19 -04:00
bool modifyShape,
FloatCurveChannel smoothnessCurve,
FloatCurveChannel roundnessCurve,
2026-04-28 15:46:32 -04:00
float smoothness,
float roundness,
2026-04-18 13:57:19 -04:00
bool stop)
{
if (stop) { StopAll(); return; }
if (!_resolved) _resolved = TryResolve();
if (!_resolved) return;
var instance = new VignetteShakeInstance(
2026-04-28 15:46:32 -04:00
feedbackContext,
intensityCurve,
modifyCenter,
centerCurve,
center,
modifyColors,
colorOuter,
colorInner,
outColor,
innerColor,
modifyShape,
smoothnessCurve,
roundnessCurve,
smoothness,
roundness
2026-04-18 13:57:19 -04:00
);
_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;
_initialColorOuter = _component.colorOuter.value;
_initialColorInner = _component.colorInner.value;
_initialSmoothness = _component.smoothness.value;
_initialRoundness = _component.roundness.value;
return true;
}
private void Restore()
{
if (!_resolved) return;
_component.intensity.value = _initialIntensity;
_component.center.value = _initialCenter;
_component.colorOuter.value = _initialColorOuter;
_component.colorInner.value = _initialColorInner;
_component.smoothness.value = _initialSmoothness;
_component.roundness.value = _initialRoundness;
}
private void StopAll()
{
_activeShakes.Clear();
Restore();
}
}
}