129 lines
4.3 KiB
C#
129 lines
4.3 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("Preset")]
|
|
[Tooltip("当前波形预设:normal / predicted / modified_joke / empty,可由 switch_emotion_wave_config 切换")]
|
|
[SerializeField] private string presetId = "normal";
|
|
|
|
[Header("Progress Control")]
|
|
[Range(0f, 1f)]
|
|
[SerializeField] private float progress = 0f;
|
|
|
|
[Header("Smooth Tracking")]
|
|
[SerializeField] private float lerpSpeed = 4f;
|
|
|
|
[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);
|
|
}
|
|
|
|
public string PresetId => presetId;
|
|
|
|
public void SetPreset(string id)
|
|
{
|
|
if (!string.IsNullOrEmpty(id))
|
|
presetId = id;
|
|
}
|
|
|
|
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.InterpolatePreset(presetId, _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;
|
|
}
|
|
|
|
// 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
|
|
}
|