using System; using UnityEngine; namespace AibisDream { public class LineAdvanceInput : MonoBehaviour { #region 状态 private LineSyncToken _curSyncToken; private ILineAdvanceHandler _handler; #endregion private ILineAdvanceHandler _defaultHandler = new DefaultAdvanceHandler(); private ILineAdvanceHandler _quickHandler = new QuickAdvanceHandler(); private ILineAdvanceHandler _autoHandler = new AutoAdvanceHandler(); private void OnEnable() { if (DialogController.Instance != null) { DialogController.Instance.advanceMode.RegisterAndTrigger(OnAdvanceModeChanged); } else { ResetAdvanceMode(); } } private void OnDisable() { if (DialogController.Instance != null) { DialogController.Instance.advanceMode.UnRegister(OnAdvanceModeChanged); } } private void OnAdvanceModeChanged(AdvanceMode mode) { SwitchAdvanceHandler(mode.CurrentMode); } public void RunLine(LineSyncToken lineSyncEvent) { _curSyncToken = lineSyncEvent; } private void LateUpdate() { _handler.Handle(_curSyncToken, IsInputAvailable, IsPointerOverUI); } public void SwitchAdvanceHandler(AdvanceModeEnum advanceMode) { _handler = advanceMode switch { AdvanceModeEnum.Auto => _autoHandler, AdvanceModeEnum.Quick => _quickHandler, AdvanceModeEnum.Default => _defaultHandler, _ => _defaultHandler, }; } public void ResetAdvanceMode() { _handler = _defaultHandler; } #region 输入事件处理 private bool IsInputAvailable() { return GameManager.Session.CanAdvanceDialogue && _curSyncToken != null && _curSyncToken.state != LineSyncState.Advanced; } private bool IsPointerOverUI() { return UIManager.Instance != null && UIManager.Instance.IsPointerOverUI(Input.mousePosition); } #endregion } public interface ILineAdvanceHandler { void Handle(LineSyncToken token, Func isAvailable, Func isPointerOverUI); static ILineAdvanceHandler Create(bool autoMode) { return autoMode ? new AutoAdvanceHandler() : new DefaultAdvanceHandler(); } } public class DefaultAdvanceHandler : ILineAdvanceHandler { public void Handle(LineSyncToken token, Func isAvailable, Func isPointerOverUI) { var pointerAdvance = Input.GetMouseButtonDown(0) && !isPointerOverUI(); var keyboardAdvance = Input.GetKeyDown(KeyCode.Space); if (pointerAdvance || keyboardAdvance) { if (isAvailable()) { HandleInput(token); } } } private void HandleInput(LineSyncToken token) { switch (token.state) { case LineSyncState.PlayText: token.TrySkip(); break; case LineSyncState.WaitForAdvance: token.TryAdvance(); break; case LineSyncState.WaitForAutoAdvance: token.TryAdvance(); break; } } } public class AutoAdvanceHandler : ILineAdvanceHandler { public void Handle(LineSyncToken token, Func isAvailable, Func isPointerOverUI) { if (!isAvailable()) { return; } // 如果已经可以继续了,就直接往下 if (token.state == LineSyncState.WaitForAutoAdvance) { token.TryAdvance(); return; } var pointerAdvance = Input.GetMouseButtonDown(0) && !isPointerOverUI(); var keyboardAdvance = Input.GetKeyDown(KeyCode.Space); if (pointerAdvance || keyboardAdvance) { HandleInput(token); } } private void HandleInput(LineSyncToken token) { switch (token.state) { case LineSyncState.PlayText: token.TrySkip(); break; case LineSyncState.WaitForAdvance: token.TryAdvance(); break; case LineSyncState.WaitForAutoAdvance: token.TryAdvance(); break; } } } public class QuickAdvanceHandler : ILineAdvanceHandler { public void Handle(LineSyncToken token, Func isAvailable, Func isPointerOverUI) { if (!isAvailable()) { return; } // 加速模式强制快进 if (token.state == LineSyncState.PlayText) { token.TrySkip(); } // 如果已经可以继续了,就直接往下 if (token.state is LineSyncState.AdvanceDelay or LineSyncState.WaitForAdvance or LineSyncState.WaitForAutoAdvance) { token.ForceAdvance(); } } } }