181 lines
5.9 KiB
C#
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;
|
|
}
|
|
}
|