사용자 정보 모달, 드래그 리스트 개발
This commit is contained in:
210
Assets/Scripts/UVC/UI/List/Draggable/ListItemController.cs
Normal file
210
Assets/Scripts/UVC/UI/List/Draggable/ListItemController.cs
Normal file
@@ -0,0 +1,210 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UVC.UI.List.Draggable
|
||||
{
|
||||
/// <summary>
|
||||
/// 리스트 아이템의 드래그와 비주얼을 관리하는 컴포넌트입니다.
|
||||
/// DragBehavior와 함께 사용되어 드래그 시 시각적 효과를 처리합니다.
|
||||
///
|
||||
/// 필수 설정:
|
||||
/// 1. 이 컴포넌트가 있는 GameObject에 또는 자식에 DragBehavior를 함께 추가해야 합니다.
|
||||
/// 2. CanvasGroup이 없으면 자동으로 추가됩니다.
|
||||
///
|
||||
/// Inspector 설정:
|
||||
/// - Drag Alpha: 드래그 중 투명도 (0~1, 기본값 0.6)
|
||||
///
|
||||
/// 사용 예시:
|
||||
/// GameObject listItem = Instantiate(itemPrefab);
|
||||
/// listItem.AddComponent<DragBehavior>();
|
||||
/// listItem.AddComponent<ListItemController>();
|
||||
/// </summary>
|
||||
public class ListItemController : MonoBehaviour
|
||||
{
|
||||
// 컴포넌트 참조들
|
||||
private CanvasGroup? canvasGroup;
|
||||
private ListReorderHandler? reorderHandler;
|
||||
private GameObject? placeholder;
|
||||
|
||||
[Header("DragBehavior 설정")]
|
||||
[SerializeField]
|
||||
private DragBehavior? dragBehavior;
|
||||
|
||||
[Header("비주얼 설정")]
|
||||
[SerializeField, Range(0f, 1f)]
|
||||
[Tooltip("드래그 중일 때의 투명도 값입니다. 0은 완전 투명, 1은 완전 불투명")]
|
||||
private float dragAlpha = 0.6f;
|
||||
|
||||
/// <summary>
|
||||
/// 현재 생성된 플레이스홀더를 가져옵니다
|
||||
/// </summary>
|
||||
public GameObject? Placeholder => placeholder;
|
||||
|
||||
/// <summary>
|
||||
/// 원래 순서(인덱스)를 가져옵니다
|
||||
/// </summary>
|
||||
public int OriginalIndex => dragBehavior?.OriginalIndex ?? -1;
|
||||
|
||||
/// <summary>
|
||||
/// 컴포넌트 초기화 - Unity가 자동으로 호출
|
||||
/// </summary>
|
||||
void Awake()
|
||||
{
|
||||
// 필수 컴포넌트들을 가져옵니다
|
||||
if(dragBehavior == null)
|
||||
dragBehavior = GetComponentInChildren<DragBehavior>();
|
||||
|
||||
// CanvasGroup이 없으면 추가합니다 (알파값 조절을 위해 필요)
|
||||
canvasGroup = GetComponent<CanvasGroup>();
|
||||
if (canvasGroup == null)
|
||||
{
|
||||
canvasGroup = gameObject.AddComponent<CanvasGroup>();
|
||||
Debug.Log($"[ListItemController] CanvasGroup을 자동으로 추가했습니다 - {gameObject.name}");
|
||||
}
|
||||
|
||||
// 드래그 이벤트에 핸들러 메서드들을 연결합니다
|
||||
if (dragBehavior != null)
|
||||
{
|
||||
dragBehavior.OnDragStarted += HandleDragStart;
|
||||
dragBehavior.OnDragging += HandleDragging;
|
||||
dragBehavior.OnDragEnded += HandleDragEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"[ListItemController] DragBehavior를 찾을 수 없습니다! - {gameObject.name}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start는 Awake 이후에 호출되며, 다른 오브젝트의 컴포넌트를 찾을 때 사용
|
||||
/// </summary>
|
||||
void Start()
|
||||
{
|
||||
// 부모에서 ListReorderHandler를 찾습니다
|
||||
reorderHandler = GetComponentInParent<ListReorderHandler>();
|
||||
|
||||
if (reorderHandler == null)
|
||||
{
|
||||
Debug.LogWarning($"[ListItemController] ListReorderHandler를 찾을 수 없습니다. 재정렬 기능이 작동하지 않을 수 있습니다. - {gameObject.name}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드래그가 시작될 때 호출되는 핸들러
|
||||
/// </summary>
|
||||
private void HandleDragStart(PointerEventData eventData)
|
||||
{
|
||||
Debug.Log($"[ListItemController] 드래그 시작 처리 - {gameObject.name}");
|
||||
|
||||
// 1. 플레이스홀더(빈 공간 표시)를 생성합니다
|
||||
CreatePlaceholder();
|
||||
|
||||
// 2. 드래그 중인 아이템을 반투명하게 만듭니다
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
canvasGroup.alpha = dragAlpha;
|
||||
canvasGroup.blocksRaycasts = false; // 드래그 중에는 클릭을 받지 않습니다
|
||||
}
|
||||
|
||||
// 3. 아이템을 최상위 Canvas로 이동시켜 다른 UI 위에 표시되도록 합니다
|
||||
Canvas? rootCanvas = GetComponentInParent<Canvas>();
|
||||
if (rootCanvas != null)
|
||||
{
|
||||
transform.SetParent(rootCanvas.transform);
|
||||
transform.SetAsLastSibling(); // 가장 위에 표시
|
||||
}
|
||||
|
||||
// 4. 리오더 핸들러에 드래그 시작을 알립니다
|
||||
reorderHandler?.StartReorder(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 중일 때 계속 호출되는 핸들러
|
||||
/// </summary>
|
||||
private void HandleDragging(PointerEventData eventData)
|
||||
{
|
||||
// 리오더 핸들러가 현재 마우스 위치에서 적절한 드롭 위치를 계산하도록 합니다
|
||||
reorderHandler?.UpdateReorderPosition(this, eventData.position);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드래그가 끝날 때 호출되는 핸들러
|
||||
/// </summary>
|
||||
private void HandleDragEnd(PointerEventData eventData)
|
||||
{
|
||||
Debug.Log($"[ListItemController] 드래그 종료 처리 - {gameObject.name}");
|
||||
|
||||
// 1. 아이템을 원래 투명도로 복원합니다
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
canvasGroup.alpha = 1f;
|
||||
canvasGroup.blocksRaycasts = true; // 다시 클릭을 받을 수 있도록
|
||||
}
|
||||
|
||||
// 2. 리오더 핸들러가 최종 위치를 결정하도록 합니다
|
||||
reorderHandler?.EndReorder(this);
|
||||
|
||||
// 3. 플레이스홀더를 제거합니다
|
||||
if (placeholder != null)
|
||||
{
|
||||
Destroy(placeholder);
|
||||
placeholder = null;
|
||||
}
|
||||
|
||||
// 중요: 드래그 종료 후 새로운 위치 정보를 업데이트
|
||||
dragBehavior?.UpdatePositionInfo();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 플레이스홀더(빈 공간 표시용 오브젝트)를 생성합니다
|
||||
/// 드래그 중인 아이템이 원래 있던 자리를 표시하는 용도입니다
|
||||
/// </summary>
|
||||
private void CreatePlaceholder()
|
||||
{
|
||||
// 이미 플레이스홀더가 있다면 생성하지 않습니다
|
||||
if (placeholder != null) return;
|
||||
|
||||
// 새 GameObject를 만들어 플레이스홀더로 사용합니다
|
||||
placeholder = new GameObject("Placeholder");
|
||||
|
||||
// RectTransform 컴포넌트를 추가하고 설정합니다
|
||||
var rect = placeholder.AddComponent<RectTransform>();
|
||||
|
||||
if (dragBehavior?.OriginalParent != null)
|
||||
{
|
||||
rect.SetParent(dragBehavior.OriginalParent);
|
||||
rect.SetSiblingIndex(dragBehavior.OriginalIndex);
|
||||
|
||||
// 원본과 같은 크기로 설정합니다
|
||||
var originalRect = GetComponent<RectTransform>();
|
||||
if (originalRect != null)
|
||||
{
|
||||
rect.sizeDelta = originalRect.sizeDelta;
|
||||
}
|
||||
}
|
||||
|
||||
// 시각적으로 구분할 수 있도록 반투명한 회색 이미지를 추가합니다
|
||||
var image = placeholder.AddComponent<Image>();
|
||||
image.color = new Color(0.5f, 0.5f, 0.5f, 0.3f);
|
||||
|
||||
Debug.Log($"[ListItemController] 플레이스홀더 생성됨 - {gameObject.name}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 컴포넌트가 파괴될 때 이벤트 구독을 해제합니다
|
||||
/// </summary>
|
||||
void OnDestroy()
|
||||
{
|
||||
// 메모리 누수를 방지하기 위해 이벤트 구독을 해제합니다
|
||||
if (dragBehavior != null)
|
||||
{
|
||||
dragBehavior.OnDragStarted -= HandleDragStart;
|
||||
dragBehavior.OnDragging -= HandleDragging;
|
||||
dragBehavior.OnDragEnded -= HandleDragEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user