Files

196 lines
5.5 KiB
C#

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<bool> isAvailable, Func<bool> isPointerOverUI);
static ILineAdvanceHandler Create(bool autoMode)
{
return autoMode ? new AutoAdvanceHandler() : new DefaultAdvanceHandler();
}
}
public class DefaultAdvanceHandler : ILineAdvanceHandler
{
public void Handle(LineSyncToken token, Func<bool> isAvailable, Func<bool> 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<bool> isAvailable, Func<bool> 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<bool> isAvailable, Func<bool> 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();
}
}
}
}