using System;
using UnityEngine;
using UnityEngine.EventSystems;
namespace UVC.UI
{
///
/// UI 요소를 마우스로 드래그하여 이동할 수 있게 만드는 컴포넌트입니다.
/// IBeginDragHandler, IDragHandler, IEndDragHandler 인터페이스를 구현하여 드래그 이벤트를 처리합니다.
/// 이 컴포넌트는 드래그될 UI 요소의 자식 오브젝트(예: 창의 헤더 영역)에 부착되어야 합니다.
///
///
/// 사용 예제:
/// 1. 드래그하고 싶은 창(Panel) UI를 만듭니다.
/// 2. 해당 창의 자식으로 드래그 핸들 역할을 할 UI(예: Image)를 만들고, 이 오브젝트에 `UIDragger` 컴포넌트를 추가합니다.
/// 3. 아래와 같은 컨트롤러 스크립트를 만들어 창에 추가하고, Inspector 창에서 `draggerHandle`과 `windowPanel`을 연결해줍니다.
///
/// using UnityEngine;
/// using UVC.UI;
///
///public class DraggableWindowController : MonoBehaviour
///{
/// [SerializeField] private UIDragger draggerHandle;
/// [SerializeField] private RectTransform customDragArea;
///
/// private void Start()
/// {
/// // 커스텀 드래그 영역 설정
/// if (customDragArea != null)
/// {
/// draggerHandle.SetDragArea(customDragArea);
/// }
///
/// // 이벤트 구독
/// draggerHandle.OnBeginDragHandler += OnDragStart;
/// draggerHandle.OnDragHandler += OnDragging;
/// draggerHandle.OnEndDragHandler += OnDragEnd;
///
/// // 창을 중앙으로 이동
/// draggerHandle.CenterInDragArea();
/// }
///
/// private void OnDragStart()
/// {
/// Debug.Log("창 드래그 시작!");
/// // 드래그 시작 시 추가 로직
/// }
///
/// private void OnDragging(Vector2 position)
/// {
/// // 드래그 중 실시간 처리
/// Debug.Log($"드래그 중: {position}");
/// }
///
/// private void OnDragEnd(Vector2 finalPosition)
/// {
/// Debug.Log($"드래그 완료! 최종 위치: {finalPosition}");
/// // 위치 저장 등의 후처리
/// }
///
/// // 런타임에서 드래그 기능 제어
/// public void ToggleDragging()
/// {
/// draggerHandle.SetDraggingEnabled(!draggerHandle.enabled);
/// }
///}
///
///
public class UIDragger : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
[Header("드래그 설정")]
[SerializeField]
[Tooltip("드래그 가능한 영역을 지정합니다. null인 경우 Canvas를 자동으로 찾습니다.")]
private RectTransform dragArea; // 드래그가 가능한 영역
[SerializeField]
[Tooltip("드래그할 UI 요소를 지정합니다. null인 경우 부모를 자동으로 설정합니다.")]
private RectTransform dragObject; // 실제로 드래그될 UI 요소 (예: 창 전체)
[SerializeField]
[Tooltip("드래그 시작 시 해당 UI 요소를 맨 앞으로 가져올지 여부를 설정합니다.")]
private bool bringToFrontOnDrag = true; // 드래그 시작 시 맨 앞으로 가져올지 여부
[Header("드래그 영역 여백")]
[SerializeField]
[Tooltip("드래그 영역 하단에 추가할 여백입니다.")]
private float bottomPadding = 0;
[SerializeField]
[Tooltip("드래그 영역 상단에 추가할 여백입니다.")]
private float topPadding = 0;
[SerializeField]
[Tooltip("드래그 영역 좌측에 추가할 여백입니다.")]
private float leftPadding = 0;
[SerializeField]
[Tooltip("드래그 영역 우측에 추가할 여백입니다.")]
private float rightPadding = 0;
[SerializeField]
[Tooltip("드래그 중 실시간으로 영역 제한을 적용할지 여부")]
private bool constrainDuringDrag = true;
// 이벤트
public Action OnBeginDragHandler { get; set; }
public Action OnDragHandler { get; set; }
public Action OnEndDragHandler { get; set; }
// 캐시된 변수들
private Vector2 originalLocalPointerPosition;
private Vector2 originalAnchoredPosition;
private int originalSiblingIndex;
private Canvas parentCanvas;
private Camera canvasCamera;
// 프로퍼티
public RectTransform DragObject => dragObject;
public RectTransform DragArea => dragArea;
public bool IsDragging { private set; get; }
private void Start()
{
InitializeComponents();
ValidateSetup();
}
///
/// 컴포넌트들을 초기화합니다.
///
private void InitializeComponents()
{
// dragObject가 설정되지 않았다면, 부모를 드래그 대상으로 설정
if (dragObject == null)
{
dragObject = transform.parent as RectTransform;
}
// Canvas와 Camera 캐싱
parentCanvas = GetComponentInParent