feat(eye): 眨眼仅用于想象上色并关闭自动眨眼

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-21 01:18:46 +08:00
co-authored by Cursor
parent e7a0089a46
commit 1e8ec2e64f
4 changed files with 90 additions and 78 deletions
+2 -2
View File
@@ -1025,8 +1025,8 @@ MonoBehaviour:
eyeWidth: 0.557
eyeHeight: 0.549
edgeSoftness: 0.1871
autoBlink: 1
autoBlinkInterval: {x: 12, y: 18}
autoBlink: 0
autoBlinkInterval: {x: 8, y: 15}
blinkCloseDuration: 0.1
blinkOpenDuration: 0.1
focusEffectAtBlinkOpen: 0.85
+46 -68
View File
@@ -52,11 +52,10 @@ namespace AibisDream
public float GetEffectTransitionDuration() => visualSettings.GetDurationForState(_currentState);
private bool ShouldPreBlinkForFocusedEffect()
/// <summary>仅「可想象色彩」上色时眨眼;无 autoBlink / 失焦眨眼。</summary>
private bool ShouldBlinkForImagine()
{
return _currentState is EyeColorState.CanImagineColor
or EyeColorState.CannotImagineColor
or EyeColorState.CanSeeColor;
return _currentState == EyeColorState.CanImagineColor;
}
private IEnumerator WaitForFocusMovement(float moveDuration)
@@ -79,25 +78,14 @@ namespace AibisDream
float duration = GetEffectTransitionDuration();
EyeViewportOverlay overlay = EnsureViewportOverlay();
if (overlay != null && Application.isPlaying && ShouldPreBlinkForFocusedEffect())
if (overlay != null && Application.isPlaying && ShouldBlinkForImagine())
{
if (_currentState == EyeColorState.CanImagineColor)
{
yield return overlay.PlayPreEffectBlinkThen(
2,
visualSettings,
() => eyeStateEffect?.ApplyFocusedEffect(target, this),
visualSettings.imagineEffectAtBlinkOpen,
visualSettings.imagineBlinkGap);
}
else
{
yield return overlay.PlayPreEffectBlinkThen(
1,
visualSettings,
() => eyeStateEffect?.ApplyFocusedEffect(target, this),
visualSettings.focusEffectAtBlinkOpen);
}
yield return overlay.PlayPreEffectBlinkThen(
2,
visualSettings,
() => eyeStateEffect?.ApplyFocusedEffect(target, this),
visualSettings.imagineEffectAtBlinkOpen,
visualSettings.imagineBlinkGap);
}
else
{
@@ -107,19 +95,9 @@ namespace AibisDream
yield return new WaitForSeconds(duration);
}
private IEnumerator RunBlurOutWithPreBlink(EyeTarget target, float duration)
private IEnumerator RunBlurOut(EyeTarget target, float duration)
{
EyeViewportOverlay overlay = EnsureViewportOverlay();
if (overlay != null && Application.isPlaying)
{
yield return overlay.PlayPreEffectBlinkThen(
1,
visualSettings,
() => target.BlurOut(duration),
visualSettings.focusEffectAtBlinkOpen);
}
else
if (target != null)
{
target.BlurOut(duration);
}
@@ -127,42 +105,34 @@ namespace AibisDream
yield return new WaitForSeconds(duration);
}
private IEnumerator RunUnfocusedEffectWithPreBlink(EyeTarget target)
/// <summary>
/// 换目标时的失焦:只做效果,不眨眼(眨眼仅在想象上色 FadeIn)。
/// </summary>
private void ApplyUnfocusedEffectSilent(EyeTarget target)
{
if (target == null || eyeStateEffect == null)
{
return;
}
if (_currentState == EyeColorState.CanImagineColor
&& target.IsAtUnfocusedColorState(visualSettings))
{
return;
}
eyeStateEffect.ApplyUnfocusedEffect(target, this);
}
private IEnumerator RunUnfocusedEffect(EyeTarget target)
{
if (target == null || eyeStateEffect == null)
{
yield break;
}
float duration = GetEffectTransitionDuration();
EyeViewportOverlay overlay = EnsureViewportOverlay();
if (overlay != null && Application.isPlaying && ShouldPreBlinkForFocusedEffect())
{
if (_currentState == EyeColorState.CanImagineColor)
{
yield return overlay.PlayPreEffectBlinkThen(
2,
visualSettings,
() => eyeStateEffect.ApplyUnfocusedEffect(target, this),
visualSettings.imagineEffectAtBlinkOpen,
visualSettings.imagineBlinkGap);
}
else
{
yield return overlay.PlayPreEffectBlinkThen(
1,
visualSettings,
() => eyeStateEffect.ApplyUnfocusedEffect(target, this),
visualSettings.focusEffectAtBlinkOpen);
}
}
else
{
eyeStateEffect.ApplyUnfocusedEffect(target, this);
}
yield return new WaitForSeconds(duration);
eyeStateEffect.ApplyUnfocusedEffect(target, this);
yield return new WaitForSeconds(GetEffectTransitionDuration());
}
private void OnValidate()
@@ -347,6 +317,14 @@ namespace AibisDream
EnsureViewportOverlay()?.EnterModule(visualSettings);
}
/// <summary>
/// UF 等密集演出:抑制非显式眨眼(含想象过渡眨眼);Yarn EyeBlink 仍可用。
/// </summary>
public void SetNonExplicitBlinkSuppressed(bool suppressed)
{
EnsureViewportOverlay()?.SetNonExplicitBlinkSuppressed(suppressed);
}
private void InitializeAllTargets()
{
foreach (EyeTarget target in targets)
@@ -442,7 +420,7 @@ namespace AibisDream
if (startDialogue)
{
DialogController.Instance.StartDialogNode("重复看同一个目标");
yield return RunBlurOutWithPreBlink(currentTarget, visualSettings.targetSwitchDuration);
yield return RunBlurOut(currentTarget, visualSettings.targetSwitchDuration);
}
yield break;
@@ -451,7 +429,7 @@ namespace AibisDream
EyeTarget leavingTarget = currentTarget;
if (leavingTarget != null)
{
StartCoroutine(EyeEffect_FadeOut());
ApplyUnfocusedEffectSilent(leavingTarget);
}
const float focusMoveDuration = 1f;
@@ -461,7 +439,7 @@ namespace AibisDream
currentTarget = target;
mouseFollowAndZoom.SetIndicatorTarget(currentTarget);
yield return RunBlurOutWithPreBlink(currentTarget, visualSettings.targetSwitchDuration);
yield return RunBlurOut(currentTarget, visualSettings.targetSwitchDuration);
if (startDialogue)
{
@@ -513,7 +491,7 @@ namespace AibisDream
}
AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine");
yield return RunUnfocusedEffectWithPreBlink(currentTarget);
yield return RunUnfocusedEffect(currentTarget);
}
[YarnCommand("EyeEffect_Init")]
@@ -37,6 +37,10 @@ namespace AibisDream
private float blinkOpen = 1f;
private bool moduleActive;
private bool editorPreviewActive;
/// <summary>
/// UF 等密集演出段:关掉 autoBlink 与效果过渡眨眼,仅保留 Yarn EyeBlink。
/// </summary>
private bool suppressNonExplicitBlink;
private bool hierarchyReady;
private bool lifecycleReady;
private Coroutine deferPrepareRoutine;
@@ -75,6 +79,7 @@ namespace AibisDream
public void ExitModule()
{
moduleActive = false;
suppressNonExplicitBlink = false;
if (editorPreviewActive)
{
return;
@@ -85,6 +90,27 @@ namespace AibisDream
activeSettings = null;
}
/// <summary>
/// 抑制自动眨眼与效果过渡眨眼;显式 PlayBlink / Yarn EyeBlink 仍可用。
/// </summary>
public void SetNonExplicitBlinkSuppressed(bool suppressed)
{
suppressNonExplicitBlink = suppressed;
if (suppressed)
{
StopAutoBlink();
return;
}
if (activeSettings != null
&& activeSettings.autoBlink
&& Application.isPlaying
&& (moduleActive || editorPreviewActive))
{
StartAutoBlink(activeSettings);
}
}
public void EnterEditorPreview(EyeVisualSettings settings)
{
editorPreviewActive = true;
@@ -141,7 +167,10 @@ namespace AibisDream
return;
}
if (settings.autoBlink && Application.isPlaying && (moduleActive || editorPreviewActive))
if (settings.autoBlink
&& Application.isPlaying
&& (moduleActive || editorPreviewActive)
&& !suppressNonExplicitBlink)
{
StartAutoBlink(settings);
}
@@ -256,6 +285,7 @@ namespace AibisDream
return Application.isPlaying
&& moduleActive
&& !editorPreviewActive
&& !suppressNonExplicitBlink
&& overlayShaderAvailable
&& settings != null
&& settings.enableViewportOverlay;
@@ -268,6 +298,11 @@ namespace AibisDream
return;
}
if (suppressNonExplicitBlink)
{
return;
}
if (!(moduleActive || editorPreviewActive))
{
return;
@@ -301,7 +336,7 @@ namespace AibisDream
SetOverlayActive(true);
if (settings.autoBlink && Application.isPlaying)
if (settings.autoBlink && Application.isPlaying && !suppressNonExplicitBlink)
{
StartAutoBlink(settings);
}
@@ -328,7 +363,7 @@ namespace AibisDream
private void StartAutoBlink(EyeVisualSettings settings)
{
StopAutoBlink();
if (!settings.autoBlink)
if (!settings.autoBlink || suppressNonExplicitBlink)
{
return;
}
@@ -84,16 +84,15 @@ namespace AibisDream
[Tooltip("Softness of the elliptical sight boundary.")]
[Range(0.001f, 0.2f)] public float edgeSoftness = 0.022f;
[Tooltip("Off by default so you can tune the sight without blinking.")]
[Tooltip("Deprecated: unused. Blink only on imagine FadeIn.")]
public bool autoBlink;
public Vector2 autoBlinkInterval = new(8f, 15f);
[HideInInspector] public Vector2 autoBlinkInterval = new(8f, 15f);
public float blinkCloseDuration = 0.09f;
public float blinkOpenDuration = 0.14f;
[Header("Transition Blink")]
[Tooltip("聚焦:单次眨眼开眼到该进度时触发变清晰(0=刚睁眼,1=完全睁开)。")]
[Range(0f, 1f)] public float focusEffectAtBlinkOpen = 0.85f;
[Header("Imagine Blink (EyeEffect_FadeIn only)")]
[HideInInspector] public float focusEffectAtBlinkOpen = 0.85f;
[Tooltip("想象:两次眨眼之间的间隔(秒)。")]
public float imagineBlinkGap = 0.04f;