using System; using AibisDream.Framework; using MeadowGames.UINodeConnect4.GraphicRenderer; using UnityEngine; using UnityEngine.EventSystems; namespace AibisDream { public class ShapeDragger : MonoBehaviour, IBlockShapeDragger, IInteraction { [Header("拖拽设置")] [SerializeField] private bool isDraggable = true; [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 _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 => BlockPuzzle.Instance.grid; } public IBlockShape BlockShape => _blockShape; // 事件 public event Action OnDragStart; public event Action OnDragUpdate; public event Action OnDragEnd; public event Action OnSnap; public event Action OnUnsnap; private void Awake() { _blockShape = GetComponent(); _spriteRenderer = GetComponent(); _eventTrigger = GetComponent(); _originalPosition = transform.position; 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(); } // 如果当前物体在拖拽中则取消拖拽 else { EndDrag(); } } public void StartDrag() { if (!isDraggable) return; // 如果原本就在网格中,则先移除 TargetGrid?.TryRemoveShapeFromGrid(_blockShape); _currentState = DragState.Dragging; // 处理层级和缩放 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; BlockPuzzle.Instance.shapeRack.RecycleBlockShape(_blockShape); } OnDragEnd?.Invoke(_blockShape, _currentState == DragState.Placed); } public void UpdateDrag() { // 检测右键点击进行旋转(仅在拖动中) if (Input.GetMouseButtonDown(1)) // 1 = 右键 { _blockShape.RotateClockwise(); } // 更新拖拽位置 transform.position = GetMouseWorldPosition() - _blockShape.GetCenterPosition(); // 进行Snap检查 _snapResult = TargetGrid.CheckSnapToGrid(_blockShape); // 在网格显示预览 TargetGrid.ShowSnapPreview(_snapResult.gridPositions); } /// /// 获取鼠标世界坐标 /// 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; } }