using System.Collections.Generic; using System; using AibisDream.Kit; using UnityEngine; namespace AibisDream.Framework { public class EventSystemEx : Singleton { #region 状态 public bool isLocked; private bool _dialogueLocked; private int _scopedLockDepth; #endregion private List pointerOverObjList; private List draggingObjList; private List 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 /// /// 兜底:鼠标左键已抬起时强制清空 holding/dragging。 /// 防止 EventTrigger 在 isLocked 时跳过 Up/EndDrag 清理后光标一直停在抓取。 /// 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(); draggingObjList = new List(); holdingObjList = new List(); _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 } }