Files
aibis-dream/Assets/Scripts/UI/Cursor/CursorManager.cs
T
2025-01-23 18:32:25 +08:00

263 lines
7.4 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using AibisDream.Framework;
using UnityEngine;
using UnityEngine.UI;
namespace AibisDream
{
public class CursorManager : MonoBehaviour
{
private const float DelayTime = 0.1f;
[Header("指针图片")] public Sprite defaultCursor;
public Sprite nextTalk, talking, option, interactive, holding, disable, eye;
private Image _cursor;
#region 状态相关
private Coroutine _switchCoroutine;
private CursorState _curState = CursorState.Default;
private bool _isTalking;
[HideInInspector] public bool isInMenu;
#endregion
// 卸载时注销事件
private readonly List<IUnRegister> _unRegisters = new();
public void Awake()
{
InitRefs();
InitCursor();
}
private void InitCursor()
{
Cursor.visible = false;
SwitchCursor(defaultCursor);
}
private void OnEnable()
{
RegisterEvent();
}
private void OnDisable()
{
// 注销所有事件
foreach (var eventUnRegister in _unRegisters)
{
eventUnRegister.UnRegister();
}
_unRegisters.Clear();
}
private void InitRefs()
{
_cursor = transform.Find("Cursor").GetComponent<Image>();
}
private void RegisterEvent()
{
// 此处监听所有可能对鼠标状态产生影响的事件
RegisterDialogEvent();
RegisterTriggerEvent();
RegisterMenu();
}
private void RegisterDialogEvent()
{
// 对话相关
_unRegisters.Add(EnumEventSystem.Global.Register<DialogEventEnum, DialogLine>(DialogEventEnum.LineStart,
OnLineStart));
_unRegisters.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineShowed, () => SwitchCursor(nextTalk)));
_unRegisters.Add(EnumEventSystem.Global.Register(DialogEventEnum.LineEnd, OnLineEnd));
_unRegisters.Add(EnumEventSystem.Global.Register(DialogEventEnum.OptionShow, OnOptionShow));
_unRegisters.Add(
EnumEventSystem.Global.Register<DialogEventEnum, DialogLine>(DialogEventEnum.OptionSelected,
OnOptionSelect));
}
private void RegisterTriggerEvent()
{
// 交互相关
_unRegisters.Add(EnumEventSystem.Global.Register(InteractionEventEnum.Start, OnInteractiveStart));
_unRegisters.Add(EnumEventSystem.Global.Register(InteractionEventEnum.End, OnInteractiveEnd));
_unRegisters.Add(
EnumEventSystem.Global.Register<TriggerEnum, IInteraction>(TriggerEnum.PointerEnter, OnPointerEnter));
_unRegisters.Add(
EnumEventSystem.Global.Register<TriggerEnum, IInteraction>(TriggerEnum.PointerExit, OnPointerExit));
_unRegisters.Add(
EnumEventSystem.Global.Register<TriggerEnum, IInteraction>(TriggerEnum.PointerDown, OnPointerDown));
_unRegisters.Add(
EnumEventSystem.Global.Register<TriggerEnum, IInteraction>(TriggerEnum.PointerUp, OnPointerUp));
}
private void RegisterMenu()
{
_unRegisters.Add(EnumEventSystem.Global.Register<EventEnum, bool>(EventEnum.Menu, OnMenuChange));
}
private void Update()
{
if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space))
{
if (_isTalking && !isInMenu)
{
DialogController.Instance.JumpLine();
}
}
}
private void LateUpdate()
{
// // 将虚拟指针与鼠标位置同步
// RectTransformUtility.ScreenPointToLocalPointInRectangle(_cursorCanvas, Input.mousePosition,
// CameraKit.Instance.uiCamera, out var worldPos);
_cursor.rectTransform.position = Input.mousePosition;
// 在输入状态,要单独处理
}
#region 对话相关
private void OnLineStart(DialogLine line)
{
_isTalking = true;
SwitchCursor(talking);
}
private void OnLineEnd()
{
StopDelayCursor();
_switchCoroutine = StartCoroutine(DelayAction(() =>
{
_isTalking = false;
_cursor.sprite = defaultCursor;
}));
}
private void OnOptionShow()
{
_isTalking = true;
SwitchCursor(option);
}
private void OnOptionSelect(DialogLine line)
{
StopDelayCursor();
StartCoroutine(DelayAction(() =>
{
_isTalking = false;
_cursor.sprite = defaultCursor;
}));
}
#endregion
#region 交互相关
private void OnInteractiveStart()
{
_curState = CursorState.Interactive;
if (EventSystemEx.Instance.pointerOverObj)
{
SwitchCursor(interactive);
}
}
private void OnInteractiveEnd()
{
_curState = CursorState.Default;
// 退出时把Cursor置为Default
SwitchCursor(defaultCursor);
}
private void OnPointerEnter(IInteraction target)
{
if (_curState == CursorState.Interactive && !_isTalking)
{
// 如果不可交互,就显示不可交互的指针
SwitchCursor(target.IsActive ? interactive : disable);
}
}
private void OnPointerExit(IInteraction target)
{
if (_curState == CursorState.Interactive && !_isTalking)
{
SwitchCursor(defaultCursor);
}
}
private void OnPointerDown(IInteraction target)
{
if (_curState == CursorState.Interactive && !_isTalking)
{
SwitchCursor(target.IsActive ? holding : defaultCursor);
}
}
private void OnPointerUp(IInteraction target)
{
if (_curState == CursorState.Interactive && !_isTalking)
{
// 如果松手时还在物体之上
SwitchCursor(EventSystemEx.Instance.holdingObj == target.GetGameObject() ? interactive : defaultCursor);
}
}
#endregion
#region 菜单打开
private void OnMenuChange(bool isMenuOpen)
{
isInMenu = isMenuOpen;
}
#endregion
#region 指针切换
/// <summary>
/// 直接切指针
/// </summary>
/// <param name="sprite">指针图片</param>
private void SwitchCursor(Sprite sprite)
{
StopDelayCursor();
_cursor.sprite = sprite;
}
private void StopDelayCursor()
{
if (_switchCoroutine != null)
{
StopCoroutine(_switchCoroutine);
_switchCoroutine = null;
}
}
#endregion
private static IEnumerator DelayAction(Action action)
{
yield return new WaitForSeconds(DelayTime);
action.Invoke();
}
}
public enum CursorState
{
Default,
Interactive,
Eye
}
}