Files
aibis-dream/Assets/Scripts/MiniGame/BlockPuzzle/Class/ShapeDragger.cs
T
2025-12-01 20:44:20 +08:00

181 lines
5.9 KiB
C#

using System;
using AibisDream.Framework;
using UnityEngine;
using UnityEngine.EventSystems;
namespace AibisDream
{
public class ShapeDragger : MonoBehaviour, IBlockShapeDragger, IInteraction
{
[Header("拖拽设置")]
[SerializeField] private bool isDraggable = true;
[SerializeField] private float snapDistance = 0.5f;
[SerializeField] private BlockPuzzleGrid targetGrid;
[Header("视觉反馈")]
[SerializeField] private Color snapColor = new Color(0f, 1f, 0f, 0.7f);
[SerializeField] private Color invalidColor = new Color(1f, 0f, 0f, 0.7f);
[SerializeField] private Color normalColor = Color.white;
[SerializeField] private float dragScale = 1.1f;
// 拖拽状态
private DragState _currentState = DragState.Idle;
private Vector3 _dragOffset;
private Vector3 _originalPosition;
private Vector3 _originalScale;
private int _originalSortingOrder;
private SnapResult _snapResult;
// 组件引用
private BlockShape _blockShape;
private SpriteRenderer _spriteRenderer;
private EventTriggerEx _eventTrigger;
public DragState CurrentState => _currentState;
public bool IsDraggable { get => isDraggable; set => isDraggable = value; }
public IBlockPuzzleGrid TargetGrid { get => targetGrid; set => targetGrid = value as BlockPuzzleGrid; }
public float SnapDistance { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
// 事件
public event Action<IBlockShape> OnDragStart;
public event Action<IBlockShape, Vector3> OnDragUpdate;
public event Action<IBlockShape, bool> OnDragEnd;
public event Action<IBlockShape, Vector3, int, int> OnSnap;
public event Action<IBlockShape> OnUnsnap;
private void Awake()
{
_blockShape = GetComponent<BlockShape>();
_spriteRenderer = GetComponent<SpriteRenderer>();
_eventTrigger = GetComponent<EventTriggerEx>();
RegisterEvent();
}
private void OnDestroy()
{
_eventTrigger.UnRegister(EventTriggerType.PointerClick, OnPointerClick);
}
private void RegisterEvent()
{
_eventTrigger.Register(EventTriggerType.PointerClick, OnPointerClick);
// _eventTrigger.Register(EventTriggerType.PointerDown, OnPointerDown);
// _eventTrigger.Register(EventTriggerType.PointerUp, OnPointerUp);
}
private void Update()
{
if (_currentState == DragState.Dragging)
{
UpdateDrag();
}
}
private void OnPointerClick(BaseEventData eventData)
{
if (eventData is not PointerEventData { button: PointerEventData.InputButton.Left })
{
return;
}
Vector3 mouseWorldPos = GetMouseWorldPosition(eventData);
// 如果当前物体不在拖拽中则进入拖拽逻辑
if (_currentState == DragState.Idle || _currentState == DragState.Placed)
{
StartDrag(mouseWorldPos);
}
// 如果当前物体在拖拽中则取消拖拽
else
{
EndDrag();
}
}
public void StartDrag(Vector3 mouseWorldPos)
{
if (!isDraggable) return;
_currentState = DragState.Dragging;
_originalPosition = transform.position;
// 计算拖拽偏移量
_dragOffset = transform.position - mouseWorldPos;
// 处理层级和缩放
HandleDragStart();
OnDragStart?.Invoke(_blockShape);
}
private void HandleDragStart()
{
// 调整缩放和层级
transform.localScale = dragScale * Vector3.one;
}
public void CancelDrag()
{
throw new NotImplementedException();
}
public void EndDrag()
{
// 如果吸附到了就靠过去
if (_snapResult.canSnap)
{
_currentState = DragState.Placed;
transform.localScale = Vector3.one;
TargetGrid.TrySnapToGrid(_blockShape, _snapResult.RootCell);
}
else
{
_currentState = DragState.Idle;
transform.position = _originalPosition;
transform.localScale = Vector3.one;
}
OnDragEnd?.Invoke(_blockShape, _currentState == DragState.Placed);
}
public void UpdateDrag()
{
// 更新拖拽位置
transform.position = GetMouseWorldPosition() + _dragOffset;
// 进行Snap检查
_snapResult = TargetGrid.CheckSnapToGrid(_blockShape);
// 在网格显示预览
TargetGrid.ShowSnapPreview(_snapResult.gridPositions);
}
/// <summary>
/// 获取鼠标世界坐标
/// </summary>
private Vector3 GetMouseWorldPosition(BaseEventData eventData)
{
Vector3 mouseWorldPos;
if (eventData is not PointerEventData pointerEventData)
{
mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
else
{
mouseWorldPos = Camera.main.ScreenToWorldPoint(pointerEventData.position);
}
return new Vector3(mouseWorldPos.x, mouseWorldPos.y, 0);
}
private Vector3 GetMouseWorldPosition()
{
var mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
return new Vector3(mouseWorldPos.x, mouseWorldPos.y, 0);
}
// 实现IInteraction接口
public bool IsActive => true;
public bool IsAvailable => true;
public GameObject GetGameObject() => gameObject;
}
}