선택한 모델 PropertyWindow 연결 완료

This commit is contained in:
logonkhi
2025-12-19 15:27:35 +09:00
parent deeaa9a7ad
commit 158a42ab9b
24 changed files with 2278 additions and 1185 deletions

View File

@@ -1,5 +1,7 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UVC.Core;
@@ -54,6 +56,7 @@ namespace UVC.Studio.Tab
hierarchyWindow.OnItemDeselected += OnItemDeselectedHandler;
hierarchyWindow.OnItemVisibilityChanged += OnItemVisibilityChangedHandler;
//다른 클래스에서 이 컴포넌트를 주입 받을 수 있도록 등록
InjectorAppContext.Instance.Injector.RegisterInstance<StudioSideTabBarHierarchy>(this, ServiceLifetime.Scene);
}
@@ -142,7 +145,7 @@ namespace UVC.Studio.Tab
}
// SelectionManager 가져오기
_selectionManager = InjectorAppContext.Instance.Get<SelectionManager>();
if (_selectionManager == null) _selectionManager = InjectorAppContext.Instance.Get<SelectionManager>();
if (_selectionManager != null)
{
// 선택 변경 이벤트 구독 (화면 클릭으로 선택 시 HierarchyWindow 동기화)
@@ -152,6 +155,7 @@ namespace UVC.Studio.Tab
{
Debug.LogWarning("[StudioSideTabBarHierarchy] SelectionManager not found.");
}
isInitialized = true;
}
/// <summary>
@@ -218,11 +222,12 @@ namespace UVC.Studio.Tab
return;
}
// TreeListItemData 생성
var treeItem = new TreeListItemData(stageObject.GameObject != null ? stageObject.GameObject.name : stageObject.Equipment.model)
{
ExternalKey = stageObject.Id
};
// TreeListItemData 생성 (하위 자식 포함)
var treeItem = CreateTreeItemRecursive(
stageObject.GameObject != null ? stageObject.GameObject.transform : null,
stageObject.GameObject != null ? stageObject.GameObject.name : stageObject.Equipment.id,
stageObject.Id
);
// 매핑 저장
_stageObjectToTreeItem[stageObject.Id] = treeItem;
@@ -230,7 +235,36 @@ namespace UVC.Studio.Tab
// HierarchyWindow에 추가
hierarchyWindow.AddItem(treeItem);
Debug.Log($"[StudioSideTabBarHierarchy] Added TreeItem: {treeItem.Name}");
Debug.Log($"[StudioSideTabBarHierarchy] Added TreeItem: {treeItem.Name} (including all children)");
}
/// <summary>
/// Transform의 자식들을 재귀적으로 탐색하여 TreeListItemData를 생성
/// </summary>
/// <param name="transform">탐색할 Transform (null이면 이름만 사용)</param>
/// <param name="name">표시 이름</param>
/// <param name="externalKey">외부 키 (루트 노드에만 설정)</param>
/// <returns>생성된 TreeListItemData</returns>
private TreeListItemData CreateTreeItemRecursive(Transform? transform, string name, string? externalKey = null)
{
var treeItem = new TreeListItemData(name);
if (!string.IsNullOrEmpty(externalKey))
{
treeItem.ExternalKey = externalKey;
}
// Transform이 있으면 자식들을 재귀적으로 추가
if (transform != null)
{
foreach (Transform child in transform)
{
var childItem = CreateTreeItemRecursive(child, child.name);
treeItem.AddChild(childItem);
}
}
return treeItem;
}
/// <summary>
@@ -269,13 +303,70 @@ namespace UVC.Studio.Tab
return _stageObjectToTreeItem.TryGetValue(stageObjectId, out var treeItem) ? treeItem : null;
}
/// <summary>
/// StageObject의 표시 이름을 변경합니다.
/// HierarchyWindow의 TreeList에도 반영됩니다.
/// </summary>
/// <param name="stageObjectId">변경할 StageObject의 ID</param>
/// <param name="newName">새 이름</param>
public void UpdateItemName(string stageObjectId, string newName)
{
if (hierarchyWindow == null) return;
if (!_stageObjectToTreeItem.TryGetValue(stageObjectId, out var treeItem)) return;
// HierarchyWindow.SetItemName을 통해 TreeList UI도 함께 갱신
hierarchyWindow.SetItemName(treeItem, newName);
Debug.Log($"[StudioSideTabBarHierarchy] Updated item name: {stageObjectId} -> {newName}");
}
/// <summary>
/// 탭 콘텐츠에 데이터를 전달합니다.
/// 탭이 활성화될 때 호출되며, SelectionManager의 선택 상태를 HierarchyWindow에 동기화합니다.
/// </summary>
/// <param name="data">전달할 데이터 객체</param>
public void SetContentData(object? data)
{
Debug.Log("StudioSideTabBarHierarchy: SetContentData called");
// SelectionManager에 선택된 항목이 있으면 HierarchyWindow에 반영
SyncSelectionFromSelectionManager();
}
/// <summary>
/// SelectionManager의 현재 선택 상태를 HierarchyWindow에 동기화합니다.
/// </summary>
private async void SyncSelectionFromSelectionManager()
{
if (!isInitialized)
{
await UniTask.WaitUntil(() => isInitialized).TimeoutWithoutException(new TimeSpan(0, 0, 1));
}
Debug.Log($"StudioSideTabBarHierarchy: SyncSelectionFromSelectionManager called. _selectionManager == null:{_selectionManager == null}, hierarchyWindow == null:{hierarchyWindow == null}");
if (_selectionManager == null || hierarchyWindow == null) return;
var selectedObjects = _selectionManager.SelectedObjects;
if (selectedObjects.Count == 0) return;
_isProcessingSelection = true;
try
{
foreach (var stageObject in selectedObjects)
{
if (string.IsNullOrEmpty(stageObject.Id)) continue;
// 매핑에서 TreeListItemData 찾기
if (_stageObjectToTreeItem.TryGetValue(stageObject.Id, out var treeItem))
{
hierarchyWindow.SelectItem(treeItem.Name);
Debug.Log($"[StudioSideTabBarHierarchy] Synced existing selection: {treeItem.Name}");
}
}
}
finally
{
_isProcessingSelection = false;
}
}
/// <summary>