Bezi回来了

This commit is contained in:
SoulliesOfficial
2026-04-28 15:46:32 -04:00
parent 7379583165
commit 0902ca8a9e
56 changed files with 3285 additions and 3803 deletions

View File

@@ -12,29 +12,21 @@ namespace Cielonos.MainGame.Effects.Feedback
[Serializable]
public struct FloatCurveChannel
{
/// <summary>
/// 是否启用此通道。
/// </summary>
public bool active;
/// <summary>
/// 震动曲线X轴为归一化时间[0,1]Y轴为强度[0,1]。
/// </summary>
[ShowIf("active")]
[ShakeCurvePreset]
public AnimationCurve curve;
/// <summary>
/// 曲线值0对应的实际数值。
/// </summary>
[ShowIf("active")]
[LabelText("Remap Min")]
public float remapMin;
/// <summary>
/// 曲线值1对应的实际数值。
/// </summary>
[ShowIf("active")]
[LabelText("Remap Max")]
public float remapMax;
@@ -47,11 +39,10 @@ namespace Cielonos.MainGame.Effects.Feedback
/// <summary>
/// 创建默认的曲线通道。
/// </summary>
public static FloatCurveChannel CreateDefault(bool active = true, float remapMin = 0f, float remapMax = 1f, bool relativeToInitial = true)
public static FloatCurveChannel CreateDefault(float remapMin = 0f, float remapMax = 1f, bool relativeToInitial = true)
{
return new FloatCurveChannel
{
active = active,
curve = new AnimationCurve(
new Keyframe(0f, 0f),
new Keyframe(0.5f, 1f),
@@ -68,7 +59,7 @@ namespace Cielonos.MainGame.Effects.Feedback
/// </summary>
public readonly float Evaluate(float normalizedTime)
{
if (!active || curve == null) return 0f;
if (curve == null) return 0f;
float t = Mathf.Clamp01(normalizedTime);
float curveValue = curve.Evaluate(t);
return Mathf.LerpUnclamped(remapMin, remapMax, curveValue);
@@ -81,15 +72,9 @@ namespace Cielonos.MainGame.Effects.Feedback
[Serializable]
public struct ColorCurveChannel
{
/// <summary>
/// 是否启用此通道。
/// </summary>
public bool active;
/// <summary>
/// 颜色渐变。
/// </summary>
[ShowIf("active")]
[LabelText("颜色渐变")]
public Gradient gradient;
@@ -100,7 +85,6 @@ namespace Cielonos.MainGame.Effects.Feedback
{
return new ColorCurveChannel
{
active = true,
gradient = new Gradient()
};
}
@@ -110,7 +94,7 @@ namespace Cielonos.MainGame.Effects.Feedback
/// </summary>
public Color Evaluate(float normalizedTime)
{
if (!active || gradient == null) return Color.white;
if (gradient == null) return Color.white;
return gradient.Evaluate(Mathf.Clamp01(normalizedTime));
}
}
@@ -121,23 +105,17 @@ namespace Cielonos.MainGame.Effects.Feedback
[Serializable]
public struct Vector2CurveChannel
{
public bool active;
[ShowIf("active")]
[LabelText("曲线 X")]
[ShakeCurvePreset]
public AnimationCurve curveX;
[ShowIf("active")]
[LabelText("曲线 Y")]
[ShakeCurvePreset]
public AnimationCurve curveY;
[ShowIf("active")]
[LabelText("Remap Min")]
public Vector2 remapMin;
[ShowIf("active")]
[LabelText("Remap Max")]
public Vector2 remapMax;
@@ -153,7 +131,6 @@ namespace Cielonos.MainGame.Effects.Feedback
{
return new Vector2CurveChannel
{
active = true,
curveX = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f)),
curveY = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f)),
remapMin = Vector2.zero,
@@ -164,9 +141,8 @@ namespace Cielonos.MainGame.Effects.Feedback
/// <summary>
/// 根据归一化时间计算Vector2值。
/// </summary>
public Vector2 Evaluate(float normalizedTime, Vector2 initialValue)
public readonly Vector2 Evaluate(float normalizedTime, Vector2 initialValue)
{
if (!active) return Vector2.zero;
float t = Mathf.Clamp01(normalizedTime);
float x = curveX?.Evaluate(t) ?? 0f;
float y = curveY?.Evaluate(t) ?? 0f;

View File

@@ -39,26 +39,19 @@ namespace Cielonos.MainGame.Effects.Feedback
/// 将给定的本地空间向量根据当前设置转换到世界空间。
/// 如果两个方向都开启,角色方向优先。
/// </summary>
/// <param name="localAmplitude">本地空间的振幅向量</param>
/// <param name="standardScreenVector">在摄像机和角色相同朝向时,屏幕空间的振幅向量</param>
/// <param name="ownerTransform">角色 Transform可能为 null</param>
/// <returns>经方向变换后的振幅向量</returns>
public Vector3 TransformAmplitude(Vector3 localAmplitude, Transform ownerTransform)
public Vector3 TransformAmplitude(Vector3 standardScreenVector, Transform ownerTransform)
{
if (affectedByCharacterDirection && ownerTransform != null)
{
return ownerTransform.TransformDirection(localAmplitude);
}
Camera mainCamera = MainGameManager.Instance?.player?.viewSc?.playerCamera;
if (mainCamera == null) return standardScreenVector;
if (affectedByCameraDirection)
{
Camera mainCamera = MainGameManager.Instance.player.viewSc.playerCamera;
if (mainCamera != null)
{
return mainCamera.transform.TransformDirection(localAmplitude);
}
}
Quaternion characterRotation = ownerTransform?.rotation ?? Quaternion.identity;
Quaternion cameraRotation = mainCamera.transform.rotation;
return localAmplitude;
Quaternion deltaRotation = Quaternion.Inverse(cameraRotation) * characterRotation;
return deltaRotation * standardScreenVector;
}
}
}

View File

@@ -16,7 +16,7 @@ namespace Cielonos.MainGame.Effects.Feedback
[TitleGroup("FOV设置")]
[LabelText("FOV曲线")]
public FloatCurveChannel fovCurve = FloatCurveChannel.CreateDefault(remapMax: 10f);
public FloatCurveChannel fovCurve = FloatCurveChannel.CreateDefault();
protected override void TriggerEvent(FeedbackContext context)
{
@@ -30,11 +30,6 @@ namespace Cielonos.MainGame.Effects.Feedback
public override bool Validate(out string error)
{
if (!fovCurve.active)
{
error = "FOV curve is not enabled.";
return false;
}
error = null;
return true;
}

View File

@@ -44,7 +44,7 @@ namespace Cielonos.MainGame.Effects.Feedback
{
Vector3 finalAmplitude = directionSettings.TransformAmplitude(amplitude, context.owner);
float intensityMultiplier = ComputeAttenuation(context);
CameraRotationShakeEvent.Trigger(context, intensityCurve, finalAmplitude * intensityMultiplier);
CameraPositionShakeEvent.Trigger(context, intensityCurve, finalAmplitude * intensityMultiplier);
}
protected override void StopEvent(FeedbackContext context)
@@ -66,11 +66,6 @@ namespace Cielonos.MainGame.Effects.Feedback
public override bool Validate(out string error)
{
if (!intensityCurve.active)
{
error = "Intensity curve is not enabled.";
return false;
}
error = null;
return true;
}

View File

@@ -17,8 +17,7 @@ namespace Cielonos.MainGame.Effects.Feedback
public Vector3 amplitude;
[LabelText("X轴曲线")]
public FloatCurveChannel intensityCurve = FloatCurveChannel.CreateDefault(remapMax: 5f);
public FloatCurveChannel intensityCurve = FloatCurveChannel.CreateDefault();
public CameraDirectionSettings directionSettings = new CameraDirectionSettings();
@@ -40,8 +39,8 @@ namespace Cielonos.MainGame.Effects.Feedback
protected override void TriggerEvent(FeedbackContext context)
{
Vector3 finalAmplitude = directionSettings.TransformAmplitude(amplitude, context.owner);
float intensityMultiplier = ComputeAttenuation(context);
CameraRotationShakeEvent.Trigger(context, intensityCurve, finalAmplitude * intensityMultiplier);
float attenuation = ComputeAttenuation(context);
CameraRotationShakeEvent.Trigger(context, intensityCurve, finalAmplitude * attenuation);
}
protected override void StopEvent(FeedbackContext context)

View File

@@ -58,11 +58,11 @@ namespace Cielonos.MainGame.Effects.Feedback
{
AnimeACESShakeEvent.Trigger(
context,
exposureChannel,
contrastChannel,
saturationChannel,
hueChannel,
colorFilterChannel
modifyExposure, exposureChannel,
modifyContrast, contrastChannel,
modifySaturation, saturationChannel,
modifyHue, hueChannel,
modifyColorFilter, colorFilterChannel
);
}

View File

@@ -3,8 +3,16 @@ using UnityEngine;
namespace Cielonos.MainGame.Effects.Feedback
{
public class BloomAction : CurveShakeAction
public class BloomAction : PostprocessingActionBase
{
protected override void TriggerEvent(FeedbackContext context)
{
throw new System.NotImplementedException();
}
protected override void StopEvent(FeedbackContext context)
{
throw new System.NotImplementedException();
}
}
}

View File

@@ -0,0 +1,60 @@
using System;
using Sirenix.OdinInspector;
using SLSUtilities.Feedback;
using UnityEngine;
namespace Cielonos.MainGame.Effects.Feedback
{
/// <summary>
/// RGB分离故障反馈动作通过 RGBSplitGlitchShakeEvent 触发 RGBSplitGlitchShaker。
/// </summary>
[Serializable]
[FeedbackActionColor(1f, 0.3f, 0.8f)]
public class RGBSplitGlitchAction : PostprocessingActionBase
{
public override string DisplayName => "RGB Split Glitch";
[LabelText("强度曲线")]
public FloatCurveChannel intensityCurve = FloatCurveChannel.CreateDefault(remapMax: 1f);
[LabelText("修改速度")]
public bool modifySpeed;
[ShowIf("modifySpeed")]
[LabelText("速度曲线")]
public FloatCurveChannel speedCurve = FloatCurveChannel.CreateDefault(remapMax: 50f);
[HideIf("modifySpeed")]
[LabelText("速度")]
[Range(0f, 100f)]
public float speed = 30f;
protected override void TriggerEvent(FeedbackContext context)
{
FloatCurveChannel finalSpeedCurve = modifySpeed
? speedCurve
: new FloatCurveChannel
{
curve = AnimationCurve.Constant(0f, 1f, speed),
relativeToInitial = false
};
RGBSplitGlitchShakeEvent.Trigger(
context,
intensityCurve,
finalSpeedCurve
);
}
protected override void StopEvent(FeedbackContext context)
{
RGBSplitGlitchShakeEvent.Trigger(context, intensityCurve, stop: true);
}
public override bool Validate(out string error)
{
error = null;
return true;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: dc20b82d80b720247a0ef6db8513af02

View File

@@ -14,73 +14,53 @@ namespace Cielonos.MainGame.Effects.Feedback
{
public override string DisplayName => "Vignette";
public FloatCurveChannel intensityCurve = FloatCurveChannel.CreateDefault(remapMax: 1f);
/// <summary>
/// 是否修改暗角中心点。
/// </summary>
[LabelText("修改中心点")]
public bool modifyCenter;
/// <summary>
/// 模糊中心的屏幕坐标 (0-1)。(0.5, 0.5) 为屏幕正中心。
/// </summary>
[HideIf("modifyCenter")]
[LabelText("中心点")]
public Vector2 center = new Vector2(0.5f, 0.5f);
[ShowIf("modifyCenter")]
[LabelText("中心点曲线")]
public Vector2CurveChannel centerCurve = Vector2CurveChannel.CreateDefault();
/// <summary>
/// 是否修改颜色。
/// </summary>
[LabelText("修改颜色")]
public bool modifyColors;
[HideIf("modifyColors")]
public Color outColor;
[HideIf("modifyColors")]
public Color innerColor;
/// <summary>
/// 外圈颜色。
/// </summary>
[ShowIf("modifyColors")]
[LabelText("外圈颜色")]
public Color outColor = Color.black;
[HideIf("modifyColors")]
[LabelText("内圈颜色")]
public Color innerColor = Color.black;
[ShowIf("modifyColors")]
[LabelText("外圈颜色曲线")]
public ColorCurveChannel outerColorCurve = ColorCurveChannel.CreateDefault();
/// <summary>
/// 内圈颜色。
/// </summary>
[ShowIf("modifyColors")]
[LabelText("内圈颜色")]
[LabelText("内圈颜色曲线")]
public ColorCurveChannel innerColorCurve = ColorCurveChannel.CreateDefault();
/// <summary>
/// 是否修改形状。
/// </summary>
[LabelText("修改形状")]
public bool modifyShape;
[HideIf("modifyShape")]
public float smoothness;
[LabelText("柔和度")]
public float smoothness = 0.5f;
[HideIf("modifyShape")]
public float roundness;
[LabelText("圆度")]
public float roundness = 1f;
/// <summary>
/// 柔和度曲线。
/// </summary>
[ShowIf("modifyShape")]
[LabelText("柔和度曲线")]
public FloatCurveChannel smoothnessCurve = FloatCurveChannel.CreateDefault(remapMax: 0.5f);
/// <summary>
/// 圆度曲线。
/// </summary>
[ShowIf("modifyShape")]
[LabelText("圆度曲线")]
public FloatCurveChannel roundnessCurve = FloatCurveChannel.CreateDefault(remapMax: 1f);
@@ -91,13 +71,18 @@ namespace Cielonos.MainGame.Effects.Feedback
context,
intensityCurve,
modifyCenter,
center,
modifyCenter ? centerCurve : default,
modifyCenter ? center : default(Vector2),
modifyColors,
outerColorCurve,
innerColorCurve,
modifyColors ? outerColorCurve : default,
modifyColors ? innerColorCurve : default,
modifyColors ? outColor : default,
modifyColors ? innerColor : default,
modifyShape,
smoothnessCurve,
roundnessCurve
modifyShape ? smoothnessCurve : default,
modifyShape ? roundnessCurve : default,
modifyShape ? smoothness : 0f,
modifyShape ? roundness : 0f
);
}

View File

@@ -17,10 +17,15 @@ namespace Cielonos.MainGame.Effects.Feedback
public delegate void ShakeDelegate(
FeedbackContext feedbackContext,
bool modifyExposure,
FloatCurveChannel exposureCurve,
bool modifyContrast,
FloatCurveChannel contrastCurve,
bool modifySaturation,
FloatCurveChannel saturationCurve,
bool modifyHue,
FloatCurveChannel hueCurve,
bool modifyColorFilter,
ColorCurveChannel colorFilterCurve,
bool stop
);
@@ -30,14 +35,32 @@ namespace Cielonos.MainGame.Effects.Feedback
public static void Trigger(
FeedbackContext feedbackContext,
bool modifyExposure = false,
FloatCurveChannel exposureCurve = default,
bool modifyContrast = false,
FloatCurveChannel contrastCurve = default,
bool modifySaturation = false,
FloatCurveChannel saturationCurve = default,
bool modifyHue = false,
FloatCurveChannel hueCurve = default,
bool modifyColorFilter = false,
ColorCurveChannel colorFilterCurve = default,
bool stop = false)
{
OnEvent?.Invoke(feedbackContext, exposureCurve, contrastCurve, saturationCurve, hueCurve, colorFilterCurve, stop);
OnEvent?.Invoke(
feedbackContext,
modifyExposure,
exposureCurve,
modifyContrast,
contrastCurve,
modifySaturation,
saturationCurve,
modifyHue,
hueCurve,
modifyColorFilter,
colorFilterCurve,
stop
);
}
}
@@ -46,26 +69,45 @@ namespace Cielonos.MainGame.Effects.Feedback
/// </summary>
public class AnimeACESShakeInstance : ShakeInstanceBase
{
public readonly FloatCurveChannel ExposureCurve;
public readonly FloatCurveChannel ContrastCurve;
public readonly FloatCurveChannel SaturationCurve;
public readonly FloatCurveChannel HueCurve;
public readonly ColorCurveChannel ColorFilterCurve;
public readonly bool modifyExposure;
public readonly FloatCurveChannel exposureCurve;
public readonly bool modifyContrast;
public readonly FloatCurveChannel contrastCurve;
public readonly bool modifySaturation;
public readonly FloatCurveChannel saturationCurve;
public readonly bool modifyHue;
public readonly FloatCurveChannel hueCurve;
public readonly bool modifyColorFilter;
public readonly ColorCurveChannel colorFilterCurve;
public AnimeACESShakeInstance(
FeedbackContext feedbackContext,
bool modifyExposure,
FloatCurveChannel exposureCurve,
bool modifyContrast,
FloatCurveChannel contrastCurve,
bool modifySaturation,
FloatCurveChannel saturationCurve,
bool modifyHue,
FloatCurveChannel hueCurve,
bool modifyColorFilter,
ColorCurveChannel colorFilterCurve)
: base(feedbackContext.timeSettings, feedbackContext.player.TimeProvider, feedbackContext.duration)
{
ExposureCurve = exposureCurve;
ContrastCurve = contrastCurve;
SaturationCurve = saturationCurve;
HueCurve = hueCurve;
ColorFilterCurve = colorFilterCurve;
this.modifyExposure = modifyExposure;
this.modifyContrast = modifyContrast;
this.modifySaturation = modifySaturation;
this.modifyHue = modifyHue;
this.modifyColorFilter = modifyColorFilter;
this.exposureCurve = exposureCurve;
this.contrastCurve = contrastCurve;
this.saturationCurve = saturationCurve;
this.hueCurve = hueCurve;
this.colorFilterCurve = colorFilterCurve;
}
}
@@ -115,38 +157,39 @@ namespace Cielonos.MainGame.Effects.Feedback
for (int i = _activeShakes.Count - 1; i >= 0; i--)
{
AnimeACESShakeInstance shake = _activeShakes[i];
shake.timer += shake.timeProvider.GetDeltaTime(shake.timeSettings);
shake.Tick();
float normalizedTime = shake.timer / shake.duration;
// Exposure
if (shake.ExposureCurve.active)
if (shake.modifyExposure)
{
additiveExposure += shake.ExposureCurve.Evaluate(normalizedTime);
additiveExposure += shake.exposureCurve.Evaluate(normalizedTime);
Debug.Log($"Exposure shake: {additiveExposure}");
}
// Contrast
if (shake.ContrastCurve.active)
if (shake.modifyContrast)
{
additiveContrast += shake.ContrastCurve.Evaluate(normalizedTime);
additiveContrast += shake.contrastCurve.Evaluate(normalizedTime);
}
// Saturation
if (shake.SaturationCurve.active)
if (shake.modifySaturation)
{
additiveSaturation += shake.SaturationCurve.Evaluate(normalizedTime);
additiveSaturation += shake.saturationCurve.Evaluate(normalizedTime);
}
// Hue
if (shake.HueCurve.active)
if (shake.modifyHue)
{
additiveHue += shake.HueCurve.Evaluate(normalizedTime);
additiveHue += shake.hueCurve.Evaluate(normalizedTime);
}
// Color Filter
if (shake.ColorFilterCurve.active)
if (shake.modifyColorFilter)
{
colorFilterAccum = shake.ColorFilterCurve.Evaluate(normalizedTime);
colorFilterAccum = shake.colorFilterCurve.Evaluate(normalizedTime);
hasColorFilter = true;
}
@@ -171,10 +214,15 @@ namespace Cielonos.MainGame.Effects.Feedback
private void OnShakeEvent(
FeedbackContext feedbackContext,
bool modifyExposure,
FloatCurveChannel exposureCurve,
bool modifyContrast,
FloatCurveChannel contrastCurve,
bool modifySaturation,
FloatCurveChannel saturationCurve,
bool modifyHue,
FloatCurveChannel hueCurve,
bool modifyColorFilter,
ColorCurveChannel colorFilterCurve,
bool stop)
{
@@ -184,12 +232,11 @@ namespace Cielonos.MainGame.Effects.Feedback
var instance = new AnimeACESShakeInstance(
feedbackContext,
exposureCurve,
contrastCurve,
saturationCurve,
hueCurve,
colorFilterCurve
);
modifyExposure, exposureCurve,
modifyContrast, contrastCurve,
modifySaturation, saturationCurve,
modifyHue, hueCurve,
modifyColorFilter, colorFilterCurve);
_activeShakes.Add(instance);
}

View File

@@ -118,21 +118,18 @@ namespace Cielonos.MainGame.Effects.Feedback
float normalizedTime = shake.timer / shake.duration;
if (shake.intensityCurve.active)
float curveValue = shake.intensityCurve.Evaluate(normalizedTime);
if (shake.intensityCurve.relativeToInitial)
{
float curveValue = shake.intensityCurve.Evaluate(normalizedTime);
if (shake.intensityCurve.relativeToInitial)
{
additiveIntensity += curveValue;
}
else
{
absoluteIntensity = curveValue;
hasAbsolute = true;
}
additiveIntensity += curveValue;
}
else
{
absoluteIntensity = curveValue;
hasAbsolute = true;
}
if (shake.modifyJitter && shake.jitterCurve.active)
if (shake.modifyJitter)
{
additiveJitter += shake.jitterCurve.Evaluate(normalizedTime);
}

View File

@@ -56,13 +56,13 @@ namespace Cielonos.MainGame.Effects.Feedback
public class CameraFovShaker : MonoBehaviour
{
private CinemachineCamera _camera;
private float _initialFov;
public float initialFov;
private readonly List<CameraFovShakeInstance> _activeShakes = new List<CameraFovShakeInstance>();
private void Awake()
{
_camera = GetComponent<CinemachineCamera>();
_initialFov = _camera.Lens.FieldOfView;
initialFov = _camera.Lens.FieldOfView;
}
private void OnEnable()
@@ -82,7 +82,7 @@ namespace Cielonos.MainGame.Effects.Feedback
if (_activeShakes.Count == 0)
{
SetFov(_initialFov);
SetFov(initialFov);
return;
}
@@ -112,7 +112,7 @@ namespace Cielonos.MainGame.Effects.Feedback
}
}
float finalFov = hasAbsolute ? absoluteFov : _initialFov + additiveFov;
float finalFov = hasAbsolute ? absoluteFov : initialFov + additiveFov;
SetFov(finalFov);
}
@@ -144,7 +144,7 @@ namespace Cielonos.MainGame.Effects.Feedback
_activeShakes.Clear();
if (_camera != null)
{
SetFov(_initialFov);
SetFov(initialFov);
}
}
}

View File

@@ -109,7 +109,6 @@ namespace Cielonos.MainGame.Effects.Feedback
}
Vector3 totalOffset = Vector3.zero;
for (int i = _activeShakes.Count - 1; i >= 0; i--)
{
CameraRotationShakeInstance shake = _activeShakes[i];
@@ -121,7 +120,6 @@ namespace Cielonos.MainGame.Effects.Feedback
_activeShakes.RemoveAt(i);
}
}
_rotationOffset.rotationOffset = _initialRotation + totalOffset;
}

View File

@@ -0,0 +1,173 @@
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 hasAbsolute = false;
float additiveSpeed = 0f;
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;
hasAbsolute = true;
}
additiveSpeed += shake.speedCurve.Evaluate(normalizedTime);
if (shake.IsFinished)
{
_activeShakes.RemoveAt(i);
}
}
float finalIntensity = hasAbsolute ? absoluteIntensity : _initialIntensity + additiveIntensity;
_component.intensity.value = finalIntensity;
_component.speed.value = _initialSpeed + additiveSpeed;
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();
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e720e1219abdd234b8c87ce75d5815cb

View File

@@ -19,13 +19,18 @@ namespace Cielonos.MainGame.Effects.Feedback
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
);
@@ -36,18 +41,23 @@ namespace Cielonos.MainGame.Effects.Feedback
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, center,
modifyColors, colorOuter, colorInner, modifyShape,
smoothnessCurve, roundnessCurve, stop);
OnEvent?.Invoke(feedbackContext, intensityCurve, modifyCenter, centerCurve, center,
modifyColors, colorOuter, colorInner, outColor, innerColor, modifyShape,
smoothnessCurve, roundnessCurve, smoothness, roundness, stop);
}
}
@@ -58,36 +68,51 @@ namespace Cielonos.MainGame.Effects.Feedback
{
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)
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;
}
}
@@ -148,37 +173,44 @@ namespace Cielonos.MainGame.Effects.Feedback
float normalizedTime = shake.timer / shake.duration;
if (shake.intensityCurve.active)
float curveValue = shake.intensityCurve.Evaluate(normalizedTime);
if (shake.intensityCurve.relativeToInitial)
{
float curveValue = shake.intensityCurve.Evaluate(normalizedTime);
if (shake.intensityCurve.relativeToInitial)
{
additiveIntensity += curveValue;
}
else
{
absoluteIntensity = curveValue;
hasAbsolute = true;
}
additiveIntensity += curveValue;
}
else
{
absoluteIntensity = curveValue;
hasAbsolute = true;
}
if (shake.modifyCenter)
{
latestCenter = shake.center;
latestCenter = shake.modifyCenter
? shake.centerCurve.Evaluate(normalizedTime, _initialCenter)
: shake.center;
hasCenter = true;
}
if (shake.modifyColors)
{
latestColorOuter = shake.colorOuter.Evaluate(normalizedTime);
latestColorInner = shake.colorInner.Evaluate(normalizedTime);
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.smoothnessCurve.Evaluate(normalizedTime);
latestRoundness = shake.roundnessCurve.Evaluate(normalizedTime);
latestSmoothness = shake.modifyShape
? shake.smoothnessCurve.Evaluate(normalizedTime)
: shake.smoothness;
latestRoundness = shake.modifyShape
? shake.roundnessCurve.Evaluate(normalizedTime)
: shake.roundness;
hasShape = true;
}
@@ -213,13 +245,18 @@ namespace Cielonos.MainGame.Effects.Feedback
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; }
@@ -227,9 +264,21 @@ namespace Cielonos.MainGame.Effects.Feedback
if (!_resolved) return;
var instance = new VignetteShakeInstance(
feedbackContext, intensityCurve, modifyCenter, center,
modifyColors, colorOuter, colorInner, modifyShape,
smoothnessCurve, roundnessCurve
feedbackContext,
intensityCurve,
modifyCenter,
centerCurve,
center,
modifyColors,
colorOuter,
colorInner,
outColor,
innerColor,
modifyShape,
smoothnessCurve,
roundnessCurve,
smoothness,
roundness
);
_activeShakes.Add(instance);
}