NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Framework/UI/DirectDragHandler.cs

341 lines
9.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using UnityEngine;
using UnityEngine.UI;
public class DirectDragHandler : MonoBehaviour
{
[Tooltip("是否在拖拽时限制移动范围")]
public bool restrictMovement = false;
[Tooltip("拖拽范围限制(如果启用限制)")]
public RectTransform movementBounds;
[Tooltip("是否锁定垂直方向移动")]
public bool lockVertical = false;
[Tooltip("是否锁定水平方向移动")]
public bool lockHorizontal = false;
[Tooltip("拖拽时是否改变视觉效果")]
public bool changeDragAppearance = true;
[Tooltip("拖拽时的缩放")]
public Vector3 dragScale = new Vector3(1.1f, 1.1f, 1.1f);
// 原始位置和缩放
private Vector3 originalPosition;
private Vector3 originalScale;
private RectTransform rectTransform;
private float scaleFactor;
// 拖拽状态
private bool isDragging = false;
[SerializeField]
private ButtonUpDrag buttonUpDrag;
private ScrollRect parentScrollRect;
/// <summary>
/// 检测拖拽位置是否可以放置
/// </summary>
private Func<Vector2, bool> checkValidFunction;
private Action onStartDrag;
private Action onEndDrag;
/// <summary>
/// 接收原始位置并返回调整后位置的函数
/// </summary>
private Func<Vector2, Vector2> positionAdjuster;
/// <summary>
/// 处理成功放置逻辑的函数
/// </summary>
private Action<Vector2> placementHandler;
/// <summary>
/// 处理拖拽过程中检测的函数
/// </summary>
private Action<Vector2> dragUpdateHandler;
/// <summary>
/// 拖拽按下事件处理器
/// </summary>
private Action onPointDownHandler;
/// <summary>
/// 拖拽松开事件处理器
/// </summary>
private Action onPointUpHandler;
/// <summary>
/// 是否启用拖拽功能
/// </summary>
private bool isDraggableEnabled = true;
private void Awake()
{
rectTransform = GetComponent<RectTransform>();
if (buttonUpDrag == null)
{
Debug.LogError("DirectDragHandler需要ButtonUpDrag组件!");
return;
}
// 注册长按事件
buttonUpDrag.AddLongPress(OnStartDrag);
buttonUpDrag.AddPointerDown(OnPointDown);
buttonUpDrag.AddPointerUp(OnPointUp);
}
public void Init(Func<Vector2, bool> checkValidFunction, Action onStartDrag, Action onEndDrag)
{
this.checkValidFunction = checkValidFunction;
this.onStartDrag = onStartDrag;
this.onEndDrag = onEndDrag;
// 查找父级ScrollRect
parentScrollRect = GetComponentInParent<ScrollRect>();
}
/// <summary>
/// 设置位置调整处理器
/// </summary>
/// <param name="positionAdjuster">接收原始位置并返回调整后位置的函数</param>
public void SetPositionAdjuster(Func<Vector2, Vector2> positionAdjuster)
{
this.positionAdjuster = positionAdjuster;
}
/// <summary>
/// 设置成功放置处理器
/// </summary>
/// <param name="placementHandler">处理成功放置逻辑的函数</param>
public void SetPlacementHandler(Action<Vector2> placementHandler)
{
this.placementHandler = placementHandler;
}
/// <summary>
/// 设置拖拽过程中的位置检测处理器
/// </summary>
/// <param name="dragUpdateHandler">在拖拽过程中处理位置检测的函数</param>
public void SetDragUpdateHandler(Action<Vector2> dragUpdateHandler)
{
this.dragUpdateHandler = dragUpdateHandler;
}
public void SetPointDownHandler(Action pointDownCallback, Action pointUpCallback)
{
this.onPointDownHandler = pointDownCallback;
this.onPointUpHandler = pointUpCallback;
}
/// <summary>
/// 启用或禁用拖拽功能
/// </summary>
public void SetDraggable(bool draggable)
{
this.isDraggableEnabled = draggable;
}
private void OnPointDown()
{
onPointDownHandler?.Invoke();
}
private void OnPointUp()
{
onPointUpHandler?.Invoke();
}
private void OnStartDrag()
{
if (!isDraggableEnabled)
return;
// 开始拖拽
isDragging = true;
scaleFactor = UIRoot.Instance.RootCanvas.GetComponent<RectTransform>().sizeDelta.x / Screen.width;
// 如果在ScrollRect中则暂时禁用它
if (parentScrollRect != null)
{
parentScrollRect.enabled = false;
}
originalPosition = rectTransform.position;
originalScale = rectTransform.localScale;
// 改变外观(如果启用)
if (changeDragAppearance)
{
rectTransform.localScale = dragScale;
}
// 注册移动和结束拖拽事件
InputManager.Instance.OnFingerMoveUI += UpdateDragPosition;
InputManager.Instance.OnFingerUpUI += EndDrag;
onStartDrag?.Invoke();
}
private void UpdateDragPosition(Vector2 delta)
{
if (!isDragging || !isDraggableEnabled)
return;
// 计算新位置(考虑偏移)
Vector2 newPosition = rectTransform.anchoredPosition + delta * scaleFactor;
// 应用方向锁定和边界限制逻辑...
// 使用自定义位置调整器(如果有)
if (positionAdjuster != null)
{
newPosition = positionAdjuster(newPosition);
}
// 更新位置
rectTransform.anchoredPosition = newPosition;
// 调用拖拽更新处理器
dragUpdateHandler?.Invoke(rectTransform.position);
}
private void EndDrag(Vector2 position)
{
if (!isDragging)
return;
isDragging = false;
// 恢复原始外观
if (changeDragAppearance)
{
rectTransform.localScale = originalScale;
}
// 处理拖拽结束逻辑
HandleDragEnd(rectTransform.position);//position
// 重新启用ScrollRect
if (parentScrollRect != null)
{
parentScrollRect.enabled = true;
}
// 清理事件监听
InputManager.Instance.OnFingerMoveUI -= UpdateDragPosition;
InputManager.Instance.OnFingerUpUI -= EndDrag;
onEndDrag?.Invoke();
}
private void HandleDragEnd(Vector2 position)
{
// 在这里实现放置逻辑
bool validPlacement = CheckValidPlacement(position);
if (validPlacement)
{
// 有效放置,执行相应逻辑
FinalizeItemPlacement(position);
}
}
private bool CheckValidPlacement(Vector2 position)
{
// 实现放置检测逻辑
// 这里只是示例,你需要根据具体需求实现
// 示例:使用射线检测
//var results = new System.Collections.Generic.List<UnityEngine.EventSystems.RaycastResult>();
//var eventData = new UnityEngine.EventSystems.PointerEventData(UnityEngine.EventSystems.EventSystem.current);
//eventData.position = position;
//UnityEngine.EventSystems.EventSystem.current.RaycastAll(eventData, results);
//
//foreach (var result in results)
//{
// // 检查是否是有效的放置目标
// // 例如:检查是否有特定的组件或标签
// if (result.gameObject.CompareTag("DropZone"))
// {
// return true;
// }
//}
//
// 默认返回true允许在任何位置放置
// 如果需要更严格的控制改为return false;
//return true;
if (checkValidFunction != null)
{
return checkValidFunction(position);
}
return false;
}
private void FinalizeItemPlacement(Vector2 position)
{
if (placementHandler != null)
{
placementHandler(position);
}
}
private void ReturnToOriginalPosition()
{
// 返回原始位置
// 可以使用动画或直接设置
// 直接设置:
// rectTransform.position = originalPosition;
// 使用动画效果:
//StartCoroutine(AnimateReturn());
rectTransform.position = originalPosition;
}
private System.Collections.IEnumerator AnimateReturn()
{
float duration = 0.3f;
float elapsed = 0f;
Vector3 startPos = rectTransform.position;
while (elapsed < duration)
{
rectTransform.position = Vector3.Lerp(startPos, originalPosition, elapsed / duration);
elapsed += Time.deltaTime;
yield return null;
}
rectTransform.position = originalPosition;
}
private void OnDestroy()
{
// 清理事件监听
if (InputManager.Instance != null)
{
InputManager.Instance.OnFingerMoveUI -= UpdateDragPosition;
InputManager.Instance.OnFingerUp -= EndDrag;
InputManager.Instance.OnFingerUpUI -= EndDrag;
}
}
// 可选:提供公共方法以在外部重置位置
public void ResetPosition()
{
rectTransform.position = originalPosition;
}
// 可选:提供公共方法以更新原始位置(例如在布局变化后)
public void UpdateOriginalPosition()
{
originalPosition = rectTransform.position;
}
}