This commit is contained in:
logonkhi
2025-11-14 17:02:38 +09:00
parent c98c1d9d9a
commit 934fff54a7
13 changed files with 579 additions and 162 deletions

View File

@@ -64,14 +64,12 @@ namespace SHI.modal
{
listView.OnItemSelected += data =>
{
Debug.Log($"BlockDetailModal: ListView OnItemSelected, data:{data==null}");
if (data == null) return;
HandleSelection(data.Id, "ListView");
};
listView.OnItemDeselected += data =>
{
Debug.Log("BlockDetailModal: ListView OnItemDeselected");
HandleDeselection(data.Id, "ListView");
};
@@ -156,7 +154,7 @@ namespace SHI.modal
_idToKey[it.Id] = it.ExternalKey;
}
}
if (listView != null) listView.Populate(items);
if (listView != null) listView.SetupData(items);
if (chartView != null) chartView.LoadData(gantt);
}

View File

@@ -18,15 +18,14 @@ namespace SHI.modal
[SerializeField]
protected ImageToggle visibleToggle;
public virtual void Init(TreeListItemData data, TreeList control, TreeListDragDropManager dragDropManager)
public override void Init(TreeListItemData data, TreeList control, TreeListDragDropManager dragDropManager)
{
base.Init(data, control, dragDropManager);
Debug.Log($"ModelDetailListItem Init. visibleToggle:{visibleToggle==null}");
if (visibleToggle != null)
{
visibleToggle.OnValueChanged.AddListener(isOn =>
{
if(data is ModelDetailListItemData modelData)
if (data is ModelDetailListItemData modelData)
{
modelData.IsVisible = isOn;
modelData.OnClickVisibleAction?.Invoke(modelData, isOn);

View File

@@ -136,10 +136,16 @@ namespace SHI.modal
/// NEW: 데이터 주입
/// </summary>
/// <param name="items"></param>
public void Populate(IEnumerable<ModelDetailListItemData> items)
public void SetupData(IEnumerable<ModelDetailListItemData> items)
{
// 기존 아이템 클리어
treeList.ClearItems();
SetVisiblilityAction(items);
AddItems(items);
}
private void SetVisiblilityAction(IEnumerable<ModelDetailListItemData> items)
{
foreach (var item in items)
{
// 가시성 아이콘 클릭 연동
@@ -152,9 +158,11 @@ namespace SHI.modal
OnVisibilityChanged?.Invoke(md.Id, isVisible);
}
};
treeList.AddItem<ModelDetailListItem>(item);
if(item.Children != null && item.Children.Count > 0)
{
SetVisiblilityAction(item.Children.OfType<ModelDetailListItemData>());
}
}
treeList.ScheduleFlattenedUpdate();
}
/// <summary>
@@ -179,6 +187,15 @@ namespace SHI.modal
treeList.AddItem<ModelDetailListItem>(data);
}
/// <summary>
/// 메인 트리에 항목들을 추가합니다.
/// </summary>
/// <param name="dataList">추가 할 데이터들</param>
public void AddItems(IEnumerable<TreeListItemData> dataList)
{
treeList.AddItems<ModelDetailListItem>(dataList);
}
/// <summary>
/// 메인 트리에 항목을 특정 인덱스에 삽입합니다.
/// </summary>
@@ -214,7 +231,6 @@ namespace SHI.modal
public void SelectItem(string name)
{
//검색 중이면 취소
CancelSearch();
treeListSearch.gameObject.SetActive(false);
treeList.gameObject.SetActive(true);
@@ -222,6 +238,15 @@ namespace SHI.modal
treeList.SelectItem(name);
}
/// <summary>
/// 이름으로 아이템 선택 해제
/// </summary>
/// <param name="name"></param>
public void DeselectItem(string name)
{
treeList.DeselectItem(name);
}
protected void StartLoadingAnimation()
{
if (loadingImage == null) return;

View File

@@ -53,12 +53,15 @@ namespace SHI.modal
private float _yawStart;
private float _pitchStart;
private Quaternion _modelStartRot;
private Vector3 _modelStartPos; // RMB 드래그 시작 시 모델 위치
private Vector3 _rmbPivot; // RMB 회전의 피벗(모델 중심)
private readonly Dictionary<Guid, GameObject> _idToObject = new Dictionary<Guid, GameObject>();
private readonly Dictionary<GameObject, (Renderer[] rends, UnityEngine.Material[][] originals)> _matCache = new Dictionary<GameObject, (Renderer[], UnityEngine.Material[][])>();
private GameObject? _root;
private Guid? _focusedId;
public async UniTask<IEnumerable<ModelDetailListItemData>> LoadModelAsync(string path, CancellationToken ct)
{
Debug.Log($"ModelDetailView.LoadModelAsync: {path}");
@@ -345,8 +348,8 @@ namespace SHI.modal
dist = Mathf.Clamp(dist, 1f, 1e4f);
_viewCamera.transform.position = center + new Vector3(1, 0.5f, 1).normalized * dist;
_viewCamera.transform.LookAt(center);
_viewCamera.nearClipPlane = Mathf.Max(0.01f, dist - radius * 2f);
_viewCamera.farClipPlane = dist + radius * 4f;
//_viewCamera.nearClipPlane = Mathf.Max(0.01f, dist - radius * 2f);
//_viewCamera.farClipPlane = dist + radius * 4f;
_orbitTarget = center;
_orbitDistance = Vector3.Distance(_viewCamera.transform.position, _orbitTarget);
@@ -530,7 +533,7 @@ namespace SHI.modal
// 드래그 상태 전이 처리 (점프 방지)
if (Input.GetMouseButtonDown(2)) { _mmbDragging = true; _mmbLastPos = Input.mousePosition; }
if (Input.GetMouseButtonUp(2)) { _mmbDragging = false; }
if (Input.GetMouseButtonDown(1)) { _rmbDragging = true; _rmbStartPos = Input.mousePosition; _yawStart = _yaw; _pitchStart = _pitch; if (_root != null) _modelStartRot = _root.transform.rotation; }
if (Input.GetMouseButtonDown(1)) { _rmbDragging = true; _rmbStartPos = Input.mousePosition; _yawStart = _yaw; _pitchStart = _pitch; if (_root != null) { _modelStartRot = _root.transform.rotation; _modelStartPos = _root.transform.position; } _rmbPivot = _orbitTarget; }
if (Input.GetMouseButtonUp(1)) { _rmbDragging = false; }
// 가운데 버튼: 모델 이동 (좌/우/상/하) - 카메라 기준, 픽셀 델타 기반
@@ -565,7 +568,7 @@ namespace SHI.modal
_orbitTarget += deltaZ;
}
// 오른쪽 버튼: 모델 회전 (카메라 기준 yaw/pitch)
// 오른쪽 버튼: 모델 회전 (카메라 기준 yaw/pitch) - 모델 중심(_orbitTarget) 기준으로 회전
if (_rmbDragging && _root != null)
{
Vector3 cur = Input.mousePosition;
@@ -573,10 +576,16 @@ namespace SHI.modal
// 반전: 좌우/상하 모두 반대 방향으로 회전
float yaw = -dpAbs.x * rotateDegPerPixel; // 좌우 반전
float pitch = dpAbs.y * rotateDegPerPixel; // 위아래 반전
// 카메라 기준 축으로 모델 회전
// 카메라 기준 축으로 회전 행렬 구성
Quaternion yawQ = Quaternion.AngleAxis(yaw, _viewCamera.transform.up);
Quaternion pitchQ = Quaternion.AngleAxis(pitch, _viewCamera.transform.right);
_root.transform.rotation = yawQ * pitchQ * _modelStartRot;
Quaternion r = yawQ * pitchQ;
// 피벗(_rmbPivot, 보통 모델 중심) 기준으로 위치+회전 동시 적용
Vector3 startVec = _modelStartPos - _rmbPivot;
_root.transform.position = _rmbPivot + r * startVec;
_root.transform.rotation = r * _modelStartRot;
}
}

View File

@@ -530,6 +530,17 @@ namespace UVC.UI.List.Tree
UpdateFlattenedItemDataList();
}
/// <summary>
/// TreeListItem 프리팹 인스턴스화
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
protected T? Create<T>() where T : TreeListItem
{
T? item = GameObject.Instantiate(ItemPrefab, root) as T;
return item;
}
/// <summary>
/// 새 아이템 추가
///
@@ -548,11 +559,11 @@ namespace UVC.UI.List.Tree
data.Parent = null;
// Instantiate(템플릿, 부모 Transform)
// = 템플릿을 복제하고 부모의 자식으로 설정
T item = GameObject.Instantiate(ItemPrefab, root) as T;
T? item = Create<T>();
// 생성된 아이템 초기화
// 데이터를 UI에 바인딩하고 이벤트 리스너 등록
item.Init(data, this, dragDropManager);
item?.Init(data, this, dragDropManager);
items.Add(data);
// 범위 선택에 필요한 평탄화 리스트 업데이트
@@ -560,6 +571,27 @@ namespace UVC.UI.List.Tree
}
/// <summary>
/// 새 아이템들 추가
/// </summary>
/// <typeparam name="T">추가 할 타입</typeparam>
/// <param name="datas">추가 할 데이터들</param>
public void AddItems<T>(IEnumerable<TreeListItemData> datas) where T : TreeListItem
{
foreach (var data in datas)
{
data.Parent = null;
// Instantiate(템플릿, 부모 Transform)
// = 템플릿을 복제하고 부모의 자식으로 설정
T? item = Create<T>();
// 생성된 아이템 초기화
// 데이터를 UI에 바인딩하고 이벤트 리스너 등록
item?.Init(data, this, dragDropManager);
items.Add(data);
}
UpdateFlattenedItemDataList();
}
/// <summary>
/// 지정 인덱스에 아이템 추가
///
@@ -970,6 +1002,19 @@ namespace UVC.UI.List.Tree
OnItemSelectionChanged?.Invoke(data, true);
}
/// <summary>
/// 이름으로 아이템 선택 해제
/// </summary>
/// <param name="name"></param>
public void DeselectItem(string name)
{
var item = allItemDataFlattened.FirstOrDefault(x => x.Name == name);
if (item != null)
{
DeselectItem(item);
}
}
/// <summary>
/// 아이템 선택 해제
///

View File

@@ -72,6 +72,12 @@ namespace UVC.UI.List.Tree
[SerializeField]
protected Button itemButton;
/// <summary>
/// text가 배치 된 RectTransform.
/// </summary>
[SerializeField]
protected RectTransform layout;
#endregion
#region (Data Fields)
@@ -91,6 +97,8 @@ namespace UVC.UI.List.Tree
/// </summary>
protected bool isAnimating = false;
protected VerticalLayoutGroup? childRootLayoutGroup = null;
#endregion
#region (Initialization)
@@ -123,7 +131,12 @@ namespace UVC.UI.List.Tree
valueText.text = data.Name;
// 3. 자식 아이템들을 UI로 생성
Debug.Log("Creating Children for " + data.Name + ", " + data.Children.Count);
//Debug.Log("Creating Children for " + data.Name + ", " + data.Children.Count);
if (childRootLayoutGroup == null)
{
childRootLayoutGroup = childRoot.GetComponent<VerticalLayoutGroup>();
}
if (data.Children.Count > 0)
@@ -164,7 +177,7 @@ namespace UVC.UI.List.Tree
if (dragHandler == null)
{
dragHandler = gameObject.AddComponent<TreeListItemDragHandler>();
Debug.Log($"[TreeListItem.Init] 새로운 TreeListItemDragHandler 추가: {data.Name}");
//Debug.Log($"[TreeListItem.Init] 새로운 TreeListItemDragHandler 추가: {data.Name}");
}
dragHandler.SetDragDropManager(this, control, dragDropManager);
@@ -173,7 +186,7 @@ namespace UVC.UI.List.Tree
// Register view to map
treeList.RegisterView(data, this);
Debug.Log($"[TreeListItem.Init] 초기화 완료: {data.Name}");
//Debug.Log($"[TreeListItem.Init] 초기화 완료: {data.Name}");
}
#endregion
@@ -305,7 +318,7 @@ namespace UVC.UI.List.Tree
else if (changedType == ChangedType.RemoveChild)
{
//따로 할것 없음 - 펼침 버튼 갱신 용
Debug.Log($"RemoveChild 처리 완료 {changedData.Name}, {index}");
//Debug.Log($"RemoveChild 처리 완료 {changedData.Name}, {index}");
}
UniTask.DelayFrame(1).ContinueWith(() =>
@@ -539,6 +552,12 @@ namespace UVC.UI.List.Tree
treeList.ItemPrefab, // 복제할 프리팹
childRoot // 부모로 배치할 위치
);
//item.layout의 너비를 childRootLayoutGroup의 padding.left 만큼 줄이기
if (item != null && item.layout != null && childRootLayoutGroup != null)
{
item.layout.sizeDelta = new Vector2(layout.sizeDelta.x - childRootLayoutGroup.padding.left, item.layout.sizeDelta.y);
}
// 2. 생성된 아이템 초기화
item.Init(data, treeList, treeList.DragDropManager);

View File

@@ -92,12 +92,11 @@ namespace UVC.UI.List.Tree
treeList = list;
dragDropManager = manager;
treeListRootParent = list.Root.parent as RectTransform;
Debug.Log($"[TreeListItemDragHandler] 드래그 핸들러 설정: {item.Data?.Name ?? "Unknown"}");
//Debug.Log($"[TreeListItemDragHandler] 드래그 핸들러 설정: {item.Data?.Name ?? "Unknown"}");
}
public void OnBeginDrag(PointerEventData eventData)
{
Debug.Log("[OnPointerDown]");
if (!enableDragDrop || treeListItem?.Data == null || dragDropManager == null)
{
return;
@@ -117,7 +116,7 @@ namespace UVC.UI.List.Tree
dragOffset = localPoint;
_lastPointerScreenPos = eventData.position;
Debug.Log($"[OnPointerDown] {treeListItem.Data.Name}에 포인터 다운, offset: {dragOffset}");
//Debug.Log($"[OnPointerDown] {treeListItem.Data.Name}에 포인터 다운, offset: {dragOffset}");
}
public void OnDrag(PointerEventData eventData)
@@ -134,7 +133,7 @@ namespace UVC.UI.List.Tree
}
_lastPointerScreenPos = eventData.position;
Debug.Log($"[OnDrag] {treeListItem.Data.Name} 드래그 중");
//Debug.Log($"[OnDrag] {treeListItem.Data.Name} 드래그 중");
if (!dragDropManager.IsDragging)
{
@@ -151,7 +150,7 @@ namespace UVC.UI.List.Tree
CreateDropIndicator();
Debug.Log($"[OnDrag] {treeListItem.Data.Name} 드래그 시작");
//Debug.Log($"[OnDrag] {treeListItem.Data.Name} 드래그 시작");
}
// 마우스 위의 드롭 대상 찾기
@@ -191,13 +190,12 @@ namespace UVC.UI.List.Tree
public void OnEndDrag(PointerEventData eventData)
{
Debug.Log("[OnPointerUp]");
if (!enableDragDrop || dragDropManager == null)
{
return;
}
Debug.Log("[OnPointerUp] 드래그 완료");
//Debug.Log("[OnPointerUp] 드래그 완료");
if (canvasGroup != null)
{
@@ -228,7 +226,7 @@ namespace UVC.UI.List.Tree
if (treeListItem?.Data != null)
{
var result = dragDropManager.TryDrop(targetItem?.Data);
Debug.Log($"[OnPointerUp] 드롭 결과: {(result ? "" : "")}");
//Debug.Log($"[OnPointerUp] 드롭 결과: {(result ? "성공" : "실패")}");
if (result) HandleDropSuccess(treeListItem.Data, targetItem);
}
@@ -305,7 +303,6 @@ namespace UVC.UI.List.Tree
private void CreateDropIndicator()
{
Debug.Log($"[CreateDropIndicator] dropIndicator != null:{dropIndicator != null}");
if (dropIndicator != null)
{
return;
@@ -318,7 +315,7 @@ namespace UVC.UI.List.Tree
dropIndicatorRect = existingDropIndicator.GetComponent<RectTransform>();
dropIndicatorParent = treeListRootParent;
Debug.Log("[CreateDropIndicator] 기존 DropIndicator를 재사용합니다");
//Debug.Log("[CreateDropIndicator] 기존 DropIndicator를 재사용합니다");
return;
}
@@ -348,7 +345,7 @@ namespace UVC.UI.List.Tree
dropIndicator.raycastTarget = false;
indicatorGo.SetActive(false);
Debug.Log("[CreateDropIndicator] 드롭 위치 표시 막대 생성됨");
//Debug.Log("[CreateDropIndicator] 드롭 위치 표시 막대 생성됨");
}
private void UpdateDropIndicator(TreeListItem? targetItem)
@@ -422,7 +419,7 @@ namespace UVC.UI.List.Tree
dropIndicatorRect.anchoredPosition = new Vector2(indicatorX, indicatorY);
dropIndicatorRect.sizeDelta = new Vector2(dropIndicatorRect.sizeDelta.x, indicatorHeight);
Debug.Log($"[UpdateDropIndicator] {targetItem?.Data?.Name} 위치: {dropPosition}, targetY: {targetWorldY}, parentY: {parentWorldY}, indicatorY: {indicatorY}");
//Debug.Log($"[UpdateDropIndicator] {targetItem?.Data?.Name} 위치: {dropPosition}, targetY: {targetWorldY}, parentY: {parentWorldY}, indicatorY: {indicatorY}");
}
private void HideDropIndicator()
@@ -446,12 +443,10 @@ namespace UVC.UI.List.Tree
Transform child = treeListRootParent.GetChild(i);
if (child.name == "DropIndicator")
{
Debug.Log("[FindDropIndicatorInRoot] DropIndicator를 찾았습니다");
return child.gameObject;
}
}
Debug.Log("[FindDropIndicatorInRoot] DropIndicator를 찾지 못했습니다");
return null;
}
@@ -476,7 +471,7 @@ namespace UVC.UI.List.Tree
es.RaycastAll(eventData, s_RaycastResults);
Debug.Log($"[GetItemAtMousePosition] Raycast 결과: {s_RaycastResults.Count}개");
//Debug.Log($"[GetItemAtMousePosition] Raycast 결과: {s_RaycastResults.Count}개");
for (int i = 0; i < s_RaycastResults.Count; i++)
{
@@ -484,7 +479,7 @@ namespace UVC.UI.List.Tree
var item = result.gameObject.GetComponentInParent<TreeListItem>();
if (item != null)
{
Debug.Log($"[GetItemAtMousePosition] 찾은 아이템: {item.Data?.Name ?? "Unknown"}");
//Debug.Log($"[GetItemAtMousePosition] 찾은 아이템: {item.Data?.Name ?? "Unknown"}");
return item;
}
}
@@ -501,7 +496,6 @@ namespace UVC.UI.List.Tree
if (targetItem == null)
{
Debug.Log("[HandleDropSuccess] 루트로 이동");
MoveToRoot(draggedData);
treeList.ScheduleFlattenedUpdate();
return;
@@ -515,7 +509,7 @@ namespace UVC.UI.List.Tree
var dropPosition = GetDropPosition(targetItem.GetComponent<RectTransform>());
Debug.Log($"[HandleDropSuccess] 드롭 위치: {targetItem?.Data?.Name} {dropPosition}");
//Debug.Log($"[HandleDropSuccess] 드롭 위치: {targetItem?.Data?.Name} {dropPosition}");
switch (dropPosition)
{
@@ -561,7 +555,7 @@ namespace UVC.UI.List.Tree
private void MoveToRoot(TreeListItemData draggedData)
{
Debug.Log($"[MoveToRoot] {draggedData.Name}을(를) 루트로 이동");
//Debug.Log($"[MoveToRoot] {draggedData.Name}을(를) 루트로 이동");
if (treeList == null)
{
@@ -583,13 +577,13 @@ namespace UVC.UI.List.Tree
{
treeList.AddCloneItem(draggedData);
}
Debug.Log($"[MoveToRoot] {draggedData.Name}을(를) 루트 레벨의 끝에 추가");
//Debug.Log($"[MoveToRoot] {draggedData.Name}을(를) 루트 레벨의 끝에 추가");
}
private void MoveAsChild(TreeListItemData draggedData, TreeListItemData targetData)
{
targetData.AddCloneChild(draggedData);
Debug.Log($"[MoveAsChild] {draggedData.Name}을(를) {targetData.Name}의 자식으로 이동");
//Debug.Log($"[MoveAsChild] {draggedData.Name}을(를) {targetData.Name}의 자식으로 이동");
}
private void MoveBefore(TreeListItemData draggedData, TreeListItemData targetData)
@@ -604,7 +598,7 @@ namespace UVC.UI.List.Tree
if (targetIndex >= 0)
{
draggedData.Parent.SwapChild(draggedData, targetIndex);
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 순서 변경");
//Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 순서 변경");
}
}
else
@@ -617,7 +611,7 @@ namespace UVC.UI.List.Tree
if (targetIndex >= 0)
{
treeList?.SwapItem(draggedData, targetIndex);
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 순서 변경(루트레벨)");
//Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 순서 변경(루트레벨)");
}
}
}
@@ -631,7 +625,7 @@ namespace UVC.UI.List.Tree
if (targetIndex >= 0)
{
parentData.AddCloneAtChild(draggedData, targetIndex);
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 이동");
//Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 이동");
}
}
else
@@ -643,7 +637,7 @@ namespace UVC.UI.List.Tree
if (targetIndex >= 0)
{
treeList?.AddCloneItemAt(draggedData, targetIndex);
Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 이동 (루트 레벨)");
//Debug.Log($"[MoveBefore] {draggedData.Name}을(를) {targetData.Name} 앞으로 {targetIndex} 이동 (루트 레벨)");
}
}
}
@@ -662,7 +656,7 @@ namespace UVC.UI.List.Tree
if (targetIndex >= 0)
{
draggedData.Parent.SwapChild(draggedData, targetIndex + 1);
Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 {targetIndex} 순서 변경");
//Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 {targetIndex} 순서 변경");
}
}
else
@@ -675,7 +669,7 @@ namespace UVC.UI.List.Tree
if (targetIndex >= 0)
{
treeList?.SwapItem(draggedData, targetIndex + 1);
Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 {targetIndex} 순서 변경(루트레벨)");
//Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 {targetIndex} 순서 변경(루트레벨)");
}
}
}
@@ -690,7 +684,7 @@ namespace UVC.UI.List.Tree
if (targetIndex >= 0)
{
parentData.AddCloneAtChild(draggedData, targetIndex + 1);
Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 {targetIndex} 이동");
//Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 {targetIndex} 이동");
}
}
else
@@ -702,7 +696,7 @@ namespace UVC.UI.List.Tree
if (targetIndex >= 0)
{
treeList?.AddCloneItemAt(draggedData, targetIndex + 1);
Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 {targetIndex} 이동 (루트 레벨)");
//Debug.Log($"[MoveAfter] {draggedData.Name}을(를) {targetData.Name} 뒤로 {targetIndex} 이동 (루트 레벨)");
}
}
}

View File

@@ -132,6 +132,15 @@ namespace UVC.UI.Window
treeList.AddItem<TreeListItem>(data);
}
/// <summary>
/// 메인 트리에 항목들을 추가합니다.
/// </summary>
/// <param name="dataList">추가 할 데이터들</param>
public void AddItems(System.Collections.Generic.IEnumerable<TreeListItemData> dataList)
{
treeList.AddItems<TreeListItem>(dataList);
}
/// <summary>
/// 메인 트리에 항목을 특정 인덱스에 삽입합니다.
/// </summary>
@@ -175,6 +184,15 @@ namespace UVC.UI.Window
treeList.SelectItem(name);
}
/// <summary>
/// 이름으로 아이템 선택 해제
/// </summary>
/// <param name="name"></param>
public void DeselectItem(string name)
{
treeList.DeselectItem(name);
}
protected void StartLoadingAnimation()
{
if (loadingImage == null) return;