diff --git a/Assets/Scripts/FixSystem/Effect/MouseFollowEffect.cs b/Assets/Scripts/FixSystem/Effect/MouseFollowEffect.cs index fe72e41a9..cf2bd828c 100644 --- a/Assets/Scripts/FixSystem/Effect/MouseFollowEffect.cs +++ b/Assets/Scripts/FixSystem/Effect/MouseFollowEffect.cs @@ -1,5 +1,6 @@ using AibisDream.Framework; using DG.Tweening; +using System.Collections; using TMPro; using UnityEngine; using UnityEngine.Serialization; @@ -83,11 +84,11 @@ namespace AibisDream initialPosition = PanTransform.position; } - public void MoveFocusTo(Transform target, float duration, Vector2 minBounds, Vector2 maxBounds, Vector2 viewportSize) + public Tween MoveFocusTo(Transform target, float duration, Vector2 minBounds, Vector2 maxBounds, Vector2 viewportSize) { if (target == null) { - return; + return null; } Vector3 focusPosition = ClampFocusPosition(target.position, minBounds, maxBounds, viewportSize); @@ -115,10 +116,26 @@ namespace AibisDream if (duration <= 0f) { PanTransform.position = initialPosition + currentOffset; - return; + focusTween = null; + return null; } focusTween = PanTransform.DOMove(initialPosition + currentOffset, duration).SetEase(Ease.InOutSine); + return focusTween; + } + + public IEnumerator WaitForFocusMove(float fallbackDuration = 0f) + { + if (focusTween != null && focusTween.IsActive()) + { + yield return focusTween.WaitForCompletion(); + yield break; + } + + if (fallbackDuration > 0f) + { + yield return new WaitForSeconds(fallbackDuration); + } } private void Start() diff --git a/Assets/Scripts/MiniGame/Peipei/Eye/EyeSystem.cs b/Assets/Scripts/MiniGame/Peipei/Eye/EyeSystem.cs index c09b7b5d7..e60f0104b 100644 --- a/Assets/Scripts/MiniGame/Peipei/Eye/EyeSystem.cs +++ b/Assets/Scripts/MiniGame/Peipei/Eye/EyeSystem.cs @@ -52,6 +52,81 @@ namespace AibisDream public float GetEffectTransitionDuration() => visualSettings.GetDurationForState(_currentState); + private bool ShouldPreBlinkForFocusedEffect() + { + return _currentState is EyeColorState.CanImagineColor + or EyeColorState.CannotImagineColor + or EyeColorState.CanSeeColor; + } + + private IEnumerator WaitForFocusMovement(float moveDuration) + { + if (!EnsureMouseFollowAndZoom()) + { + yield break; + } + + yield return mouseFollowAndZoom.WaitForFocusMove(moveDuration); + } + + private IEnumerator RunFocusedEffectWithPreBlink(EyeTarget target) + { + if (EnsureMouseFollowAndZoom()) + { + yield return mouseFollowAndZoom.WaitForFocusMove(); + } + + float duration = GetEffectTransitionDuration(); + EyeViewportOverlay overlay = EnsureViewportOverlay(); + + if (overlay != null && Application.isPlaying && ShouldPreBlinkForFocusedEffect()) + { + 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); + } + } + else + { + eyeStateEffect?.ApplyFocusedEffect(target, this); + } + + yield return new WaitForSeconds(duration); + } + + private IEnumerator RunBlurOutWithPreBlink(EyeTarget target, float duration) + { + EyeViewportOverlay overlay = EnsureViewportOverlay(); + + if (overlay != null && Application.isPlaying) + { + yield return overlay.PlayPreEffectBlinkThen( + 1, + visualSettings, + () => target.BlurOut(duration), + visualSettings.focusEffectAtBlinkOpen); + } + else + { + target.BlurOut(duration); + } + + yield return new WaitForSeconds(duration); + } + private void OnValidate() { ApplyVisualSettingsNow( @@ -289,7 +364,7 @@ namespace AibisDream [YarnCommand("EyeBlink")] public void EyeBlink(float duration = 0f) { - EnsureViewportOverlay()?.PlayBlink(duration > 0f ? duration : null); + EnsureViewportOverlay()?.PlayBlink(duration > 0f ? duration : null, restartAutoBlinkAfter: true); } [YarnCommand("set_Eyetarget")] @@ -311,28 +386,28 @@ namespace AibisDream YarnVariableStorage.Instance.SetValue("$currentEyeTarget", target.name); StartCoroutine(EyeEffect_FadeOut()); - FocusOnTarget(target, 1f); + const float focusMoveDuration = 1f; + FocusOnTarget(target, focusMoveDuration); if (currentTarget != null) { currentTarget.BlurIn(visualSettings.targetSwitchDuration); } + yield return WaitForFocusMovement(focusMoveDuration); + if (currentTarget == target) { DialogController.Instance.StartDialogNode("重复看同一个目标"); currentTarget = target; mouseFollowAndZoom.SetIndicatorTarget(currentTarget); - currentTarget.BlurOut(visualSettings.targetSwitchDuration); - yield return new WaitForSeconds(visualSettings.targetSwitchDuration); + yield return RunBlurOutWithPreBlink(currentTarget, visualSettings.targetSwitchDuration); yield break; } currentTarget = target; mouseFollowAndZoom.SetIndicatorTarget(currentTarget); - currentTarget.BlurOut(visualSettings.targetSwitchDuration); - - yield return new WaitForSeconds(visualSettings.targetSwitchDuration); + yield return RunBlurOutWithPreBlink(currentTarget, visualSettings.targetSwitchDuration); if (startDialogue) { @@ -357,10 +432,8 @@ namespace AibisDream if (currentTarget != null) { AudioManager.Instance.PlaySfx("event:/ActionFB/color_imagine"); - eyeStateEffect?.ApplyFocusedEffect(currentTarget, this); + yield return RunFocusedEffectWithPreBlink(currentTarget); } - - yield return new WaitForSeconds(GetEffectTransitionDuration()); } [YarnCommand("EyeEffect_FadeOut")]