Files
aibis-dream/Assets/Scripts/MiniGame/BlockPuzzle/Class/ShapeDragger.cs
T
2026-01-22 18:16:11 +08:00

170 lines
5.0 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 dragScale = 1.1f;
// 拖拽状态
private DragState _currentState = DragState.Idle;
private SnapResult _snapResult;
// 组件引用
private BlockShape _blockShape;
private EventTriggerEx _eventTrigger;
public DragState CurrentState => _currentState;
public bool IsDraggable { get => isDraggable; set => isDraggable = value; }
public IBlockPuzzleGrid TargetGrid => BlockPuzzleSystem.Instance.grid;
public IBlockShape BlockShape => _blockShape;
// 事件
public event Action<IBlockShape> OnDragStart;
public event Action<IBlockShape> OnDragUpdate;
public event Action<IBlockShape, bool> OnDragEnd;
private void Awake()
{
_blockShape = GetComponent<BlockShape>();
_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;
}
// 如果当前物体不在拖拽中则进入拖拽逻辑
if (_currentState == DragState.Idle || _currentState == DragState.Placed)
{
StartDrag();
}
// 如果当前物体在拖拽中则取消拖拽
else
{
EndDrag();
}
}
public void StartDrag()
{
if (!isDraggable) return;
// 如果原本就在网格中,则先移除
TargetGrid?.TryRemoveShapeFromGrid(_blockShape);
TargetGrid?.ResetPreviewGrid();
_currentState = DragState.Dragging;
// 处理层级和缩放
HandleDragStart();
OnDragStart?.Invoke(_blockShape);
}
private void HandleDragStart()
{
// 调整缩放和层级
transform.localScale = dragScale * Vector3.one;
}
public void CancelDrag()
{
throw new NotImplementedException();
}
public void EndDrag()
{
TargetGrid?.ResetPreviewGrid();
// 如果吸附到了就靠过去
if (_snapResult.canSnap)
{
_currentState = DragState.Placed;
transform.localScale = Vector3.one;
TargetGrid.TrySnapToGrid(_blockShape, _snapResult.RootCell);
// 处理Cursor
_eventTrigger.OnPointerUp(null);
OnDragEnd?.Invoke(_blockShape, _currentState == DragState.Placed);
}
// TODO: 无法吸附直接不处理
// else
// {
// _currentState = DragState.Idle;
// // transform.position = _originalPosition;
// transform.localScale = Vector3.one;
// // BlockPuzzleSystem.Instance.shapeRack.RecycleBlockShape(_blockShape);
// }
TargetGrid.GridVisualizer.UpdateAllCellsVisual();
}
public void UpdateDrag()
{
// 检测右键点击进行旋转(仅在拖动中)
if (Input.GetMouseButtonDown(1)) // 1 = 右键
{
_blockShape.RotateClockwise();
}
// 更新拖拽位置
transform.position = GetMouseWorldPosition() - _blockShape.GetCenterPosition();
// 进行Snap检查
_snapResult = TargetGrid.CheckSnapToGrid(_blockShape);
// 在网格显示预览
TargetGrid.ShowSnapPreview(_snapResult);
OnDragUpdate?.Invoke(_blockShape);
}
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;
}
}