Files

217 lines
6.3 KiB
C#

using System.Collections.Generic;
using System;
using AibisDream.Kit;
using UnityEngine;
namespace AibisDream.Framework
{
public class EventSystemEx : Singleton<EventSystemEx>
{
#region 状态
public bool isLocked;
private bool _dialogueLocked;
private int _scopedLockDepth;
#endregion
private List<GameObject> pointerOverObjList;
private List<GameObject> draggingObjList;
private List<GameObject> holdingObjList;
#region 事件触发中转
public void OnPointerEnter(IInteraction interaction)
{
if (!pointerOverObjList.Contains(interaction.GetGameObject()))
{
pointerOverObjList.Add(interaction.GetGameObject());
}
}
public void OnPointerExit(IInteraction interaction)
{
pointerOverObjList.Remove(interaction.GetGameObject());
}
public void OnPointerDown(IInteraction interaction)
{
if (!holdingObjList.Contains(interaction.GetGameObject()))
{
holdingObjList.Add(interaction.GetGameObject());
}
}
public void OnPointerUp(IInteraction interaction)
{
holdingObjList.Remove(interaction.GetGameObject());
}
public void OnDrag(IInteraction interaction)
{
if (!draggingObjList.Contains(interaction.GetGameObject()))
{
draggingObjList.Add(interaction.GetGameObject());
}
}
public void OnEndDrag(IInteraction interaction)
{
draggingObjList.Remove(interaction.GetGameObject());
}
public void OnBeginDrag(IInteraction interaction)
{
if (!draggingObjList.Contains(interaction.GetGameObject()))
{
draggingObjList.Add(interaction.GetGameObject());
}
}
public TriggerEnum GetPointerState()
{
if (holdingObjList.Count > 0 || draggingObjList.Count > 0)
{
return TriggerEnum.Dragging;
}
else if (pointerOverObjList.Count > 0)
{
return TriggerEnum.PointerOver;
}
else
{
return TriggerEnum.None;
}
}
public void UnRegister(IInteraction interaction)
{
pointerOverObjList.Remove(interaction.GetGameObject());
draggingObjList.Remove(interaction.GetGameObject());
holdingObjList.Remove(interaction.GetGameObject());
}
#endregion
/// <summary>
/// 兜底:鼠标左键已抬起时强制清空 holding/dragging。
/// 防止 EventTrigger 在 isLocked 时跳过 Up/EndDrag 清理后光标一直停在抓取。
/// </summary>
private void LateUpdate()
{
if (Input.GetMouseButton(0)) return;
if (holdingObjList.Count > 0)
holdingObjList.Clear();
if (draggingObjList.Count > 0)
draggingObjList.Clear();
}
private void HandleDialogueComplete()
{
_dialogueLocked = false;
RefreshLockState();
}
private void HandleDialogueStart()
{
_dialogueLocked = true;
RefreshLockState();
}
public IDisposable AcquireInteractionLock(string reason)
{
_scopedLockDepth++;
RefreshLockState();
Debug.Log(
$"[EventSystemEx] Acquire interaction lock: {reason ?? "(unspecified)"}, " +
$"depth={_scopedLockDepth}");
return new InteractionLockScope(this, reason);
}
private void ReleaseInteractionLock(string reason)
{
_scopedLockDepth = Math.Max(0, _scopedLockDepth - 1);
RefreshLockState();
Debug.Log(
$"[EventSystemEx] Release interaction lock: {reason ?? "(unspecified)"}, " +
$"depth={_scopedLockDepth}");
}
private void RefreshLockState()
{
isLocked = _dialogueLocked || _scopedLockDepth > 0;
}
#region 单例必须的代码
public override void OnSingletonInit()
{
pointerOverObjList = new List<GameObject>();
draggingObjList = new List<GameObject>();
holdingObjList = new List<GameObject>();
_dialogueLocked = false;
_scopedLockDepth = 0;
RefreshLockState();
EnumEventSystem.Global.Register(GameLifecycleEvent.SessionStarted, ClearAll);
EnumEventSystem.Global.Register(GameLifecycleEvent.SessionEnded, ClearAll);
EnumEventSystem.Global.Register(InteractionEventEnum.DialogEnd, HandleDialogueComplete);
EnumEventSystem.Global.Register(InteractionEventEnum.DialogStart, HandleDialogueStart);
}
private void ClearAll()
{
pointerOverObjList.Clear();
draggingObjList.Clear();
holdingObjList.Clear();
}
public override void OnSingletonDestroy()
{
EnumEventSystem.Global.UnRegister(GameLifecycleEvent.SessionStarted, ClearAll);
EnumEventSystem.Global.UnRegister(GameLifecycleEvent.SessionEnded, ClearAll);
EnumEventSystem.Global.UnRegister(InteractionEventEnum.DialogEnd, HandleDialogueComplete);
EnumEventSystem.Global.UnRegister(InteractionEventEnum.DialogStart, HandleDialogueStart);
_dialogueLocked = false;
_scopedLockDepth = 0;
RefreshLockState();
}
private sealed class InteractionLockScope : IDisposable
{
private EventSystemEx _owner;
private readonly string _reason;
public InteractionLockScope(EventSystemEx owner, string reason)
{
_owner = owner;
_reason = reason;
}
public void Dispose()
{
if (_owner == null)
{
return;
}
_owner.ReleaseInteractionLock(_reason);
_owner = null;
}
}
#endregion
}
public enum TriggerEnum
{
None,
Dragging,
PointerOver
}
}