135 lines
4.8 KiB
C#
135 lines
4.8 KiB
C#
using UnityEngine;
|
|
|
|
namespace AibisDream.MiniGame.HuoShan.EmotionWave
|
|
{
|
|
/// <summary>
|
|
/// Controls the EmotionWave visualization.
|
|
/// Drag the progress slider in the Inspector to drive the 3-act narrative.
|
|
/// Ported from Web_EmotionWave/js/app.js.
|
|
/// </summary>
|
|
[ExecuteAlways]
|
|
public class EmotionWaveController : MonoBehaviour
|
|
{
|
|
[Header("References")]
|
|
[SerializeField] private EmotionWaveConfig config;
|
|
[SerializeField] private EmotionWaveRenderer waveRenderer;
|
|
|
|
[Header("Progress Control")]
|
|
[Range(0f, 1f)]
|
|
[SerializeField] private float progress = 0f;
|
|
|
|
[Header("Smooth Tracking")]
|
|
[SerializeField] private float lerpSpeed = 4f;
|
|
|
|
[Header("Tweak (active in 0.75~1.0 range)")]
|
|
[Range(0f, 1f)] [SerializeField] private float tweakFuzz = 0f;
|
|
[Range(0f, 1f)] [SerializeField] private float tweakSpin = 0.5f;
|
|
[Range(0f, 1f)] [SerializeField] private float tweakHue = 0f;
|
|
|
|
[Header("CRT Startup")]
|
|
[SerializeField] private float startupDuration = 1.8f;
|
|
|
|
[Header("Debug")]
|
|
[SerializeField] [ReadOnlyField] private string currentStage = "";
|
|
[SerializeField] [ReadOnlyField] private string currentStageName = "";
|
|
[SerializeField] [ReadOnlyField] private float smoothedProgress;
|
|
|
|
private float _currentValue;
|
|
private float _elapsedTime;
|
|
|
|
public float Progress
|
|
{
|
|
get => progress;
|
|
set => progress = Mathf.Clamp01(value);
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (config == null || waveRenderer == null) return;
|
|
|
|
float dt = Time.deltaTime;
|
|
_elapsedTime += dt;
|
|
|
|
// CRT startup ease
|
|
float startupFactor = Mathf.Clamp01(_elapsedTime / startupDuration);
|
|
float startupEase = startupFactor * startupFactor;
|
|
|
|
// Smooth tracking
|
|
_currentValue += (progress - _currentValue) * Mathf.Min(1f, dt * lerpSpeed);
|
|
smoothedProgress = _currentValue;
|
|
|
|
// Interpolate wave params
|
|
var waveParams = config.Interpolate(_currentValue);
|
|
|
|
// Inject review parameters based on stage phase
|
|
string phase = config.GetStagePhase(_currentValue);
|
|
currentStage = phase;
|
|
currentStageName = config.GetStageName(_currentValue);
|
|
|
|
if (phase == "REVIEW")
|
|
{
|
|
float r0 = 0.35f, r1 = 0.5f, r2 = 0.65f;
|
|
if (_currentValue <= r1)
|
|
waveParams.reviewIntensity = Smoothstep((_currentValue - r0) / (r1 - r0));
|
|
else
|
|
waveParams.reviewIntensity = 0.15f + 0.85f * Smoothstep((r2 - _currentValue) / (r2 - r1));
|
|
waveParams.featureBoxRate = 3f;
|
|
waveParams.thresholdLevel = 0.75f;
|
|
waveParams.cursorSpeed = 0.5f;
|
|
}
|
|
else
|
|
{
|
|
waveParams.reviewIntensity = 0f;
|
|
waveParams.featureBoxRate = 0f;
|
|
waveParams.thresholdLevel = 0.8f;
|
|
waveParams.cursorSpeed = 0f;
|
|
}
|
|
|
|
// End-stage tweaks (smoothstep fade-in from 0.75)
|
|
float tweakLinear = Mathf.Clamp01((_currentValue - 0.75f) / 0.1f);
|
|
float tweakWeight = tweakLinear * tweakLinear * (3f - 2f * tweakLinear);
|
|
if (tweakWeight > 0.001f)
|
|
{
|
|
float fuzz = tweakFuzz * 0.8f;
|
|
float spin = 0.2f + tweakSpin * 1f;
|
|
float hueVal = tweakHue * 128f;
|
|
waveParams.weierstrassAmount = Mathf.Lerp(waveParams.weierstrassAmount, fuzz, tweakWeight);
|
|
waveParams.phaseSpeed = Mathf.Lerp(waveParams.phaseSpeed, spin, tweakWeight);
|
|
waveParams.hue = Mathf.Lerp(waveParams.hue, hueVal, tweakWeight);
|
|
}
|
|
|
|
// CRT startup fade
|
|
waveParams.glowIntensity *= startupEase;
|
|
waveParams.lightness *= startupEase;
|
|
|
|
// Push to renderer
|
|
waveRenderer.currentParams = waveParams;
|
|
waveRenderer.time = _elapsedTime;
|
|
}
|
|
|
|
static float Smoothstep(float t)
|
|
{
|
|
t = Mathf.Clamp01(t);
|
|
return t * t * (3f - 2f * t);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Makes a field read-only in the Inspector.
|
|
/// </summary>
|
|
public class ReadOnlyFieldAttribute : PropertyAttribute { }
|
|
|
|
#if UNITY_EDITOR
|
|
[UnityEditor.CustomPropertyDrawer(typeof(ReadOnlyFieldAttribute))]
|
|
public class ReadOnlyFieldDrawer : UnityEditor.PropertyDrawer
|
|
{
|
|
public override void OnGUI(Rect position, UnityEditor.SerializedProperty property, GUIContent label)
|
|
{
|
|
UnityEditor.EditorGUI.BeginDisabledGroup(true);
|
|
UnityEditor.EditorGUI.PropertyField(position, property, label);
|
|
UnityEditor.EditorGUI.EndDisabledGroup();
|
|
}
|
|
}
|
|
#endif
|
|
}
|