diff --git a/Assets/Resources/UIToolkit.meta b/Assets/Resources/UIToolkit.meta
new file mode 100644
index 00000000..69a0e951
--- /dev/null
+++ b/Assets/Resources/UIToolkit.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 166e6c1e42c1dee4a836845108ff7782
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Resources/UIToolkit/Images.meta b/Assets/Resources/UIToolkit/Images.meta
new file mode 100644
index 00000000..79a5c5a9
--- /dev/null
+++ b/Assets/Resources/UIToolkit/Images.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 7592dc8b147efba4c87e224db8ad6411
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Resources/UIToolkit/Images/btn_cancel_64.png b/Assets/Resources/UIToolkit/Images/btn_cancel_64.png
new file mode 100644
index 00000000..7894909f
Binary files /dev/null and b/Assets/Resources/UIToolkit/Images/btn_cancel_64.png differ
diff --git a/Assets/Resources/UIToolkit/Images/btn_cancel_64.png.meta b/Assets/Resources/UIToolkit/Images/btn_cancel_64.png.meta
new file mode 100644
index 00000000..231030e4
--- /dev/null
+++ b/Assets/Resources/UIToolkit/Images/btn_cancel_64.png.meta
@@ -0,0 +1,143 @@
+fileFormatVersion: 2
+guid: 9dd52303744ec104bb941cd8271e0668
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 13
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 0
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ flipGreenChannel: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMipmapLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 1
+ aniso: 1
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 0
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ swizzle: 50462976
+ cookieLightType: 0
+ platformSettings:
+ - serializedVersion: 4
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 64
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: WebGL
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: WindowsStoreApps
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ customData:
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spriteCustomMetadata:
+ entries: []
+ nameFileIdTable: {}
+ mipmapLimitGroupName:
+ pSDRemoveMatte: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Resources/UIToolkit/Images/button_close_22.png b/Assets/Resources/UIToolkit/Images/button_close_22.png
new file mode 100644
index 00000000..fa22e0e2
Binary files /dev/null and b/Assets/Resources/UIToolkit/Images/button_close_22.png differ
diff --git a/Assets/Resources/UIToolkit/Images/button_close_22.png.meta b/Assets/Resources/UIToolkit/Images/button_close_22.png.meta
new file mode 100644
index 00000000..950bfccf
--- /dev/null
+++ b/Assets/Resources/UIToolkit/Images/button_close_22.png.meta
@@ -0,0 +1,117 @@
+fileFormatVersion: 2
+guid: 91d854fabfbb60445ba500eaffcaea07
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 13
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 0
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ flipGreenChannel: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMipmapLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 1
+ aniso: 1
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 0
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ swizzle: 50462976
+ cookieLightType: 0
+ platformSettings:
+ - serializedVersion: 4
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 32
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ customData:
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spriteCustomMetadata:
+ entries: []
+ nameFileIdTable: {}
+ mipmapLimitGroupName:
+ pSDRemoveMatte: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Resources/UIToolkit/Images/icon_search_16x17.png b/Assets/Resources/UIToolkit/Images/icon_search_16x17.png
new file mode 100644
index 00000000..96b276f8
Binary files /dev/null and b/Assets/Resources/UIToolkit/Images/icon_search_16x17.png differ
diff --git a/Assets/Resources/UIToolkit/Images/icon_search_16x17.png.meta b/Assets/Resources/UIToolkit/Images/icon_search_16x17.png.meta
new file mode 100644
index 00000000..80ec6f05
--- /dev/null
+++ b/Assets/Resources/UIToolkit/Images/icon_search_16x17.png.meta
@@ -0,0 +1,143 @@
+fileFormatVersion: 2
+guid: 4737b068c8483f348aef876954e2afee
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 13
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 0
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ flipGreenChannel: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ vTOnly: 0
+ ignoreMipmapLimit: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: 1
+ aniso: 1
+ mipBias: 0
+ wrapU: 1
+ wrapV: 1
+ wrapW: 0
+ nPOTScale: 0
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 1
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 1
+ spriteTessellationDetail: -1
+ textureType: 8
+ textureShape: 1
+ singleChannelComponent: 0
+ flipbookRows: 1
+ flipbookColumns: 1
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ ignorePngGamma: 0
+ applyGammaDecoding: 0
+ swizzle: 50462976
+ cookieLightType: 0
+ platformSettings:
+ - serializedVersion: 4
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 32
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: Standalone
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: WebGL
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ - serializedVersion: 4
+ buildTarget: WindowsStoreApps
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ ignorePlatformSupport: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ customData:
+ physicsShape: []
+ bones: []
+ spriteID: 5e97eb03825dee720800000000000000
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spriteCustomMetadata:
+ entries: []
+ nameFileIdTable: {}
+ mipmapLimitGroupName:
+ pSDRemoveMatte: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Resources/UIToolkit/List.meta b/Assets/Resources/UIToolkit/List.meta
new file mode 100644
index 00000000..c851465f
--- /dev/null
+++ b/Assets/Resources/UIToolkit/List.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3a74dc9dc20593f4e911815b5182854b
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uss b/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uss
new file mode 100644
index 00000000..b584df4d
--- /dev/null
+++ b/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uss
@@ -0,0 +1,254 @@
+/*
+ * UIToolkitTreeList.uss - UIToolkitTreeList 컴포넌트 스타일시트
+ *
+ * [개요]
+ * UIToolkitTreeList.uxml과 UIToolkitTreeListItem.uxml에서 사용하는 스타일을 정의합니다.
+ * 어두운 테마(Dark Theme)에 맞춰 디자인되었습니다.
+ *
+ * [스타일 구조]
+ * 1. .tree-menu-container : 메인 컨테이너 (어두운 배경, 240px 너비)
+ * 2. .search-field : 검색 입력 필드 (흰색 배경, 둥근 모서리)
+ * 3. #main-tree-view : TreeView 기본 설정 (들여쓰기 10px)
+ * 4. .unity-tree-view__item-toggle : 펼침/접기 토글 버튼
+ * 5. .unity-collection-view__item : 항목 배경색 (기본/호버/선택)
+ * 6. .visibility-toggle : 가시성 토글 버튼 (눈 아이콘)
+ *
+ * [색상 팔레트]
+ * - 배경: rgb(40, 44, 52) - 어두운 회색
+ * - 호버: rgba(0, 10, 37, 0.25) - 반투명 파랑
+ * - 선택: rgba(0, 10, 37, 0.5) - 더 진한 반투명 파랑
+ * - 텍스트: rgb(255, 255, 255) - 흰색
+ *
+ * [연관 파일]
+ * - UIToolkitTreeList.uxml : 메인 레이아웃
+ * - UIToolkitTreeListItem.uxml : 개별 항목 템플릿
+ * - UIToolkitTreeList.cs : C# 컨트롤러
+ */
+
+/* ===================================
+ 메인 컨테이너 스타일
+ 사이드 패널 전체를 감싸는 컨테이너
+ =================================== */
+.tree-menu-container {
+ background-color: rgb(40, 44, 52); /* 어두운 회색 배경 */
+ flex-grow: 1; /* 부모 영역 채우기 */
+ padding: 5px;
+ padding-top: 25px;
+ padding-bottom: 25px;
+ padding-left: 20px;
+ padding-right: 20px;
+ width: 240px; /* 고정 너비 */
+}
+
+/* ===================================
+ 검색 입력 필드 스타일
+ 흰색 배경의 둥근 입력창
+ =================================== */
+.search-field {
+ margin-bottom: 20px;
+ background-color: rgb(255, 255, 255); /* 흰색 배경 */
+ border-radius: 4px; /* 둥근 모서리 */
+ height: 30px;
+ width: auto;
+ margin-top: 0;
+ margin-right: 0;
+ margin-left: 0;
+ -unity-font-definition: resource('Fonts/Pretendard/Pretendard-Regular');
+}
+
+/* 검색 필드 내부 텍스트 입력 영역 */
+#search-field > #unity-text-input {
+ padding-top: 4px;
+ padding-right: 24px; /* 오른쪽 아이콘 공간 확보 */
+ padding-bottom: 4px;
+ padding-left: 4px;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+ border-top-width: 0; /* 테두리 제거 */
+ border-right-width: 0;
+ border-bottom-width: 0;
+ border-left-width: 0;
+}
+
+/* ===================================
+ 체크박스 스타일
+ =================================== */
+#unity-checkmark {
+ -unity-background-image-tint-color: rgb(255, 255, 255);
+}
+
+/* ===================================
+ TreeView 기본 설정
+ =================================== */
+#main-tree-view {
+ --unity-item-indent-width: 10; /* 계층별 들여쓰기 너비 */
+}
+
+/* 펼침/접기 토글 아이콘 컨테이너 */
+#unity-tree-view__item-toggle > VisualElement > VisualElement {
+ margin-left: 0;
+ margin-right: 0;
+ width: 22px; /* 토글 아이콘 너비 */
+}
+
+/* 펼침/접기 토글 버튼 */
+.unity-tree-view__item-toggle {
+ margin-right: 5px; /* 라벨과의 간격 */
+}
+
+/* ===================================
+ 항목 배경색 스타일
+ 기본, 호버, 선택 상태별 배경색
+ =================================== */
+
+/* 기본 상태: 투명 배경 */
+.unity-collection-view__item {
+ background-color: rgba(50, 50, 50, 0);
+}
+
+/* 호버 상태: 반투명 파란색 배경 */
+.unity-collection-view__item:hover {
+ background-color: rgba(0, 10, 37, 0.25);
+}
+
+/* 선택 상태: 더 진한 반투명 파란색 배경 */
+.unity-collection-view__item--selected {
+ background-color: rgba(0, 10, 37, 0.5);
+}
+
+/* ===================================
+ 가시성 토글 버튼 스타일
+ 눈 아이콘으로 3D 모델 가시성 제어
+ =================================== */
+.visibility-toggle {
+ background-color: rgba(0, 0, 0, 0); /* 투명 배경 */
+ border-width: 0; /* 테두리 없음 */
+ width: 16px;
+ height: 16px;
+ margin-top: 0;
+ margin-bottom: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ margin-right: 0;
+ align-items: center;
+ justify-content: center;
+ padding-right: 0;
+ padding-left: 0;
+ margin-left: 0;
+ flex-shrink: 0; /* 크기 축소 방지 */
+ background-image: resource('SHI/Images/icon_visibility_on_64'); /* 기본: 보이는 상태 */
+}
+
+/* 가시성 켜짐 상태 (눈 열린 아이콘) */
+.visibility-on {
+ background-image: resource('SHI/Images/icon_visibility_on_64');
+}
+
+/* 가시성 꺼짐 상태 (눈 닫힌 아이콘) */
+.visibility-off {
+ background-image: resource('SHI/Images/icon_visibility_off_64');
+}
+
+/* ===================================
+ 세로 스크롤바 스타일
+ 슬림한 6px 너비의 커스텀 스크롤바
+ =================================== */
+.unity-scroller--vertical {
+ width: 6px; /* 슬림한 너비 */
+ margin-right: 4px;
+ margin-bottom: 0px;
+}
+
+/* 세로 스크롤바 트랙 (배경) */
+.unity-scroller--vertical .unity-base-slider__tracker {
+ background-color: rgba(255, 255, 255, 0); /* 흰색 배경 */
+ border-width: 0;
+}
+
+/* 세로 스크롤바 드래거 컨테이너 위치 조정 */
+.unity-scroller--vertical .unity-base-slider__drag-container {
+ left: 0;
+ right: 0;
+}
+
+/* 세로 스크롤바 드래거 (핸들) */
+.unity-scroller--vertical .unity-base-slider__dragger {
+ background-color: rgb(216, 216, 216); /* 밝은 회색 */
+ border-width: 0;
+ border-radius: 3px; /* 둥근 모서리 */
+ width: 6px;
+ left: 0;
+}
+
+/* 세로 스크롤바 화살표 버튼 숨김 */
+.unity-scroller--vertical .unity-repeat-button {
+ display: none;
+ width: 0;
+ height: 0;
+ min-width: 0;
+ min-height: 0;
+}
+
+/* 세로 스크롤바 슬라이더 마진 제거 */
+.unity-scroller--vertical .unity-slider {
+ margin: 0;
+}
+
+/* 세로 스크롤바 입력 필드 크기 조정 */
+.unity-scroller--vertical .unity-base-field__input {
+ width: 6px;
+ min-width: 6px;
+}
+
+/* ===================================
+ 가로 스크롤바 스타일
+ 슬림한 6px 높이의 커스텀 스크롤바
+ =================================== */
+.unity-scroller--horizontal {
+ height: 6px; /* 슬림한 높이 */
+ margin-bottom: 4px;
+ margin-right: 0px;
+}
+
+/* 가로 스크롤바 트랙 (배경) */
+.unity-scroller--horizontal .unity-base-slider__tracker {
+ background-color: rgba(255, 255, 255, 0); /* 흰색 배경 */
+ border-width: 0;
+}
+
+/* 가로 스크롤바 드래거 컨테이너 위치 조정 */
+.unity-scroller--horizontal .unity-base-slider__drag-container {
+ top: 0;
+ bottom: 0;
+}
+
+/* 가로 스크롤바 드래거 (핸들) */
+.unity-scroller--horizontal .unity-base-slider__dragger {
+ background-color: rgb(216, 216, 216); /* 밝은 회색 */
+ border-width: 0;
+ border-radius: 3px; /* 둥근 모서리 */
+ height: 6px;
+ top: 0;
+}
+
+/* 가로 스크롤바 화살표 버튼 숨김 */
+.unity-scroller--horizontal .unity-repeat-button {
+ display: none;
+ width: 0;
+ height: 0;
+ min-width: 0;
+ min-height: 0;
+}
+
+/* 가로 스크롤바 슬라이더 마진 제거 */
+.unity-scroller--horizontal .unity-slider {
+ margin: 0;
+}
+
+/* 가로 스크롤바 입력 필드 크기 조정 */
+.unity-scroller--horizontal .unity-base-field__input {
+ height: 6px;
+ min-height: 6px;
+}
diff --git a/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uss.meta b/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uss.meta
new file mode 100644
index 00000000..9b70be23
--- /dev/null
+++ b/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uss.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b0076250b40d2ac45ab1bff4cd47920c
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
+ disableValidation: 0
diff --git a/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uxml b/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uxml
new file mode 100644
index 00000000..0f91897d
--- /dev/null
+++ b/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uxml
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uxml.meta b/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uxml.meta
new file mode 100644
index 00000000..97fc9fc7
--- /dev/null
+++ b/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 47c61b579b8a69e4883b732447fa6059
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
diff --git a/Assets/Resources/UIToolkit/List/UIToolkitTreeListItem.uxml b/Assets/Resources/UIToolkit/List/UIToolkitTreeListItem.uxml
new file mode 100644
index 00000000..13c9e85b
--- /dev/null
+++ b/Assets/Resources/UIToolkit/List/UIToolkitTreeListItem.uxml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Assets/Resources/UIToolkit/List/UIToolkitTreeListItem.uxml.meta b/Assets/Resources/UIToolkit/List/UIToolkitTreeListItem.uxml.meta
new file mode 100644
index 00000000..15d51613
--- /dev/null
+++ b/Assets/Resources/UIToolkit/List/UIToolkitTreeListItem.uxml.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 87efc218ceca98347841e1e40ae18e7f
+ScriptedImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 2
+ userData:
+ assetBundleName:
+ assetBundleVariant:
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
diff --git a/Assets/Scripts/UVC/UIToolkit.meta b/Assets/Scripts/UVC/UIToolkit.meta
new file mode 100644
index 00000000..0908f95c
--- /dev/null
+++ b/Assets/Scripts/UVC/UIToolkit.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a5169ad85a612864eac1a963b0b7372d
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/UVC/UIToolkit/List.meta b/Assets/Scripts/UVC/UIToolkit/List.meta
new file mode 100644
index 00000000..76a65fce
--- /dev/null
+++ b/Assets/Scripts/UVC/UIToolkit/List.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: fee30b3694322a54fae6f9b8904d4866
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/UVC/UIToolkit/List/UIToolkitTreeList.cs b/Assets/Scripts/UVC/UIToolkit/List/UIToolkitTreeList.cs
new file mode 100644
index 00000000..274834b7
--- /dev/null
+++ b/Assets/Scripts/UVC/UIToolkit/List/UIToolkitTreeList.cs
@@ -0,0 +1,623 @@
+#nullable enable
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using UnityEngine.UIElements;
+
+namespace UVC.UIToolkit.List
+{
+ ///
+ /// 계층적 트리 구조를 표시하는 커스텀 UI Toolkit 컴포넌트입니다.
+ ///
+ /// 개요:
+ ///
+ /// TreeList는 Unity UI Toolkit의 TreeView를 래핑하여 검색, 가시성 토글,
+ /// 닫기 기능 등을 제공하는 재사용 가능한 컴포넌트입니다.
+ /// UXML 파일(TreeList.uxml, TreeListItem.uxml)과 함께 사용됩니다.
+ ///
+ ///
+ /// 주요 기능:
+ ///
+ /// - 계층적 트리 구조 표시 (펼치기/접기 지원)
+ /// - 실시간 검색 필터링
+ /// - 항목별 가시성(눈 아이콘) 토글
+ /// - 선택 이벤트 처리
+ ///
+ ///
+ /// UXML에서 사용:
+ ///
+ ///
+ ///
+ ///
+ /// 코드에서 사용:
+ ///
+ /// var treeList = root.Q();
+ /// treeList.OnSelectionChanged += (item) => Debug.Log($"선택: {item.name}");
+ /// treeList.OnVisibilityChanged += (item) => model.SetActive(item.id, item.IsVisible);
+ /// treeList.SetData(treeItems);
+ ///
+ ///
+ /// 관련 리소스:
+ ///
+ /// - Resources/UIToolkit/List/UIToolkitTreeList.uxml - 메인 레이아웃
+ /// - Resources/UIToolkit/List/UIToolkitTreeListItem.uxml - 개별 항목 템플릿
+ ///
+ ///
+ public partial class UIToolkitTreeList : VisualElement, IDisposable
+ {
+ #region IDisposable
+ private bool _disposed = false;
+ #endregion
+ #region 상수 (Constants)
+ /// 메인 UXML 파일 경로 (Resources 폴더 기준)
+ private const string UXML_PATH = "SHI/Modal/TreeList";
+
+ #endregion
+
+ #region UI 컴포넌트 참조 (UI Component References)
+ /// 검색어 입력 필드
+ private TextField? _searchField;
+
+ /// Unity UI Toolkit의 TreeView 컴포넌트
+ private TreeView? _treeView;
+
+ /// 트리 리스트 닫기 버튼
+ private Button? _closeButton;
+
+ /// 검색어 지우기 버튼
+ private Button? _clearButton;
+ #endregion
+
+ #region 내부 데이터 (Internal Data)
+
+
+ ///
+ /// 원본 루트 데이터입니다.
+ /// 검색 필터 해제 시 원래 데이터로 복원하는 데 사용됩니다.
+ ///
+ private List _originalRoots = new();
+
+ ///
+ /// TreeView에 바인딩되는 데이터 소스입니다.
+ /// TreeViewItemData는 Unity의 TreeView가 요구하는 래퍼 타입입니다.
+ ///
+ private List>? _rootData;
+
+ ///
+ /// 항목 ID 자동 생성을 위한 시드 값입니다.
+ /// SetData() 호출 시 id가 0인 항목에 순차적으로 ID를 할당합니다.
+ ///
+ private int _idSeed = 1;
+
+ ///
+ /// 이전에 선택된 항목입니다.
+ /// 선택 해제 이벤트 발송에 사용됩니다.
+ ///
+ private UIToolkitTreeListItemData? _previouslySelectedItem;
+ #endregion
+
+ #region 외부 이벤트 (Public Events)
+ ///
+ /// 항목의 가시성(눈 아이콘)이 변경될 때 발생합니다.
+ /// 3D 모델의 GameObject 활성화/비활성화에 연동합니다.
+ ///
+ public event Action? OnVisibilityChanged;
+
+ ///
+ /// 항목 선택 상태가 변경될 때 발생합니다.
+ /// 선택 및 선택 해제 모두에서 발생하며, item.isSelected로 구분합니다.
+ ///
+ public event Action? OnSelectionChanged;
+
+ ///
+ /// 트리 리스트가 닫힐 때(숨겨질 때) 발생합니다.
+ /// 닫기 버튼 클릭 시 트리거됩니다.
+ ///
+ public event Action? OnClosed;
+ #endregion
+
+ #region 생성자 (Constructor)
+ ///
+ /// TreeList 컴포넌트를 초기화합니다.
+ /// UXML 템플릿을 로드하고 내부 컴포넌트를 설정합니다.
+ ///
+ public TreeList()
+ {
+ // 1. 메인 UXML 로드 및 복제
+ // CloneTree(this)로 UXML 내용이 이 클래스의 자식으로 추가됨
+ var visualTree = Resources.Load(UXML_PATH);
+ if (visualTree == null)
+ {
+ Debug.LogError($"[TreeMenu] UXML not found at: {UXML_PATH}");
+ return;
+ }
+ visualTree!.CloneTree(this);
+
+
+ // 2. 자식 요소 참조 획득 (UXML의 name 속성으로 찾음)
+ _searchField = this.Q("search-field");
+ _treeView = this.Q("main-tree-view");
+ _closeButton = this.Q