using System.Linq;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
namespace AibisDream.Framework
{
///
/// EventTrigger扩展
///
[RequireComponent(typeof(Collider2D))]
public class EventTriggerEx : EventTrigger
{
private IInteraction _interaction;
private IInteraction Interaction
{
get
{
// 惰性获取:bridge 可能在 EventTriggerEx 之后才 AddComponent
if (_interaction == null)
_interaction = GetComponent();
return _interaction;
}
}
private void Awake()
{
_interaction = GetComponent();
}
///
/// 注册事件
///
/// 事件类型
/// 函数
public void Register(EventTriggerType triggerType, UnityAction action)
{
if (TryGetTriggerEvent(triggerType, out var triggerEvent))
{
triggerEvent.AddListener(action);
}
else
{
Debug.LogWarning($"{triggerType.ToString()}未添加");
}
}
///
/// 卸载事件
///
/// 事件类型
/// 函数
public void UnRegister(EventTriggerType triggerType, UnityAction action)
{
if (TryGetTriggerEvent(triggerType, out var triggerEvent))
{
triggerEvent.RemoveListener(action);
}
else
{
Debug.LogWarning($"{triggerType.ToString()}未添加");
}
}
///
/// 获取触发事件
///
/// 事件类型
/// 事件
/// 是否存在
private bool TryGetTriggerEvent(EventTriggerType triggerType, out TriggerEvent triggerEvent)
{
var entry = triggers.FirstOrDefault(item => item.eventID == triggerType);
if (entry == null)
{
triggerEvent = null;
return false;
}
else
{
triggerEvent = entry.callback;
return true;
}
}
private bool CanStartInteraction()
{
return Interaction != null
&& Interaction.IsAvailable
&& EventSystemEx.Instance != null
&& !EventSystemEx.Instance.isLocked;
}
public override void OnPointerEnter(PointerEventData data)
{
if (Interaction != null && EventSystemEx.Instance != null)
EventSystemEx.Instance.OnPointerEnter(Interaction);
base.OnPointerEnter(data);
}
public override void OnPointerExit(PointerEventData data)
{
// 退出必须始终清理,否则旋转/细长 Collider 丢 Exit 时会卡住光标
if (Interaction != null && EventSystemEx.Instance != null)
EventSystemEx.Instance.OnPointerExit(Interaction);
base.OnPointerExit(data);
}
public override void OnPointerDown(PointerEventData eventData)
{
// 对话等场景 isLocked 时仍要让 EventTrigger 上注册的回调执行(如塔罗 PointerDown),
// 否则会出现能 Hover、但 Down/Up/Click 全不进组件的问题。
// 仅「开始」交互时受 isLocked / IsAvailable 门控;清理路径见 Up/EndDrag。
if (CanStartInteraction())
EventSystemEx.Instance.OnPointerDown(Interaction);
base.OnPointerDown(eventData);
}
public override void OnPointerUp(PointerEventData eventData)
{
// 松手必须始终清理 holding,否则充能结束开对话把 isLocked 置真后会永远卡在抓取光标
if (Interaction != null && EventSystemEx.Instance != null)
EventSystemEx.Instance.OnPointerUp(Interaction);
base.OnPointerUp(eventData);
}
public override void OnDrag(PointerEventData eventData)
{
if (CanStartInteraction())
{
EventSystemEx.Instance.OnDrag(Interaction);
base.OnDrag(eventData);
}
}
public override void OnEndDrag(PointerEventData eventData)
{
// 与 PointerUp 相同:清理不受 isLocked 门控
if (Interaction != null && EventSystemEx.Instance != null)
EventSystemEx.Instance.OnEndDrag(Interaction);
base.OnEndDrag(eventData);
}
public override void OnBeginDrag(PointerEventData eventData)
{
if (CanStartInteraction())
{
EventSystemEx.Instance.OnBeginDrag(Interaction);
base.OnBeginDrag(eventData);
}
}
public override void OnPointerClick(PointerEventData eventData)
{
if (CanStartInteraction())
{
// EventSystemEx.Instance.OnPointerClick(Interaction);
}
base.OnPointerClick(eventData);
}
void OnDestroy()
{
if (EventSystemEx.Instance != null && Interaction != null)
EventSystemEx.Instance.UnRegister(Interaction);
}
}
public interface IInteraction
{
// 判断是否激活,激活就正常显示鼠标,否则就显示禁用标志
public bool IsActive { get; }
// 判断是否可用,可用就正常显示鼠标,否则就保持原有标志不变
public bool IsAvailable { get; }
// 返回GameObject
public GameObject GetGameObject();
}
}