fix(dialog): 修复快进时后处理渐变回写

This commit is contained in:
2026-07-19 22:36:45 +08:00
parent 06d6127c69
commit 5a37f529ab
+92 -27
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using AibisDream.Framework;
using AibisDream.UI;
using UnityEngine;
@@ -11,6 +12,10 @@ 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("NextYarn")]
@@ -54,6 +59,7 @@ namespace AibisDream
return;
}
CancelVolumeTween(volume, ActiveVolumeWeightTweens);
volume.weight = Mathf.Clamp01(weight);
}
@@ -69,23 +75,14 @@ namespace AibisDream
}
targetWeight = Mathf.Clamp01(targetWeight);
if (duration <= 0f)
{
volume.weight = targetWeight;
yield break;
}
var startWeight = volume.weight;
var elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.unscaledDeltaTime;
var progress = Mathf.Clamp01(elapsed / duration);
volume.weight = Mathf.Lerp(startWeight, targetWeight, EaseInOutSine(progress));
yield return null;
}
volume.weight = targetWeight;
yield return TweenVolumeFloat(
volume,
ActiveVolumeWeightTweens,
() => volume.weight,
value => volume.weight = value,
targetWeight,
duration,
EaseInOutSine);
}
[YarnCommand("tween_volume_weight_async")]
@@ -103,28 +100,32 @@ namespace AibisDream
[YarnCommand("set_volume_brightness")]
public static void SetVolumeBrightness(string volumeName, float brightness)
{
if (!TryGetVolumeAdjustments(volumeName, out _, out var adjustments))
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 _, out var adjustments))
if (!TryGetVolumeAdjustments(volumeName, out var volume, out var adjustments))
{
yield break;
}
targetBrightness = Mathf.Clamp(targetBrightness, -1f, 1f);
yield return TweenUnscaledFloat(
yield return TweenVolumeFloat(
volume,
ActiveVolumeBrightnessTweens,
() => adjustments.m_Brightness.value,
value => adjustments.m_Brightness.value = value,
targetBrightness,
duration);
duration,
SmootherStep);
}
[YarnCommand("tween_volume_brightness_async")]
@@ -153,12 +154,12 @@ namespace AibisDream
// Bloom 先扩散;等 Bloom 完全起来后,才用曝光把剩余暗部推到纯白。
adjustments.m_Brightness.value = 0f;
yield return TweenUnscaledFloat(
yield return TweenFloat(
() => volume.weight,
value => volume.weight = value,
1f,
bloomDuration);
yield return TweenUnscaledFloat(
yield return TweenFloat(
() => adjustments.m_Brightness.value,
value => adjustments.m_Brightness.value = value,
1f,
@@ -177,12 +178,12 @@ namespace AibisDream
}
// 先从纯白恢复画面层次,再逐渐收掉仍然存在的 Bloom。
yield return TweenUnscaledFloat(
yield return TweenFloat(
() => adjustments.m_Brightness.value,
value => adjustments.m_Brightness.value = value,
0f,
exposureDuration);
yield return TweenUnscaledFloat(
yield return TweenFloat(
() => volume.weight,
value => volume.weight = value,
0f,
@@ -217,7 +218,7 @@ namespace AibisDream
return true;
}
private static IEnumerator TweenUnscaledFloat(
private static IEnumerator TweenFloat(
Func<float> getter,
Action<float> setter,
float target,
@@ -233,7 +234,8 @@ namespace AibisDream
var elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.unscaledDeltaTime;
// 与 Yarn 的 <<wait>> 使用同一时间域,让快进同步加速后处理演出。
elapsed += Time.deltaTime;
var progress = Mathf.Clamp01(elapsed / duration);
setter(Mathf.Lerp(start, target, SmootherStep(progress)));
yield return null;
@@ -242,6 +244,69 @@ namespace AibisDream
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);