138 lines
4.1 KiB
C#
138 lines
4.1 KiB
C#
using System;
|
||
using UnityEngine;
|
||
using UnityEngine.EventSystems;
|
||
|
||
// 为避免潜在的冲突和更清晰的逻辑,建议将类名稍作更改,以反映其新功能
|
||
// 例如:UIMouseBlocker,或者就保持 UIBlockCameraDrag 也可以,只要功能上能理解
|
||
public class UIBlockCameraDrag : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler
|
||
{
|
||
private const float DragThresholdPixels = 10f;
|
||
|
||
public static bool IsPointerOnUI = false;
|
||
public static bool ShouldBlockDrag = false;
|
||
public static bool MoveEvent = false;
|
||
public static bool DownUpEvent = false;
|
||
public static Vector3 PointerDownScreenPosition;
|
||
public static Vector3 ClickScreenPosition;
|
||
public static Vector3 DragOrigin;
|
||
public static Vector3 MoveVector;
|
||
private static UIBlockCameraDrag _activeBlocker;
|
||
|
||
private bool _isPointerInside;
|
||
|
||
//是否ban点击
|
||
public bool BanClick = false;
|
||
|
||
public static void ResetState()
|
||
{
|
||
IsPointerOnUI = false;
|
||
ShouldBlockDrag = false;
|
||
MoveEvent = false;
|
||
DownUpEvent = false;
|
||
PointerDownScreenPosition = Vector3.zero;
|
||
ClickScreenPosition = Vector3.zero;
|
||
DragOrigin = Vector3.zero;
|
||
MoveVector = Vector3.zero;
|
||
_activeBlocker = null;
|
||
}
|
||
|
||
private static Vector3 GetMouseWorldPosition()
|
||
{
|
||
var mainCamera = Camera.main;
|
||
return mainCamera == null ? Vector3.zero : mainCamera.ScreenToWorldPoint(Input.mousePosition);
|
||
}
|
||
|
||
private void ClearDragState()
|
||
{
|
||
if (_activeBlocker != null && _activeBlocker != this)
|
||
return;
|
||
|
||
if (_activeBlocker == this)
|
||
_activeBlocker = null;
|
||
|
||
ShouldBlockDrag = false;
|
||
MoveEvent = false;
|
||
DragOrigin = Vector3.zero;
|
||
MoveVector = Vector3.zero;
|
||
}
|
||
|
||
public void OnPointerEnter(PointerEventData eventData)
|
||
{
|
||
_isPointerInside = true;
|
||
IsPointerOnUI = true;
|
||
}
|
||
|
||
public void OnPointerExit(PointerEventData eventData)
|
||
{
|
||
_isPointerInside = false;
|
||
IsPointerOnUI = false;
|
||
ClearDragState();
|
||
}
|
||
|
||
public void OnPointerDown(PointerEventData eventData)
|
||
{
|
||
if (eventData.button == PointerEventData.InputButton.Left)
|
||
{
|
||
// OnPointerEnter may be missed after reconnect/reset if the cursor is already on this raycast target.
|
||
_isPointerInside = true;
|
||
IsPointerOnUI = true;
|
||
_activeBlocker = this;
|
||
ShouldBlockDrag = true;
|
||
MoveEvent = false;
|
||
PointerDownScreenPosition = eventData.position;
|
||
ClickScreenPosition = PointerDownScreenPosition;
|
||
DragOrigin = GetMouseWorldPosition();
|
||
MoveVector = Vector3.zero;
|
||
}
|
||
}
|
||
|
||
public void OnPointerUp(PointerEventData eventData)
|
||
{
|
||
if (eventData.button == PointerEventData.InputButton.Left)
|
||
{
|
||
if ((_activeBlocker == this || _isPointerInside) && !MoveEvent && !BanClick)
|
||
{
|
||
ClickScreenPosition = PointerDownScreenPosition;
|
||
DownUpEvent = true;
|
||
}
|
||
|
||
IsPointerOnUI = _isPointerInside;
|
||
ClearDragState();
|
||
}
|
||
}
|
||
|
||
private void OnDisable()
|
||
{
|
||
_isPointerInside = false;
|
||
if (_activeBlocker == this)
|
||
ResetState();
|
||
}
|
||
|
||
public void Update()
|
||
{
|
||
if (ShouldBlockDrag)
|
||
{
|
||
if (!MoveEvent)
|
||
{
|
||
var screenDelta = (Vector2)Input.mousePosition - (Vector2)PointerDownScreenPosition;
|
||
if (screenDelta.magnitude <= DragThresholdPixels)
|
||
{
|
||
MoveVector = Vector3.zero;
|
||
return;
|
||
}
|
||
|
||
MoveEvent = true;
|
||
DragOrigin = GetMouseWorldPosition();
|
||
MoveVector = Vector3.zero;
|
||
return;
|
||
}
|
||
|
||
MoveVector = DragOrigin - GetMouseWorldPosition();
|
||
if (MoveVector.sqrMagnitude <= Mathf.Epsilon)
|
||
{
|
||
MoveVector = Vector3.zero;
|
||
}
|
||
}
|
||
}
|
||
}
|