Files
Cielonos/Assets/Scripts/MainGame/Effects/Feedbacks/Shakers/VignetteShaker.cs
SoulliesOfficial 0902ca8a9e Bezi回来了
2026-04-28 15:46:32 -04:00

319 lines
11 KiB
C#

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,
Vector2CurveChannel centerCurve,
Vector2 center,
bool modifyColors,
ColorCurveChannel colorOuter,
ColorCurveChannel colorInner,
Color outColor,
Color innerColor,
bool modifyShape,
FloatCurveChannel smoothnessCurve,
FloatCurveChannel roundnessCurve,
float smoothness,
float roundness,
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 centerCurve = default,
Vector2 center = default,
bool modifyColors = false,
ColorCurveChannel colorOuter = default,
ColorCurveChannel colorInner = default,
Color outColor = default,
Color innerColor = default,
bool modifyShape = false,
FloatCurveChannel smoothnessCurve = default,
FloatCurveChannel roundnessCurve = default,
float smoothness = 0f,
float roundness = 0f,
bool stop = false)
{
OnEvent?.Invoke(feedbackContext, intensityCurve, modifyCenter, centerCurve, center,
modifyColors, colorOuter, colorInner, outColor, innerColor, modifyShape,
smoothnessCurve, roundnessCurve, smoothness, roundness, stop);
}
}
/// <summary>
/// 暗角震动实例。
/// </summary>
public class VignetteShakeInstance : ShakeInstanceBase
{
public readonly FloatCurveChannel intensityCurve;
public readonly bool modifyCenter;
public readonly Vector2CurveChannel centerCurve;
public readonly Vector2 center;
public readonly bool modifyColors;
public readonly ColorCurveChannel colorOuter;
public readonly ColorCurveChannel colorInner;
public readonly Color outColor;
public readonly Color innerColor;
public readonly bool modifyShape;
public readonly FloatCurveChannel smoothnessCurve;
public readonly FloatCurveChannel roundnessCurve;
public readonly float smoothness;
public readonly float roundness;
public VignetteShakeInstance(
FeedbackContext feedbackContext,
FloatCurveChannel intensityCurve,
bool modifyCenter,
Vector2CurveChannel centerCurve,
Vector2 center,
bool modifyColors,
ColorCurveChannel colorOuter,
ColorCurveChannel colorInner,
Color outColor,
Color innerColor,
bool modifyShape,
FloatCurveChannel smoothnessCurve,
FloatCurveChannel roundnessCurve,
float smoothness,
float roundness)
: base(feedbackContext.timeSettings, feedbackContext.player.TimeProvider, feedbackContext.duration)
{
this.intensityCurve = intensityCurve;
this.modifyCenter = modifyCenter;
this.centerCurve = centerCurve;
this.center = center;
this.modifyColors = modifyColors;
this.colorOuter = colorOuter;
this.colorInner = colorInner;
this.outColor = outColor;
this.innerColor = innerColor;
this.modifyShape = modifyShape;
this.smoothnessCurve = smoothnessCurve;
this.roundnessCurve = roundnessCurve;
this.smoothness = smoothness;
this.roundness = roundness;
}
}
/// <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;
float curveValue = shake.intensityCurve.Evaluate(normalizedTime);
if (shake.intensityCurve.relativeToInitial)
{
additiveIntensity += curveValue;
}
else
{
absoluteIntensity = curveValue;
hasAbsolute = true;
}
if (shake.modifyCenter)
{
latestCenter = shake.modifyCenter
? shake.centerCurve.Evaluate(normalizedTime, _initialCenter)
: shake.center;
hasCenter = true;
}
if (shake.modifyColors)
{
latestColorOuter = shake.modifyColors
? shake.colorOuter.Evaluate(normalizedTime)
: shake.outColor;
latestColorInner = shake.modifyColors
? shake.colorInner.Evaluate(normalizedTime)
: shake.innerColor;
hasColors = true;
}
if (shake.modifyShape)
{
latestSmoothness = shake.modifyShape
? shake.smoothnessCurve.Evaluate(normalizedTime)
: shake.smoothness;
latestRoundness = shake.modifyShape
? shake.roundnessCurve.Evaluate(normalizedTime)
: shake.roundness;
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,
Vector2CurveChannel centerCurve,
Vector2 center,
bool modifyColors,
ColorCurveChannel colorOuter,
ColorCurveChannel colorInner,
Color outColor,
Color innerColor,
bool modifyShape,
FloatCurveChannel smoothnessCurve,
FloatCurveChannel roundnessCurve,
float smoothness,
float roundness,
bool stop)
{
if (stop) { StopAll(); return; }
if (!_resolved) _resolved = TryResolve();
if (!_resolved) return;
var instance = new VignetteShakeInstance(
feedbackContext,
intensityCurve,
modifyCenter,
centerCurve,
center,
modifyColors,
colorOuter,
colorInner,
outColor,
innerColor,
modifyShape,
smoothnessCurve,
roundnessCurve,
smoothness,
roundness
);
_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();
}
}
}