550 lines
19 KiB
C#
550 lines
19 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using AibisDream.Framework;
|
|
using AibisDream.UI;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using VolFx;
|
|
using Yarn.Unity;
|
|
|
|
namespace AibisDream
|
|
{
|
|
public static class BaseYarnCommand
|
|
{
|
|
private static readonly Dictionary<int, long> ActiveVolumeWeightTweens = new();
|
|
private static readonly Dictionary<int, long> ActiveVolumeBrightnessTweens = new();
|
|
private static long _nextVolumeTweenToken;
|
|
|
|
#region 命令名
|
|
|
|
[YarnCommand("OpenEndMenu")]
|
|
public static void OpenEndMenu()
|
|
{
|
|
UIManager.Instance.ShowPanel<EndPanel>();
|
|
}
|
|
|
|
[YarnCommand("NextYarn")]
|
|
public static void NextYarn(string exitName = null)
|
|
{
|
|
if (!GameManager.Instance.TryAdvanceChapterFromYarn(exitName))
|
|
{
|
|
return;
|
|
}
|
|
|
|
EnumEventSystem.Global.Send(EventEnum.NextYarn);
|
|
YarnVariableStorage.Instance.ClearLocal();
|
|
}
|
|
|
|
[YarnCommand("load_scene")]
|
|
public static IEnumerator LoadScene(string sceneName, float _unusedFadeDuration = 0f)
|
|
{
|
|
yield return GameManager.Instance.LoadSceneFromYarn(sceneName);
|
|
}
|
|
|
|
[YarnCommand("unload_scene")]
|
|
public static IEnumerator UnloadScene()
|
|
{
|
|
yield return GameManager.Instance.UnloadSceneFromYarn();
|
|
}
|
|
|
|
[YarnCommand("set_volume_weight")]
|
|
public static void SetVolumeWeight(string volumeName, float weight)
|
|
{
|
|
var volumeObject = GameObject.Find(volumeName);
|
|
var volume = volumeObject != null ? volumeObject.GetComponent<Volume>() : null;
|
|
if (volume == null)
|
|
{
|
|
Debug.LogWarning($"[BaseYarnCommand] 未找到 Volume: {volumeName}");
|
|
return;
|
|
}
|
|
|
|
CancelVolumeTween(volume, ActiveVolumeWeightTweens);
|
|
volume.weight = Mathf.Clamp01(weight);
|
|
}
|
|
|
|
[YarnCommand("tween_volume_weight")]
|
|
public static IEnumerator TweenVolumeWeight(string volumeName, float targetWeight, float duration)
|
|
{
|
|
var volumeObject = GameObject.Find(volumeName);
|
|
var volume = volumeObject != null ? volumeObject.GetComponent<Volume>() : null;
|
|
if (volume == null)
|
|
{
|
|
Debug.LogWarning($"[BaseYarnCommand] 未找到 Volume: {volumeName}");
|
|
yield break;
|
|
}
|
|
|
|
targetWeight = Mathf.Clamp01(targetWeight);
|
|
yield return TweenVolumeFloat(
|
|
volume,
|
|
ActiveVolumeWeightTweens,
|
|
() => volume.weight,
|
|
value => volume.weight = value,
|
|
targetWeight,
|
|
duration,
|
|
EaseInOutSine);
|
|
}
|
|
|
|
[YarnCommand("tween_volume_weight_async")]
|
|
public static void TweenVolumeWeightAsync(string volumeName, float targetWeight, float duration)
|
|
{
|
|
if (DialogController.Instance == null)
|
|
{
|
|
Debug.LogWarning("[BaseYarnCommand] DialogController 未初始化,无法启动异步 Volume tween");
|
|
return;
|
|
}
|
|
|
|
DialogController.Instance.StartCoroutine(TweenVolumeWeight(volumeName, targetWeight, duration));
|
|
}
|
|
|
|
[YarnCommand("set_volume_brightness")]
|
|
public static void SetVolumeBrightness(string volumeName, float brightness)
|
|
{
|
|
if (!TryGetVolumeAdjustments(volumeName, out var volume, out var adjustments))
|
|
{
|
|
return;
|
|
}
|
|
|
|
CancelVolumeTween(volume, ActiveVolumeBrightnessTweens);
|
|
adjustments.m_Brightness.value = Mathf.Clamp(brightness, -1f, 1f);
|
|
}
|
|
|
|
[YarnCommand("tween_volume_brightness")]
|
|
public static IEnumerator TweenVolumeBrightness(string volumeName, float targetBrightness, float duration)
|
|
{
|
|
if (!TryGetVolumeAdjustments(volumeName, out var volume, out var adjustments))
|
|
{
|
|
yield break;
|
|
}
|
|
|
|
targetBrightness = Mathf.Clamp(targetBrightness, -1f, 1f);
|
|
yield return TweenVolumeFloat(
|
|
volume,
|
|
ActiveVolumeBrightnessTweens,
|
|
() => adjustments.m_Brightness.value,
|
|
value => adjustments.m_Brightness.value = value,
|
|
targetBrightness,
|
|
duration,
|
|
SmootherStep);
|
|
}
|
|
|
|
[YarnCommand("tween_volume_brightness_async")]
|
|
public static void TweenVolumeBrightnessAsync(string volumeName, float targetBrightness, float duration)
|
|
{
|
|
if (DialogController.Instance == null)
|
|
{
|
|
Debug.LogWarning("[BaseYarnCommand] DialogController 未初始化,无法启动异步曝光 tween");
|
|
return;
|
|
}
|
|
|
|
DialogController.Instance.StartCoroutine(
|
|
TweenVolumeBrightness(volumeName, targetBrightness, duration));
|
|
}
|
|
|
|
[YarnCommand("bloom_exposure_in")]
|
|
public static IEnumerator BloomExposureIn(
|
|
string volumeName,
|
|
float bloomDuration = 2f,
|
|
float exposureDuration = 0.8f)
|
|
{
|
|
if (!TryGetVolumeAdjustments(volumeName, out var volume, out var adjustments))
|
|
{
|
|
yield break;
|
|
}
|
|
|
|
// Bloom 先扩散;等 Bloom 完全起来后,才用曝光把剩余暗部推到纯白。
|
|
adjustments.m_Brightness.value = 0f;
|
|
yield return TweenFloat(
|
|
() => volume.weight,
|
|
value => volume.weight = value,
|
|
1f,
|
|
bloomDuration);
|
|
yield return TweenFloat(
|
|
() => adjustments.m_Brightness.value,
|
|
value => adjustments.m_Brightness.value = value,
|
|
1f,
|
|
exposureDuration);
|
|
}
|
|
|
|
[YarnCommand("bloom_exposure_out")]
|
|
public static IEnumerator BloomExposureOut(
|
|
string volumeName,
|
|
float bloomDuration = 2f,
|
|
float exposureDuration = 0.8f)
|
|
{
|
|
if (!TryGetVolumeAdjustments(volumeName, out var volume, out var adjustments))
|
|
{
|
|
yield break;
|
|
}
|
|
|
|
// 先从纯白恢复画面层次,再逐渐收掉仍然存在的 Bloom。
|
|
yield return TweenFloat(
|
|
() => adjustments.m_Brightness.value,
|
|
value => adjustments.m_Brightness.value = value,
|
|
0f,
|
|
exposureDuration);
|
|
yield return TweenFloat(
|
|
() => volume.weight,
|
|
value => volume.weight = value,
|
|
0f,
|
|
bloomDuration);
|
|
}
|
|
|
|
private static bool TryGetVolumeAdjustments(
|
|
string volumeName,
|
|
out Volume volume,
|
|
out AdjustmentsVol adjustments)
|
|
{
|
|
var volumeObject = GameObject.Find(volumeName);
|
|
volume = volumeObject != null ? volumeObject.GetComponent<Volume>() : null;
|
|
adjustments = null;
|
|
|
|
if (volume == null)
|
|
{
|
|
Debug.LogWarning($"[BaseYarnCommand] 未找到 Volume: {volumeName}");
|
|
return false;
|
|
}
|
|
|
|
// 使用实例化 profile,避免运行时调参污染共享的 VolumeProfile 资源。
|
|
var profile = volume.profile;
|
|
if (profile == null || !profile.TryGet(out adjustments))
|
|
{
|
|
Debug.LogWarning($"[BaseYarnCommand] Volume {volumeName} 缺少 AdjustmentsVol");
|
|
return false;
|
|
}
|
|
|
|
adjustments.active = true;
|
|
adjustments.m_Brightness.overrideState = true;
|
|
return true;
|
|
}
|
|
|
|
private static IEnumerator TweenFloat(
|
|
Func<float> getter,
|
|
Action<float> setter,
|
|
float target,
|
|
float duration)
|
|
{
|
|
if (duration <= 0f)
|
|
{
|
|
setter(target);
|
|
yield break;
|
|
}
|
|
|
|
var start = getter();
|
|
var elapsed = 0f;
|
|
while (elapsed < duration)
|
|
{
|
|
// 与 Yarn 的 <<wait>> 使用同一时间域,让快进同步加速后处理演出。
|
|
elapsed += Time.deltaTime;
|
|
var progress = Mathf.Clamp01(elapsed / duration);
|
|
setter(Mathf.Lerp(start, target, SmootherStep(progress)));
|
|
yield return null;
|
|
}
|
|
|
|
setter(target);
|
|
}
|
|
|
|
private static IEnumerator TweenVolumeFloat(
|
|
Volume volume,
|
|
Dictionary<int, long> activeTweens,
|
|
Func<float> getter,
|
|
Action<float> setter,
|
|
float target,
|
|
float duration,
|
|
Func<float, float> easing)
|
|
{
|
|
var volumeId = volume.GetInstanceID();
|
|
var token = ++_nextVolumeTweenToken;
|
|
activeTweens[volumeId] = token;
|
|
|
|
if (duration <= 0f)
|
|
{
|
|
if (IsCurrentVolumeTween(activeTweens, volumeId, token))
|
|
setter(target);
|
|
CompleteVolumeTween(activeTweens, volumeId, token);
|
|
yield break;
|
|
}
|
|
|
|
var start = getter();
|
|
var elapsed = 0f;
|
|
while (elapsed < duration)
|
|
{
|
|
if (volume == null || !IsCurrentVolumeTween(activeTweens, volumeId, token))
|
|
yield break;
|
|
|
|
// 与 Yarn 的 <<wait>> 使用同一时间域,让快进同步加速后处理演出。
|
|
elapsed += Time.deltaTime;
|
|
var progress = Mathf.Clamp01(elapsed / duration);
|
|
setter(Mathf.Lerp(start, target, easing(progress)));
|
|
yield return null;
|
|
}
|
|
|
|
if (volume != null && IsCurrentVolumeTween(activeTweens, volumeId, token))
|
|
setter(target);
|
|
CompleteVolumeTween(activeTweens, volumeId, token);
|
|
}
|
|
|
|
private static void CancelVolumeTween(Volume volume, Dictionary<int, long> activeTweens)
|
|
{
|
|
if (volume != null)
|
|
activeTweens.Remove(volume.GetInstanceID());
|
|
}
|
|
|
|
private static bool IsCurrentVolumeTween(
|
|
Dictionary<int, long> activeTweens,
|
|
int volumeId,
|
|
long token)
|
|
{
|
|
return activeTweens.TryGetValue(volumeId, out var activeToken) && activeToken == token;
|
|
}
|
|
|
|
private static void CompleteVolumeTween(
|
|
Dictionary<int, long> activeTweens,
|
|
int volumeId,
|
|
long token)
|
|
{
|
|
if (IsCurrentVolumeTween(activeTweens, volumeId, token))
|
|
activeTweens.Remove(volumeId);
|
|
}
|
|
|
|
private static float EaseInOutSine(float progress)
|
|
{
|
|
progress = Mathf.Clamp01(progress);
|
|
return 0.5f - 0.5f * Mathf.Cos(progress * Mathf.PI);
|
|
}
|
|
|
|
private static float SmootherStep(float progress)
|
|
{
|
|
progress = Mathf.Clamp01(progress);
|
|
return progress * progress * progress * (progress * (progress * 6f - 15f) + 10f);
|
|
}
|
|
|
|
[YarnCommand("hide_dialog")]
|
|
public static void HideDialog()
|
|
{
|
|
DialogUIManager.Instance.HideDialog();
|
|
}
|
|
|
|
[YarnCommand("fade_in")]
|
|
public static IEnumerator FadeIn(float duration = 1)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<ScreenTransitionPanel>();
|
|
return panel.FadeInAsync(duration);
|
|
}
|
|
|
|
[YarnCommand("fade_out")]
|
|
public static IEnumerator FadeOut(float duration = 1)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<ScreenTransitionPanel>();
|
|
return panel.FadeOutAsync(duration);
|
|
}
|
|
|
|
[YarnCommand("fade_in_sync")]
|
|
public static void FadeInSync(float duration = 1)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<ScreenTransitionPanel>();
|
|
panel.FadeInSync(duration);
|
|
}
|
|
|
|
[YarnCommand("fade_out_sync")]
|
|
public static void FadeOutSync(float duration = 1)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<ScreenTransitionPanel>();
|
|
panel.FadeOutSync(duration);
|
|
}
|
|
|
|
[YarnCommand("fade_in_white")]
|
|
public static IEnumerator FadeInWhite(float duration = 1)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<ScreenTransitionPanel>();
|
|
return panel.FadeInWhiteAsync(duration);
|
|
}
|
|
|
|
[YarnCommand("flash_white")]
|
|
public static IEnumerator FlashWhite(float duration = 0.2f)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<ScreenTransitionPanel>();
|
|
return panel.FlashWhite(duration);
|
|
}
|
|
|
|
[YarnCommand("wipe_in")]
|
|
public static IEnumerator WipeIn(float duration = 0.6f)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<ScreenTransitionPanel>();
|
|
return panel.WipeInAsync(duration);
|
|
}
|
|
|
|
[YarnCommand("wipe_out")]
|
|
public static IEnumerator WipeOut(float duration = 0.6f)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<ScreenTransitionPanel>();
|
|
return panel.WipeOutAsync(duration);
|
|
}
|
|
|
|
[YarnCommand("shutter_in")]
|
|
public static IEnumerator ShutterIn(float duration = 0.6f)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<ScreenTransitionPanel>();
|
|
return panel.ShutterInAsync(duration);
|
|
}
|
|
|
|
[YarnCommand("shutter_out")]
|
|
public static IEnumerator ShutterOut(float duration = 0.6f)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<ScreenTransitionPanel>();
|
|
return panel.ShutterOutAsync(duration);
|
|
}
|
|
|
|
[YarnCommand("show_obj")]
|
|
public static IEnumerator ShowObj(string picName, float duration = 1)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<PlayToolPanel>();
|
|
return panel.ShowObj(picName, duration);
|
|
}
|
|
|
|
[YarnCommand("show_l10n_obj")]
|
|
public static IEnumerator ShowL10nObj(string picName, float duration = 1)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<PlayToolPanel>();
|
|
return panel.ShowL10nObj(picName, duration);
|
|
}
|
|
|
|
[YarnCommand("hide_obj")]
|
|
public static IEnumerator HideObj(float duration = 1)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<PlayToolPanel>();
|
|
return panel.HideObj(duration);
|
|
}
|
|
|
|
[YarnCommand("show_sprite")]
|
|
public static IEnumerator ShowSprite(string picName, float duration = 1)
|
|
{
|
|
yield return SpriteShowcase.Instance.ShowObj(picName, duration);
|
|
}
|
|
|
|
[YarnCommand("hide_sprite")]
|
|
public static IEnumerator HideSprite(float duration = 1)
|
|
{
|
|
yield return SpriteShowcase.Instance.HideObj(duration);
|
|
}
|
|
|
|
[YarnCommand("showcase_fade_in")]
|
|
public static IEnumerator ShowcaseFadeIn(float duration = 1)
|
|
{
|
|
yield return SpriteShowcase.Instance.FadeInAsync(duration);
|
|
}
|
|
|
|
[YarnCommand("showcase_fade_out")]
|
|
public static IEnumerator ShowcaseFadeOut(float duration = 1)
|
|
{
|
|
yield return SpriteShowcase.Instance.FadeOutAsync(duration);
|
|
}
|
|
|
|
[YarnCommand("showcase_fade_in_sync")]
|
|
public static void ShowcaseFadeInSync(float duration = 1)
|
|
{
|
|
SpriteShowcase.Instance.FadeInSync(duration);
|
|
}
|
|
|
|
[YarnCommand("showcase_fade_out_sync")]
|
|
public static void ShowcaseFadeOutSync(float duration = 1)
|
|
{
|
|
SpriteShowcase.Instance.FadeOutSync(duration);
|
|
}
|
|
|
|
[YarnCommand("show_large_sprite")]
|
|
public static IEnumerator ShowLargeSprite(string picName, float duration = 1)
|
|
{
|
|
yield return SpriteShowcase.Instance.ShowLargeObj(picName, duration);
|
|
}
|
|
|
|
[YarnCommand("hide_large_sprite")]
|
|
public static IEnumerator HideLargeSprite(float duration = 1)
|
|
{
|
|
yield return SpriteShowcase.Instance.HideLargeObj(duration);
|
|
}
|
|
|
|
[YarnCommand("hide_all_sprites")]
|
|
public static IEnumerator HideAllSprites(float duration = 1)
|
|
{
|
|
yield return SpriteShowcase.Instance.HideAll(duration);
|
|
}
|
|
|
|
[YarnCommand("show_full_screen")]
|
|
public static IEnumerator ShowFullScreen(string picName, float duration = 1)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<PlayToolPanel>();
|
|
return panel.ShowFullScreen(picName, duration);
|
|
}
|
|
|
|
[YarnCommand("show_l10n_full_screen")]
|
|
public static IEnumerator ShowL10nFullScreen(string picName, float duration = 1)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<PlayToolPanel>();
|
|
return panel.ShowL10nFullScreen(picName, duration);
|
|
}
|
|
|
|
[YarnCommand("hide_full_screen")]
|
|
public static IEnumerator HideFullScreen(float duration = 1)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<PlayToolPanel>();
|
|
return panel.HideFullScreen(duration);
|
|
}
|
|
|
|
[YarnCommand("open_progress_window")]
|
|
public static IEnumerator OpenProgressWindow(string title, string description, float duration)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<PlayToolPanel>();
|
|
return panel.OpenProgressWindow(title, description, duration);
|
|
}
|
|
|
|
[YarnCommand("open_warning_window")]
|
|
public static IEnumerator OpenWarningWindow(string description)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<PlayToolPanel>();
|
|
return panel.OpenWarningWindow(description);
|
|
}
|
|
|
|
[YarnCommand("flash_red")]
|
|
public static IEnumerator FlashRed(float duration = 0.2f)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<PlayToolPanel>();
|
|
return panel.FlashRed(duration);
|
|
}
|
|
|
|
[YarnCommand("show_sign_board")]
|
|
public static void ShowSignBoard(bool enable = true)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<PlayToolPanel>();
|
|
panel.ShowSignBoard();
|
|
if (enable)
|
|
{
|
|
panel.EnableSignBoard();
|
|
}
|
|
}
|
|
|
|
[YarnCommand("enable_sign_board")]
|
|
public static void EnableSignBoard()
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<PlayToolPanel>();
|
|
panel.EnableSignBoard();
|
|
}
|
|
|
|
[YarnCommand("close_sign_board")]
|
|
public static void CloseSignBoard()
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<PlayToolPanel>();
|
|
panel.CloseSignBoard();
|
|
}
|
|
|
|
[YarnCommand("time_flows_on")]
|
|
public static IEnumerator TimeFlowsOn(string originState, string targetState)
|
|
{
|
|
var panel = UIManager.Instance.GetPanel<PlayToolPanel>();
|
|
return panel.TimeFlowsOn(originState, targetState);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|