버그 수정 중. 이동 후 남겨지는 경우가 있음
This commit is contained in:
@@ -9,74 +9,57 @@ namespace UVC.UI.List.Tree
|
||||
/// TreeListItem의 드래그 & 드롭 입력을 처리하는 컴포넌트입니다.
|
||||
///
|
||||
/// 역할:
|
||||
/// 1. 마우스 입력 감지 (클릭, 드래그)
|
||||
/// 2. 드래그 시각 피드백 (알파값 변경, 오프셋 이동)
|
||||
/// 3. 드롭 대상 판단 (마우스 위치 기반)
|
||||
/// 4. 드래그 매니저에 이벤트 전달
|
||||
/// 1) 마우스 입력 처리: 드래그 시작/진행/종료
|
||||
/// 2) 드래그 시각 피드백: 알파 변경, 드롭 위치 표시기 갱신
|
||||
/// 3) 마우스 위치 기반 드롭 대상 탐색 및 드롭 위치 판정
|
||||
/// 4) 드래그 매니저(TreeListDragDropManager)와 이벤트 연동
|
||||
///
|
||||
/// 구조:
|
||||
/// - PointerDown: 마우스 클릭 감지 → 드래그 시작 준비
|
||||
/// - Drag: 마우스 이동 중 → 드래그 진행, 시각 피드백
|
||||
/// - PointerUp: 마우스 해제 → 드롭 처리
|
||||
/// 이벤트 흐름(IBeginDragHandler/IDragHandler/IEndDragHandler):
|
||||
/// - OnBeginDrag: 드래그 시작 준비(안전성 검증, 오프셋 계산)
|
||||
/// - OnDrag: 최초 드래그 프레임에 StartDrag, DropIndicator 생성/갱신
|
||||
/// - OnEndDrag: 알파/레이캐스트 복구, DropIndicator 숨김, TryDrop 수행
|
||||
///
|
||||
/// 시각 피드백:
|
||||
/// - CanvasGroup.alpha를 일시적으로 낮춰 드래그 중임을 표시
|
||||
/// - DropIndicator(얇은 선 또는 블록)로 삽입 위치/자식 투입 위치를 표시
|
||||
/// </summary>
|
||||
public class TreeListItemDragHandler : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// 부모 TreeListItem입니다.
|
||||
/// </summary>
|
||||
/// <summary>부모 TreeListItem.</summary>
|
||||
private TreeListItem? treeListItem;
|
||||
|
||||
/// <summary>
|
||||
/// 부모 TreeList입니다.
|
||||
/// </summary>
|
||||
/// <summary>부모 TreeList.</summary>
|
||||
private TreeList? treeList;
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 & 드롭 매니저입니다.
|
||||
/// </summary>
|
||||
/// <summary>드래그 & 드롭 매니저.</summary>
|
||||
private TreeListDragDropManager? dragDropManager;
|
||||
|
||||
private RectTransform? rectTransform;
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 중 시각 피드백을 위한 CanvasGroup입니다.
|
||||
/// </summary>
|
||||
/// <summary>드래그 시각 피드백용 CanvasGroup.</summary>
|
||||
private CanvasGroup? canvasGroup;
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 시작 시 원본 알파값입니다.
|
||||
/// </summary>
|
||||
/// <summary>드래그 시작 전 원본 알파값.</summary>
|
||||
private float originalAlpha = 1f;
|
||||
|
||||
private Vector2 dragOffset = Vector2.zero;
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 중 적용할 알파값입니다.
|
||||
/// </summary>
|
||||
/// <summary>드래그 중 적용할 알파값.</summary>
|
||||
[SerializeField]
|
||||
private float dragAlpha = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 활성화 여부입니다.
|
||||
/// </summary>
|
||||
/// <summary>드래그 활성화 여부.</summary>
|
||||
[SerializeField]
|
||||
private bool enableDragDrop = true;
|
||||
|
||||
/// <summary>
|
||||
/// 드롭 위치 표시 막대 프리팹입니다.
|
||||
/// </summary>
|
||||
/// <summary>드롭 위치 표시 라인/블록.</summary>
|
||||
private Image? dropIndicator;
|
||||
private RectTransform? dropIndicatorRect;
|
||||
|
||||
/// <summary>
|
||||
/// 드롭 표시기의 부모 (Content 또는 EntryRoot)
|
||||
/// </summary>
|
||||
/// <summary>드롭 표시기의 부모(RectTransform).</summary>
|
||||
private RectTransform? dropIndicatorParent;
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 시작 시 아이템의 원본 부모입니다.
|
||||
/// 드래그 후 원래 위치로 복구할 때 사용합니다.
|
||||
/// </summary>
|
||||
/// <summary>드래그 시작 시의 원본 부모/순서.</summary>
|
||||
private Transform? originalParent;
|
||||
private int originalSiblingIndex;
|
||||
|
||||
@@ -95,6 +78,12 @@ namespace UVC.UI.List.Tree
|
||||
originalAlpha = canvasGroup.alpha;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 외부에서 드래그 매니저 및 상위 컨텍스트를 주입합니다.
|
||||
/// </summary>
|
||||
/// <param name="item">이 핸들러가 속한 아이템.</param>
|
||||
/// <param name="list">아이템 컨테이너(TreeList).</param>
|
||||
/// <param name="manager">드래그 & 드롭 매니저.</param>
|
||||
public void SetDragDropManager(TreeListItem item, TreeList list, TreeListDragDropManager manager)
|
||||
{
|
||||
treeListItem = item;
|
||||
@@ -105,9 +94,10 @@ namespace UVC.UI.List.Tree
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드래그가 시작될 때 호출됩니다. (IBeginDragHandler)
|
||||
/// OnPointerDown 이후 마우스가 약간 움직이면 자동으로 호출됩니다.
|
||||
/// 드래그가 시작될 때 호출됩니다.
|
||||
/// OnPointerDown 이후 마우스가 임계치 이상 이동하면 자동 호출됩니다.
|
||||
/// </summary>
|
||||
/// <param name="eventData">포인터 이벤트 데이터.</param>
|
||||
public void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
Debug.Log($"[OnPointerDown]");
|
||||
@@ -122,9 +112,9 @@ namespace UVC.UI.List.Tree
|
||||
return;
|
||||
}
|
||||
|
||||
// 드래그 시작 준비: 마우스 위치와 아이템 위치의 오프셋 계산
|
||||
// 마우스 위치의 로컬 좌표 저장(필요 시 Y 오프셋 계산에 사용)
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
treeListRootParent,//rectTransform,
|
||||
treeListRootParent,
|
||||
eventData.position,
|
||||
null,
|
||||
out var localPoint);
|
||||
@@ -135,8 +125,10 @@ namespace UVC.UI.List.Tree
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 중에 마우스가 이동할 때 호출됩니다. (IDragHandler)
|
||||
/// 드래그 중 프레임마다 호출됩니다.
|
||||
/// 최초 1프레임에 드래그 상태 진입 및 표시기 생성, 이후 hover 대상/표시기 갱신을 수행합니다.
|
||||
/// </summary>
|
||||
/// <param name="eventData">포인터 이벤트 데이터.</param>
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!enableDragDrop || dragDropManager == null || treeListItem?.Data == null || treeList == null || rectTransform == null)
|
||||
@@ -152,16 +144,16 @@ namespace UVC.UI.List.Tree
|
||||
|
||||
Debug.Log($"[OnDrag] {treeListItem.Data.Name} 드래그 중");
|
||||
|
||||
// 드래그 시작 처리 (첫 드래그 프레임)
|
||||
// 최초 드래그 프레임: 드래그 상태 진입 및 시각 피드백/표시기 준비
|
||||
if (!dragDropManager.IsDragging)
|
||||
{
|
||||
dragDropManager.StartDrag(treeListItem.Data);
|
||||
|
||||
// 원본 부모와 위치 저장
|
||||
// 원본 부모/순서 저장
|
||||
originalParent = rectTransform.parent;
|
||||
originalSiblingIndex = rectTransform.GetSiblingIndex();
|
||||
|
||||
// 드래그 중 시각 피드백
|
||||
// 시각 피드백(투명도/레이캐스트)
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
canvasGroup.alpha = dragAlpha;
|
||||
@@ -174,21 +166,22 @@ namespace UVC.UI.List.Tree
|
||||
Debug.Log($"[OnDrag] {treeListItem.Data.Name} 드래그 시작");
|
||||
}
|
||||
|
||||
// 아이템이 마우스를 따라다니도록 위치 업데이트
|
||||
// 필요 시 실제 UI를 마우스를 따라 이동시키려면 아래 호출을 활성화
|
||||
//UpdateDragPosition(eventData);
|
||||
|
||||
// 마우스 위의 드롭 대상 찾기
|
||||
var targetItem = GetItemAtMousePosition(eventData.position);
|
||||
dragDropManager.OnDragOver(targetItem?.Data);
|
||||
|
||||
// 드롭 위치 표시 업데이트
|
||||
// 드롭 위치 표시 갱신(위/아래/자식)
|
||||
UpdateDropIndicator(targetItem);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드래그가 종료될 때 호출됩니다. (IEndDragHandler)
|
||||
/// 마우스 버튼을 놓으면 자동으로 호출됩니다.
|
||||
/// 드래그가 종료될 때 호출됩니다(마우스 버튼 해제).
|
||||
/// 상태/시각 피드백 복구 후 TryDrop을 수행합니다.
|
||||
/// </summary>
|
||||
/// <param name="eventData">포인터 이벤트 데이터.</param>
|
||||
public void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
Debug.Log($"[OnPointerUp]");
|
||||
@@ -206,7 +199,7 @@ namespace UVC.UI.List.Tree
|
||||
canvasGroup.blocksRaycasts = true;
|
||||
}
|
||||
|
||||
// 원본 부모로 복구 (드래그 중 이동했던 위치 복구)
|
||||
// 원본 부모/순서 복구(드래그 중 시각 이동을 되돌림)
|
||||
if (originalParent != null)
|
||||
{
|
||||
rectTransform?.SetParent(originalParent);
|
||||
@@ -230,17 +223,13 @@ namespace UVC.UI.List.Tree
|
||||
var targetItem = GetItemAtMousePosition(eventData.position);
|
||||
|
||||
|
||||
// 드롭 시도
|
||||
// 드롭 시도 및 성공 시 데이터 동기화
|
||||
if (treeListItem?.Data != null)
|
||||
{
|
||||
var result = dragDropManager.TryDrop(targetItem?.Data);
|
||||
Debug.Log($"[OnPointerUp] 드롭 결과: {(result ? "성공" : "실패")}");
|
||||
|
||||
if (result)
|
||||
{
|
||||
// 드롭 성공 → 데이터 동기화
|
||||
HandleDropSuccess(treeListItem.Data, targetItem);
|
||||
}
|
||||
if (result) HandleDropSuccess(treeListItem.Data, targetItem);
|
||||
}
|
||||
|
||||
dragDropManager.EndDrag();
|
||||
@@ -248,8 +237,9 @@ namespace UVC.UI.List.Tree
|
||||
|
||||
/// <summary>
|
||||
/// 드래그 중 아이템이 마우스를 따라다니도록 위치를 업데이트합니다.
|
||||
/// Y축만 이동 (X축은 고정)
|
||||
/// Y축만 이동(X축 고정).
|
||||
/// </summary>
|
||||
/// <param name="eventData">포인터 이벤트 데이터.</param>
|
||||
private void UpdateDragPosition(PointerEventData eventData)
|
||||
{
|
||||
if (rectTransform == null || treeList == null)
|
||||
@@ -281,7 +271,7 @@ namespace UVC.UI.List.Tree
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드롭 위치 표시 막대를 생성합니다.
|
||||
/// 드롭 위치 표시기(DropIndicator)를 생성하거나 재사용합니다.
|
||||
/// </summary>
|
||||
private void CreateDropIndicator()
|
||||
{
|
||||
@@ -340,9 +330,11 @@ namespace UVC.UI.List.Tree
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드롭 위치 표시 막대를 업데이트합니다.
|
||||
/// VerticalLayoutGroup 환경에서도 정확하게 위치를 계산합니다.
|
||||
/// 드롭 위치 표시기를 갱신합니다.
|
||||
/// 복잡도: 대상 RectTransform의 월드 코너를 부모 기준 로컬 좌표로 환산하여,
|
||||
/// 위/아래/자식(블록) 위치를 정확히 계산합니다.
|
||||
/// </summary>
|
||||
/// <param name="targetItem">현재 마우스 아래의 대상 아이템(null이면 숨김).</param>
|
||||
private void UpdateDropIndicator(TreeListItem? targetItem)
|
||||
{
|
||||
if (dropIndicator == null || dropIndicatorRect == null || dropIndicatorParent == null)
|
||||
@@ -437,7 +429,7 @@ namespace UVC.UI.List.Tree
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드롭 위치 표시 막대를 숨깁니다.
|
||||
/// 드롭 위치 표시기를 숨깁니다.
|
||||
/// </summary>
|
||||
private void HideDropIndicator()
|
||||
{
|
||||
@@ -448,9 +440,9 @@ namespace UVC.UI.List.Tree
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// treeListRootParent의 자식 중에서 "DropIndicator"라는 이름의 GameObject를 찾습니다.
|
||||
/// treeListRootParent의 직접 자식 중 "DropIndicator" GameObject를 찾습니다.
|
||||
/// </summary>
|
||||
/// <returns>찾은 GameObject (없으면 null)</returns>
|
||||
/// <returns>찾은 GameObject. 없으면 null.</returns>
|
||||
private GameObject? FindDropIndicatorInRoot()
|
||||
{
|
||||
if (treeListRootParent == null)
|
||||
@@ -477,10 +469,10 @@ namespace UVC.UI.List.Tree
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 주어진 스크린 좌표에 있는 TreeListItem을 찾습니다.
|
||||
/// 스크린 좌표에 위치한 TreeListItem을 찾습니다.
|
||||
/// </summary>
|
||||
/// <param name="screenPosition">스크린 좌표</param>
|
||||
/// <returns>찾은 TreeListItem (없으면 null)</returns>
|
||||
/// <param name="screenPosition">스크린 좌표.</param>
|
||||
/// <returns>찾은 TreeListItem. 없으면 null.</returns>
|
||||
private TreeListItem? GetItemAtMousePosition(Vector2 screenPosition)
|
||||
{
|
||||
if (treeList == null)
|
||||
@@ -514,10 +506,11 @@ namespace UVC.UI.List.Tree
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 드롭 성공 후 데이터를 동기화합니다.
|
||||
/// 드롭 성공 후 데이터 구조를 갱신합니다.
|
||||
/// 루트 드롭/형제 간 이동/자식으로 이동 등을 처리합니다.
|
||||
/// </summary>
|
||||
/// <param name="draggedData">드래그된 아이템</param>
|
||||
/// <param name="targetItem">드롭 대상 UI 아이템</param>
|
||||
/// <param name="draggedData">드래그한 데이터.</param>
|
||||
/// <param name="targetItem">드롭 대상 UI 아이템(null: 루트로 드롭).</param>
|
||||
private void HandleDropSuccess(TreeListItemData? draggedData, TreeListItem? targetItem)
|
||||
{
|
||||
if (draggedData == null || treeList == null)
|
||||
@@ -567,10 +560,11 @@ namespace UVC.UI.List.Tree
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 드롭 위치를 판단합니다.
|
||||
/// 대상 RectTransform 내 마우스 Y 위치로 위/아래/자식 드롭 위치를 판정합니다.
|
||||
/// 상/하 30% → 위/아래, 중간 40% → 자식.
|
||||
/// </summary>
|
||||
/// <param name="targetRect">대상 아이템의 RectTransform</param>
|
||||
/// <returns>드롭 위치</returns>
|
||||
/// <param name="targetRect">대상 아이템 RectTransform.</param>
|
||||
/// <returns>드롭 위치.</returns>
|
||||
private DropPosition GetDropPosition(RectTransform targetRect)
|
||||
{
|
||||
// 목표: 마우스 Y 위치를 기반으로 위/아래/안쪽 판단
|
||||
@@ -610,18 +604,13 @@ namespace UVC.UI.List.Tree
|
||||
|
||||
/// <summary>
|
||||
/// 아이템을 루트 레벨로 이동합니다.
|
||||
/// 이미 루트면 순서만 변경합니다.
|
||||
/// </summary>
|
||||
/// <param name="draggedData">드래그된 데이터.</param>
|
||||
private void MoveToRoot(TreeListItemData draggedData)
|
||||
{
|
||||
// 기존 부모에서 제거
|
||||
//RemoveFromParent(draggedData);
|
||||
Debug.Log($"[MoveToRoot] {draggedData.Name}을(를) 루트로 이동");
|
||||
|
||||
// ✅ 루트 레벨에 추가
|
||||
// TreeList의 Root는 직접 자식들을 포함하는 컨테이너
|
||||
// Root의 자식 TreeListItem들이 실제 루트 레벨 아이템
|
||||
// 데이터 구조에서 루트 아이템을 찾기 위해 모든 루트 아이템들을 순회
|
||||
//
|
||||
if (treeList == null)
|
||||
{
|
||||
return;
|
||||
@@ -633,174 +622,173 @@ namespace UVC.UI.List.Tree
|
||||
return;
|
||||
}
|
||||
|
||||
// 1️. 현재 마우스 위치(드래그 대상)를 기반으로 루트 아이템의 인덱스 계산
|
||||
// 2️. AddItemAt()을 호출하여 정확한 위치에 아이템 추가
|
||||
|
||||
// 루트 아이템 중 마우스 위의 아이템 찾기
|
||||
var targetItem = GetItemAtMousePosition(Input.mousePosition);
|
||||
|
||||
if (targetItem != null && targetItem.Data != null)
|
||||
if (draggedData.Parent == null)
|
||||
{
|
||||
// 드롭 위치 판단
|
||||
var dropPosition = GetDropPosition(targetItem.GetComponent<RectTransform>());
|
||||
var targetData = targetItem.Data;
|
||||
|
||||
// 대상 아이템이 루트 레벨의 아이템인지 확인
|
||||
if (targetData.Parent == null)
|
||||
{
|
||||
// 루트 레벨 아이템이라면 해당 위치에 삽입
|
||||
int targetIndex = treeList.Items.IndexOf(targetData);
|
||||
|
||||
if (targetIndex >= 0)
|
||||
{
|
||||
// Above: 대상 아이템 앞에 삽입
|
||||
if (dropPosition == DropPosition.Above)
|
||||
{
|
||||
treeList.AddItemAt(draggedData, targetIndex);
|
||||
}
|
||||
// Below: 대상 아이템 뒤에 삽입
|
||||
else if (dropPosition == DropPosition.Below)
|
||||
{
|
||||
treeList.AddItemAt(draggedData, targetIndex + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// InsideAsChild: 루트 레벨에서는 아래에 추가
|
||||
treeList.AddItemAt(draggedData, targetIndex + 1);
|
||||
}
|
||||
|
||||
Debug.Log($"[MoveToRoot] {draggedData.Name}을(를) 루트 레벨의 인덱스 {targetIndex}에 추가");
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 이미 루트 레벨인 경우 순서만 변경
|
||||
treeList.Items.Remove(draggedData);
|
||||
treeList.SwapItem(draggedData, treeList.Items.Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 루트 레벨에 아이템이 없거나 유효한 위치를 찾지 못한 경우 끝에 추가
|
||||
treeList.AddCloneItem(draggedData);
|
||||
}
|
||||
|
||||
// 루트 레벨에 아이템이 없거나 유효한 위치를 찾지 못한 경우 끝에 추가
|
||||
treeList.AddItem(draggedData);
|
||||
Debug.Log($"[MoveToRoot] {draggedData.Name}을(를) 루트 레벨의 끝에 추가");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 아이템을 다른 아이템의 자식으로 이동합니다.
|
||||
/// 아이템을 대상의 자식으로 이동합니다.
|
||||
/// </summary>
|
||||
/// <param name="draggedData">이동할 데이터.</param>
|
||||
/// <param name="targetData">대상 데이터.</param>
|
||||
private void MoveAsChild(TreeListItemData draggedData, TreeListItemData targetData)
|
||||
{
|
||||
//RemoveFromParent(draggedData);
|
||||
targetData.AddChild(draggedData);
|
||||
targetData.AddCloneChild(draggedData);
|
||||
Debug.Log($"[MoveAsChild] {draggedData.Name}을(를) {targetData.Name}의 자식으로 이동");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 아이템을 다른 아이템 앞으로 이동합니다.
|
||||
/// 아이템을 대상 앞(위)으로 이동합니다.
|
||||
/// 같은 부모면 재정렬, 다르면 부모 교체 후 삽입합니다.
|
||||
/// </summary>
|
||||
/// <param name="draggedData">이동할 데이터.</param>
|
||||
/// <param name="targetData">기준 데이터.</param>
|
||||
private void MoveBefore(TreeListItemData draggedData, TreeListItemData targetData)
|
||||
{
|
||||
var parentData = targetData.Parent;// FindParentOfItem(targetData);
|
||||
//RemoveFromParent(draggedData);
|
||||
|
||||
if (parentData != null)
|
||||
//부모가 같은 경우 순서만 변경
|
||||
if (draggedData.Parent == targetData.Parent)
|
||||
{
|
||||
var targetIndex = parentData.Children.IndexOf(targetData);
|
||||
if (targetIndex >= 0)
|
||||
if (draggedData.Parent != null)
|
||||
{
|
||||
parentData.AddChildAt(draggedData, targetIndex); // 자식으로 추가
|
||||
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 이동");
|
||||
var draggedIndex = draggedData.Parent.Children.IndexOf(draggedData);
|
||||
draggedData.Parent.Children.Remove(draggedData);
|
||||
var targetIndex = draggedData.Parent.Children.IndexOf(targetData);
|
||||
if (targetIndex >= 0)
|
||||
{
|
||||
draggedData.Parent.SwapChild(draggedData, targetIndex);
|
||||
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 순서 변경");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var treeListItems = treeList?.Items;
|
||||
if (treeListItems != null)
|
||||
{
|
||||
treeListItems.Remove(draggedData);
|
||||
var targetIndex = treeListItems.IndexOf(targetData);
|
||||
if (targetIndex >= 0)
|
||||
{
|
||||
treeList?.SwapItem(draggedData, targetIndex);
|
||||
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 순서 변경(루트레벨)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 루트 레벨인 경우
|
||||
var treeListItems = treeList?.Items;
|
||||
if (treeListItems != null)
|
||||
|
||||
var parentData = targetData.Parent;// FindParentOfItem(targetData);
|
||||
//RemoveFromParent(draggedData);
|
||||
if (parentData != null)
|
||||
{
|
||||
var targetIndex = treeListItems.IndexOf(targetData);
|
||||
var targetIndex = parentData.Children.IndexOf(targetData);
|
||||
if (targetIndex >= 0)
|
||||
{
|
||||
treeList?.AddItemAt(draggedData, targetIndex);
|
||||
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 이동 (루트 레벨)");
|
||||
parentData.AddCloneAtChild(draggedData, targetIndex); // 자식으로 추가
|
||||
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 이동");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 루트 레벨인 경우
|
||||
var treeListItems = treeList?.Items;
|
||||
if (treeListItems != null)
|
||||
{
|
||||
var targetIndex = treeListItems.IndexOf(targetData);
|
||||
if (targetIndex >= 0)
|
||||
{
|
||||
treeList?.AddCloneItemAt(draggedData, targetIndex);
|
||||
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 이동 (루트 레벨)");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 아이템을 다른 아이템 뒤로 이동합니다.
|
||||
/// 아이템을 대상 뒤(아래)로 이동합니다.
|
||||
/// 같은 부모면 재정렬, 다르면 부모 교체 후 삽입합니다.
|
||||
/// </summary>
|
||||
/// <param name="draggedData">이동할 데이터.</param>
|
||||
/// <param name="targetData">기준 데이터.</param>
|
||||
private void MoveAfter(TreeListItemData draggedData, TreeListItemData targetData)
|
||||
{
|
||||
var parentData = targetData.Parent;
|
||||
//RemoveFromParent(draggedData);
|
||||
|
||||
if (parentData != null)
|
||||
//부모가 같은 경우 순서만 변경
|
||||
if (draggedData.Parent == targetData.Parent)
|
||||
{
|
||||
var targetIndex = parentData.Children.IndexOf(targetData);
|
||||
if (targetIndex >= 0)
|
||||
if (draggedData.Parent != null)
|
||||
{
|
||||
parentData.AddChildAt(draggedData, targetIndex + 1);
|
||||
Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 이동");
|
||||
var draggedIndex = draggedData.Parent.Children.IndexOf(draggedData);
|
||||
draggedData.Parent.Children.Remove(draggedData);
|
||||
var targetIndex = draggedData.Parent.Children.IndexOf(targetData);
|
||||
if (targetIndex >= 0)
|
||||
{
|
||||
draggedData.Parent.SwapChild(draggedData, targetIndex + 1);
|
||||
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 순서 변경");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var treeListItems = treeList?.Items;
|
||||
if (treeListItems != null)
|
||||
{
|
||||
treeListItems.Remove(draggedData);
|
||||
var targetIndex = treeListItems.IndexOf(targetData);
|
||||
if (targetIndex >= 0)
|
||||
{
|
||||
treeList?.SwapItem(draggedData, targetIndex + 1);
|
||||
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 순서 변경(루트레벨)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 루트 레벨인 경우
|
||||
var treeListItems = treeList?.Items;
|
||||
if (treeListItems != null)
|
||||
var parentData = targetData.Parent;
|
||||
|
||||
if (parentData != null)
|
||||
{
|
||||
var targetIndex = treeListItems.IndexOf(targetData);
|
||||
var targetIndex = parentData.Children.IndexOf(targetData);
|
||||
if (targetIndex >= 0)
|
||||
{
|
||||
treeList?.AddItemAt(draggedData, targetIndex + 1);
|
||||
Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 이동 (루트 레벨)");
|
||||
parentData.AddCloneAtChild(draggedData, targetIndex + 1);
|
||||
Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 {targetIndex} 이동");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 루트 레벨인 경우
|
||||
var treeListItems = treeList?.Items;
|
||||
if (treeListItems != null)
|
||||
{
|
||||
var targetIndex = treeListItems.IndexOf(targetData);
|
||||
if (targetIndex >= 0)
|
||||
{
|
||||
treeList?.AddCloneItemAt(draggedData, targetIndex + 1);
|
||||
Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 {targetIndex} 이동 (루트 레벨)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 아이템을 현재 부모에서 제거합니다.
|
||||
/// </summary>
|
||||
private void RemoveFromParent(TreeListItemData item)
|
||||
{
|
||||
|
||||
Debug.Log($"[RemoveFromParent] {item.Name}을(를) 부모 {item.Parent == null}에서 제거");
|
||||
if (item.Parent != null)
|
||||
{
|
||||
item.Parent.RemoveChild(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 루트 레벨에서 제거
|
||||
treeList?.RemoveItem(item);
|
||||
}
|
||||
treeList?.UpdateFlattenedItemDataList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 주어진 아이템의 부모를 찾습니다.
|
||||
/// </summary>
|
||||
private TreeListItemData? FindParentOfItem(TreeListItemData item)
|
||||
{
|
||||
if (treeList == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (TreeListItemData data in treeList!.AllItemsFlattened)
|
||||
{
|
||||
if (data == item)
|
||||
{
|
||||
return data.Parent;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 드롭 위치를 나타내는 열거형입니다.
|
||||
/// 드롭 위치를 나타냅니다.
|
||||
/// </summary>
|
||||
private enum DropPosition
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user