186 lines
5.9 KiB
C#
186 lines
5.9 KiB
C#
using System.Collections.Generic;
|
|
using SLSUtilities.Feedback;
|
|
using SLSUtilities.Rendering.PostProcessing;
|
|
using UnityEngine;
|
|
|
|
namespace Cielonos.MainGame.Effects.Feedback
|
|
{
|
|
/// <summary>
|
|
/// RGB分离故障震动事件。
|
|
/// </summary>
|
|
public struct RGBSplitGlitchShakeEvent
|
|
{
|
|
private static event ShakeDelegate OnEvent;
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
|
private static void RuntimeInitialization() { OnEvent = null; }
|
|
|
|
public delegate void ShakeDelegate(
|
|
FeedbackContext feedbackContext,
|
|
FloatCurveChannel intensityCurve,
|
|
FloatCurveChannel speedCurve,
|
|
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,
|
|
FloatCurveChannel speedCurve = default,
|
|
bool stop = false)
|
|
{
|
|
OnEvent?.Invoke(feedbackContext, intensityCurve, speedCurve, stop);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// RGB分离故障震动实例。
|
|
/// </summary>
|
|
public class RGBSplitGlitchShakeInstance : ShakeInstanceBase
|
|
{
|
|
public readonly FloatCurveChannel intensityCurve;
|
|
public readonly FloatCurveChannel speedCurve;
|
|
|
|
public RGBSplitGlitchShakeInstance(
|
|
FeedbackContext feedbackContext,
|
|
FloatCurveChannel intensityCurve,
|
|
FloatCurveChannel speedCurve)
|
|
: base(feedbackContext.timeSettings, feedbackContext.player.TimeProvider, feedbackContext.duration)
|
|
{
|
|
this.intensityCurve = intensityCurve;
|
|
this.speedCurve = speedCurve;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// RGBSplitGlitch 的震动聚合器。
|
|
/// </summary>
|
|
[AddComponentMenu("SLS Utilities/Feedback Shakers/RGB Split Glitch Shaker")]
|
|
public class RGBSplitGlitchShaker : MonoBehaviour
|
|
{
|
|
private RGBSplitGlitch _component;
|
|
private float _initialIntensity;
|
|
private float _initialSpeed;
|
|
private bool _resolved;
|
|
|
|
private readonly List<RGBSplitGlitchShakeInstance> _activeShakes = new List<RGBSplitGlitchShakeInstance>();
|
|
|
|
private void Awake()
|
|
{
|
|
_resolved = TryResolve();
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
RGBSplitGlitchShakeEvent.Register(OnShakeEvent);
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
RGBSplitGlitchShakeEvent.Unregister(OnShakeEvent);
|
|
StopAll();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!_resolved || _activeShakes.Count == 0) return;
|
|
|
|
float additiveIntensity = 0f;
|
|
float absoluteIntensity = 0f;
|
|
bool hasAbsoluteIntensity = false;
|
|
float additiveSpeed = 0f;
|
|
float absoluteSpeed = 0f;
|
|
bool hasAbsoluteSpeed = false;
|
|
|
|
for (int i = _activeShakes.Count - 1; i >= 0; i--)
|
|
{
|
|
RGBSplitGlitchShakeInstance shake = _activeShakes[i];
|
|
shake.timer += shake.timeProvider.GetDeltaTime(shake.timeSettings);
|
|
|
|
float normalizedTime = shake.timer / shake.duration;
|
|
|
|
float intensityValue = shake.intensityCurve.Evaluate(normalizedTime);
|
|
if (shake.intensityCurve.relativeToInitial)
|
|
{
|
|
additiveIntensity += intensityValue;
|
|
}
|
|
else
|
|
{
|
|
absoluteIntensity = intensityValue;
|
|
hasAbsoluteIntensity = true;
|
|
}
|
|
|
|
float speedValue = shake.speedCurve.Evaluate(normalizedTime);
|
|
if (shake.speedCurve.relativeToInitial)
|
|
{
|
|
additiveSpeed += speedValue;
|
|
}
|
|
else
|
|
{
|
|
absoluteSpeed = speedValue;
|
|
hasAbsoluteSpeed = true;
|
|
}
|
|
|
|
if (shake.IsFinished)
|
|
{
|
|
_activeShakes.RemoveAt(i);
|
|
}
|
|
}
|
|
|
|
float finalIntensity = hasAbsoluteIntensity ? absoluteIntensity : _initialIntensity + additiveIntensity;
|
|
float finalSpeed = hasAbsoluteSpeed ? absoluteSpeed : _initialSpeed + additiveSpeed;
|
|
_component.intensity.value = finalIntensity;
|
|
_component.speed.value = finalSpeed;
|
|
|
|
if (_activeShakes.Count == 0)
|
|
{
|
|
Restore();
|
|
}
|
|
}
|
|
|
|
private void OnShakeEvent(
|
|
FeedbackContext feedbackContext,
|
|
FloatCurveChannel intensityCurve,
|
|
FloatCurveChannel speedCurve,
|
|
bool stop)
|
|
{
|
|
if (stop) { StopAll(); return; }
|
|
if (!_resolved) _resolved = TryResolve();
|
|
if (!_resolved) return;
|
|
|
|
var instance = new RGBSplitGlitchShakeInstance(
|
|
feedbackContext,
|
|
intensityCurve,
|
|
speedCurve
|
|
);
|
|
_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;
|
|
_initialSpeed = _component.speed.value;
|
|
return true;
|
|
}
|
|
|
|
private void Restore()
|
|
{
|
|
if (!_resolved) return;
|
|
_component.intensity.value = _initialIntensity;
|
|
_component.speed.value = _initialSpeed;
|
|
}
|
|
|
|
private void StopAll()
|
|
{
|
|
_activeShakes.Clear();
|
|
Restore();
|
|
}
|
|
}
|
|
}
|