UTKTreeListWindow 개발 중
This commit is contained in:
@@ -1,130 +1,73 @@
|
||||
/*
|
||||
* TreeList.uss - TreeList 컴포넌트 스타일시트
|
||||
*
|
||||
* [개요]
|
||||
* TreeList.uxml과 TreeListItem.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) - 흰색
|
||||
*
|
||||
* [연관 파일]
|
||||
* - TreeList.uxml : 메인 레이아웃
|
||||
* - TreeListItem.uxml : 개별 항목 템플릿
|
||||
* - TreeList.cs : C# 컨트롤러
|
||||
*/
|
||||
|
||||
/* ===================================
|
||||
메인 컨테이너 스타일
|
||||
사이드 패널 전체를 감싸는 컨테이너
|
||||
=================================== */
|
||||
.tree-menu-container {
|
||||
background-color: rgb(40, 44, 52); /* 어두운 회색 배경 */
|
||||
flex-grow: 1; /* 부모 영역 채우기 */
|
||||
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; /* 고정 너비 */
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
/* ===================================
|
||||
검색 입력 필드 스타일
|
||||
흰색 배경의 둥근 입력창
|
||||
=================================== */
|
||||
.search-field {
|
||||
margin-bottom: 20px;
|
||||
background-color: rgb(255, 255, 255); /* 흰색 배경 */
|
||||
border-radius: 4px; /* 둥근 모서리 */
|
||||
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-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-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-item-indent-width: 10;
|
||||
}
|
||||
|
||||
/* 펼침/접기 토글 아이콘 컨테이너 */
|
||||
#unity-tree-view__item-toggle > VisualElement > VisualElement {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
width: 22px; /* 토글 아이콘 너비 */
|
||||
width: 22px;
|
||||
}
|
||||
|
||||
/* 펼침/접기 토글 버튼 */
|
||||
.unity-tree-view__item-toggle {
|
||||
margin-right: 5px; /* 라벨과의 간격 */
|
||||
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; /* 테두리 없음 */
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
border-width: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-top: 0;
|
||||
@@ -137,52 +80,42 @@
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
margin-left: 0;
|
||||
flex-shrink: 0; /* 크기 축소 방지 */
|
||||
background-image: resource('SHI/Images/icon_visibility_on_64'); /* 기본: 보이는 상태 */
|
||||
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; /* 슬림한 너비 */
|
||||
width: 6px;
|
||||
margin-right: 4px;
|
||||
margin-bottom: 0px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* 세로 스크롤바 트랙 (배경) */
|
||||
.unity-scroller--vertical .unity-base-slider__tracker {
|
||||
background-color: rgba(255, 255, 255, 0); /* 흰색 배경 */
|
||||
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); /* 밝은 회색 */
|
||||
background-color: rgb(216, 216, 216);
|
||||
border-width: 0;
|
||||
border-radius: 3px; /* 둥근 모서리 */
|
||||
border-radius: 3px;
|
||||
width: 6px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* 세로 스크롤바 화살표 버튼 숨김 */
|
||||
.unity-scroller--vertical .unity-repeat-button {
|
||||
display: none;
|
||||
width: 0;
|
||||
@@ -191,49 +124,39 @@
|
||||
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; /* 슬림한 높이 */
|
||||
height: 6px;
|
||||
margin-bottom: 4px;
|
||||
margin-right: 0px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* 가로 스크롤바 트랙 (배경) */
|
||||
.unity-scroller--horizontal .unity-base-slider__tracker {
|
||||
background-color: rgba(255, 255, 255, 0); /* 흰색 배경 */
|
||||
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); /* 밝은 회색 */
|
||||
background-color: rgb(216, 216, 216);
|
||||
border-width: 0;
|
||||
border-radius: 3px; /* 둥근 모서리 */
|
||||
border-radius: 3px;
|
||||
height: 6px;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/* 가로 스크롤바 화살표 버튼 숨김 */
|
||||
.unity-scroller--horizontal .unity-repeat-button {
|
||||
display: none;
|
||||
width: 0;
|
||||
@@ -242,12 +165,10 @@
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
/* 가로 스크롤바 슬라이더 마진 제거 */
|
||||
.unity-scroller--horizontal .unity-slider {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* 가로 스크롤바 입력 필드 크기 조정 */
|
||||
.unity-scroller--horizontal .unity-base-field__input {
|
||||
height: 6px;
|
||||
min-height: 6px;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ebf477f3ba4991c439a8729dc21abac7
|
||||
guid: c4f4597de9fcbbf42b0ae7a69db1d5c3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
9
Assets/Resources/UIToolkit/Document/DynamicDocument.uxml
Normal file
9
Assets/Resources/UIToolkit/Document/DynamicDocument.uxml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ui:UXML
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:ui="UnityEngine.UIElements"
|
||||
xmlns:uie="UnityEditor.UIElements"
|
||||
xsi:noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd"
|
||||
>
|
||||
|
||||
</ui:UXML>
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 388c12cc6f747a3409725653495a6501
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
9
Assets/Resources/UIToolkit/Document/ModalDocument.uxml
Normal file
9
Assets/Resources/UIToolkit/Document/ModalDocument.uxml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ui:UXML
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:ui="UnityEngine.UIElements"
|
||||
xmlns:uie="UnityEditor.UIElements"
|
||||
xsi:noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd"
|
||||
>
|
||||
|
||||
</ui:UXML>
|
||||
10
Assets/Resources/UIToolkit/Document/ModalDocument.uxml.meta
Normal file
10
Assets/Resources/UIToolkit/Document/ModalDocument.uxml.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ad0294e546cb18409d368046997e670
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
9
Assets/Resources/UIToolkit/Document/StaticDocument.uxml
Normal file
9
Assets/Resources/UIToolkit/Document/StaticDocument.uxml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ui:UXML
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:ui="UnityEngine.UIElements"
|
||||
xmlns:uie="UnityEditor.UIElements"
|
||||
xsi:noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd"
|
||||
>
|
||||
|
||||
</ui:UXML>
|
||||
10
Assets/Resources/UIToolkit/Document/StaticDocument.uxml.meta
Normal file
10
Assets/Resources/UIToolkit/Document/StaticDocument.uxml.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d3024917e8d4b546943ec3f7b03d9e4
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
BIN
Assets/Resources/UIToolkit/Images/btn_close_16.png
Normal file
BIN
Assets/Resources/UIToolkit/Images/btn_close_16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 192 B |
117
Assets/Resources/UIToolkit/Images/btn_close_16.png.meta
Normal file
117
Assets/Resources/UIToolkit/Images/btn_close_16.png.meta
Normal file
@@ -0,0 +1,117 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22696bb0676cc944586f52b7c9068566
|
||||
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:
|
||||
|
Before Width: | Height: | Size: 209 B After Width: | Height: | Size: 209 B |
@@ -1,254 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
||||
<Style src="project://database/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uss?fileID=7433441132597879392&guid=a1b1f50d423b463408e1f540fb4acfe9&type=3#UIToolkitTreeList" />
|
||||
<ui:VisualElement name="container" class="tree-menu-container">
|
||||
<ui:VisualElement name="header" style="flex-direction: row; margin-bottom: 5px; justify-content: space-between;">
|
||||
<ui:Label text="모델 검색" style="color: white; -unity-font-style: normal; font-size: 20px; -unity-font-definition: resource('Fonts/Pretendard/Pretendard-Bold');" />
|
||||
<ui:Button name="hide-btn" style="width: 22px; height: 22px; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; background-color: rgba(188, 188, 188, 0); background-image: resource('UIToolkit/Images/btn_close_22'); align-self: center; align-items: auto; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0;" />
|
||||
</ui:VisualElement>
|
||||
<ui:TextField name="search-field" placeholder-text="검색어를 입력하세요." class="search-field">
|
||||
<ui:Button name="clear-btn" style="width: 18px; height: 18px; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0; background-color: rgba(255, 255, 255, 0); background-image: resource('UIToolkit/Images/btn_cancel_64'); margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; align-self: center; position: absolute; right: 26px; -unity-background-image-tint-color: rgb(180, 180, 180);" />
|
||||
<ui:VisualElement style="flex-grow: 1; position: absolute; right: 6px; width: 16px; height: 17px; justify-content: center; align-items: auto; align-self: center; background-image: resource('UIToolkit/Images/icon_search_16x17');" />
|
||||
</ui:TextField>
|
||||
<ui:TreeView name="main-tree-view" view-data-key="model-tree-view" fixed-item-height="32" auto-expand="true" item-template="project://database/Assets/Resources/UIToolkit/List/UIToolkitTreeListItem.uxml?fileID=9197481963319205126&guid=c5b3acae6c4669946b6e6b8b36d82e88&type=3#UIToolkitTreeListItem" horizontal-scrolling="true" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@@ -1,39 +0,0 @@
|
||||
<!--
|
||||
UIToolkitTreeListItem.uxml - TreeView 개별 항목 템플릿
|
||||
|
||||
[개요]
|
||||
UIToolkitTreeList의 각 항목(노드)을 표시하는 템플릿입니다.
|
||||
UIToolkitTreeList.cs의 MakeItem()에서 이 템플릿을 복제하여 사용합니다.
|
||||
|
||||
[UI 구조]
|
||||
item-root (tree-item-container)
|
||||
├── item-label - 항목 이름 표시 라벨
|
||||
└── visibility-btn - 가시성 토글 버튼 (눈 아이콘)
|
||||
|
||||
[바인딩]
|
||||
- item-label.text : TreeListItemData.name에 바인딩
|
||||
- visibility-btn.class : IsVisible 상태에 따라 visibility-on/off 클래스 토글
|
||||
|
||||
[이벤트]
|
||||
- visibility-btn 클릭 시 해당 항목과 하위 항목의 3D 모델 가시성 토글
|
||||
|
||||
[스타일]
|
||||
- UIToolkitTreeList.uss의 .visibility-toggle 클래스 적용
|
||||
- 높이 32px 고정 (UIToolkitTreeList.uxml의 fixed-item-height와 일치)
|
||||
|
||||
[연관 파일]
|
||||
- UIToolkitTreeList.uxml : 부모 컨테이너
|
||||
- UIToolkitTreeList.uss : 스타일시트
|
||||
- UIToolkitTreeList.cs : 바인딩 및 이벤트 처리
|
||||
- TreeListItemData.cs : 데이터 모델
|
||||
-->
|
||||
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
||||
<Style src="project://database/Assets/Resources/UIToolkit/List/UIToolkitTreeList.uss?fileID=7433441132597879392&guid=a1b1f50d423b463408e1f540fb4acfe9&type=3#UIToolkitTreeList" />
|
||||
<!-- 항목 루트 컨테이너: 가로 배치, 라벨과 버튼 양 끝 정렬 -->
|
||||
<ui:VisualElement name="item-root" class="tree-item-container" style="flex-direction: row; justify-content: space-between; height: 32px; padding-left: 0; padding-right: 8px; align-items: center;">
|
||||
<!-- 항목 이름 라벨: TreeListItemData.name에 바인딩됨 -->
|
||||
<ui:Label name="item-label" text="Item Name" class="item-label-style" style="flex-grow: 1; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-left: 4px; padding-top: 0; padding-bottom: 0; padding-right: 4px; color: rgb(255, 255, 255); font-size: 14px;" />
|
||||
<!-- 가시성 토글 버튼: 클릭 시 3D 모델 표시/숨김 전환 -->
|
||||
<ui:Button name="visibility-btn" class="visibility-toggle" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
7
Assets/Resources/UIToolkit/List/UTKTreeListItem.uxml
Normal file
7
Assets/Resources/UIToolkit/List/UTKTreeListItem.uxml
Normal file
@@ -0,0 +1,7 @@
|
||||
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
||||
<Style src="project://database/Assets/Resources/UIToolkit/Window/UTKTreeListWindow.uss?fileID=7433441132597879392&guid=b0076250b40d2ac45ab1bff4cd47920c&type=3#UTKTreeListWindow" />
|
||||
<ui:VisualElement name="item-root" class="tree-item-container" style="flex-direction: row; justify-content: space-between; height: 18px; padding-left: 0; padding-right: 8px; align-items: center;">
|
||||
<ui:Label name="item-label" text="Item Name" class="item-label-style" style="flex-grow: 1; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-left: 4px; padding-top: 0; padding-bottom: 0; padding-right: 4px; color: rgb(204, 204, 204); font-size: 11px; -unity-font-definition: resource('Fonts/Pretendard/Pretendard-Bold');" />
|
||||
<ui:Button name="visibility-btn" class="visibility-toggle" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
8
Assets/Resources/UIToolkit/Settings.meta
Normal file
8
Assets/Resources/UIToolkit/Settings.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a825db9fef7d0b444add478047ac30ff
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,5 @@
|
||||
@import url("unity-theme://default");
|
||||
|
||||
@import url("UTKDefaultStyle.uss");
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3658c4df19569594295f511142185317
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 12388, guid: 0000000000000000e000000000000000, type: 0}
|
||||
disableValidation: 0
|
||||
202
Assets/Resources/UIToolkit/Settings/UTKDefaultStyle.uss
Normal file
202
Assets/Resources/UIToolkit/Settings/UTKDefaultStyle.uss
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* ===================================
|
||||
* DefaultStyle.uss
|
||||
* UI Toolkit 공통 기본 스타일시트
|
||||
* ===================================
|
||||
*
|
||||
* 이 파일은 UI Toolkit 컴포넌트들의 기본 스타일을 정의합니다.
|
||||
* Unity의 기본 UI 요소들을 커스터마이징하여 일관된 디자인을 적용합니다.
|
||||
*
|
||||
* 주요 스타일 섹션:
|
||||
* 1. 드롭다운 팝업 스타일
|
||||
* 2. TreeView 항목 스타일
|
||||
* 3. 컬렉션 뷰 항목 스타일 (선택, 호버)
|
||||
* 4. 수직 스크롤바 스타일
|
||||
* 5. 수평 스크롤바 스타일
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* 전체 텍스트 요소에 적용 */
|
||||
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Regular');
|
||||
|
||||
/* 스크롤바 드래거 색상 변수 (코드에서 참조) */
|
||||
--scroller-dragger-normal: #333333;
|
||||
--scroller-dragger-hover: #525252;
|
||||
--scroller-dragger-active: #333333;
|
||||
|
||||
/* 스크롤바 트래커(배경) 색상 변수 (코드에서 참조) */
|
||||
--scroller-tracker-normal: rgba(0, 0, 0, 0);
|
||||
--scroller-tracker-hover: rgba(26, 26, 26, 0);
|
||||
}
|
||||
|
||||
/* ===================================
|
||||
드롭다운 팝업 아이템 스타일
|
||||
- DropdownField의 팝업 메뉴 항목 스타일
|
||||
=================================== */
|
||||
|
||||
|
||||
|
||||
/* 드롭다운 개별 항목 - 패딩 제거 및 어두운 배경색 적용 */
|
||||
.unity-base-dropdown__item {
|
||||
padding: 0px;
|
||||
background-color: rgb(40, 44, 52); /* 어두운 회색 배경 */
|
||||
color: rgb(255, 255, 255); /* 흰색 텍스트 */
|
||||
}
|
||||
|
||||
/* 드롭다운 내부 컨테이너 - 패딩 제거 */
|
||||
.unity-base-dropdown__container-inner {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
|
||||
/* ===================================
|
||||
TreeView 항목 스타일
|
||||
- TreeView의 펼치기/접기 토글 버튼 스타일
|
||||
=================================== */
|
||||
|
||||
/* TreeView 펼치기/접기 화살표 토글 - 우측 여백 추가 */
|
||||
.unity-tree-view__item-toggle {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
|
||||
/* ===================================
|
||||
컬렉션 뷰 항목 스타일
|
||||
- ListView, TreeView 등 컬렉션 뷰의 항목 상태별 스타일
|
||||
=================================== */
|
||||
|
||||
/* 기본 상태 - 투명 배경 */
|
||||
.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);
|
||||
}
|
||||
|
||||
|
||||
/* ===================================
|
||||
수직 스크롤바 스타일
|
||||
- 기본 Unity 스크롤바를 슬림하고 미니멀하게 커스터마이징
|
||||
|
||||
[주의] 스크롤바 드래거/트래커의 hover/active 색상은 USS :hover/:active
|
||||
pseudo-class가 제대로 동작하지 않습니다.
|
||||
드래거는 마우스 이벤트를 직접 받지 않고 트래커가 받기 때문입니다.
|
||||
hover/active 색상 변경이 필요하면 UTKTreeListWindow.cs의
|
||||
SetupDraggerEvents() 메서드처럼 코드로 MouseEnterEvent/MouseLeaveEvent 등을
|
||||
등록하여 구현해야 합니다.
|
||||
=================================== */
|
||||
|
||||
/* 수직 스크롤바 컨테이너 - 폭 6px의 슬림한 스크롤바 */
|
||||
.unity-scroller--vertical {
|
||||
width: 6px;
|
||||
margin-right: 4px;
|
||||
margin-bottom: 0;
|
||||
background-color: rgba(30, 30, 30, 0); /* 스크롤바 영역 배경색 */
|
||||
}
|
||||
|
||||
/* 스크롤바 트랙 (배경) - 반투명 어두운 배경 */
|
||||
.unity-scroller--vertical .unity-base-slider__tracker {
|
||||
background-color: var(--scroller-tracker-normal);
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
/* 드래그 컨테이너 - 좌우 정렬 */
|
||||
.unity-scroller--vertical .unity-base-slider__drag-container {
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
/* 드래거 (스크롤 핸들) - 기본 상태 */
|
||||
.unity-scroller--vertical .unity-base-slider__dragger {
|
||||
background-color: var(--scroller-dragger-normal);
|
||||
border-width: 0;
|
||||
border-radius: 3px; /* 둥근 모서리 */
|
||||
width: 6px;
|
||||
left: 0;
|
||||
transition-duration: 0.15s; /* 부드러운 전환 효과 */
|
||||
transition-property: background-color;
|
||||
}
|
||||
|
||||
/* 상하 화살표 버튼 - 완전히 숨김 처리 */
|
||||
.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;
|
||||
}
|
||||
|
||||
/* 입력 영역 - 폭 6px로 고정 */
|
||||
.unity-scroller--vertical .unity-base-field__input {
|
||||
width: 6px;
|
||||
min-width: 6px;
|
||||
}
|
||||
|
||||
|
||||
/* ===================================
|
||||
수평 스크롤바 스타일
|
||||
- 수직 스크롤바와 동일한 디자인을 수평으로 적용
|
||||
=================================== */
|
||||
|
||||
/* 수평 스크롤바 컨테이너 - 높이 6px의 슬림한 스크롤바 */
|
||||
.unity-scroller--horizontal {
|
||||
height: 6px;
|
||||
margin-bottom: 4px;
|
||||
margin-right: 0;
|
||||
background-color: rgba(30, 30, 30, 0); /* 스크롤바 영역 배경색 */
|
||||
}
|
||||
|
||||
/* 스크롤바 트랙 (배경) - 반투명 어두운 배경 */
|
||||
.unity-scroller--horizontal .unity-base-slider__tracker {
|
||||
background-color: var(--scroller-tracker-normal);
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
/* 드래그 컨테이너 - 상하 정렬 */
|
||||
.unity-scroller--horizontal .unity-base-slider__drag-container {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
/* 드래거 (스크롤 핸들) - 기본 상태 */
|
||||
.unity-scroller--horizontal .unity-base-slider__dragger {
|
||||
background-color: var(--scroller-dragger-normal);
|
||||
border-width: 0;
|
||||
border-radius: 3px; /* 둥근 모서리 */
|
||||
height: 6px;
|
||||
top: 0;
|
||||
transition-duration: 0.15s; /* 부드러운 전환 효과 */
|
||||
transition-property: background-color;
|
||||
}
|
||||
|
||||
/* 좌우 화살표 버튼 - 완전히 숨김 처리 */
|
||||
.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;
|
||||
}
|
||||
|
||||
/* 입력 영역 - 높이 6px로 고정 */
|
||||
.unity-scroller--horizontal .unity-base-field__input {
|
||||
height: 6px;
|
||||
min-height: 6px;
|
||||
}
|
||||
11
Assets/Resources/UIToolkit/Settings/UTKDefaultStyle.uss.meta
Normal file
11
Assets/Resources/UIToolkit/Settings/UTKDefaultStyle.uss.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2bc5215860a4ca43895ba1a89f329e0
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
|
||||
disableValidation: 0
|
||||
49
Assets/Resources/UIToolkit/Settings/UTKSettings.asset
Normal file
49
Assets/Resources/UIToolkit/Settings/UTKSettings.asset
Normal file
@@ -0,0 +1,49 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 19101, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Name: UTKSettings
|
||||
m_EditorClassIdentifier: UnityEngine.dll::UnityEngine.UIElements.PanelSettings
|
||||
themeUss: {fileID: -4733365628477956816, guid: 3658c4df19569594295f511142185317, type: 3}
|
||||
m_DisableNoThemeWarning: 0
|
||||
m_TargetTexture: {fileID: 0}
|
||||
m_RenderMode: 0
|
||||
m_ColliderUpdateMode: 0
|
||||
m_ColliderIsTrigger: 1
|
||||
m_ScaleMode: 0
|
||||
m_ReferenceSpritePixelsPerUnit: 100
|
||||
m_PixelsPerUnit: 100
|
||||
m_Scale: 1
|
||||
m_ReferenceDpi: 96
|
||||
m_FallbackDpi: 96
|
||||
m_ReferenceResolution: {x: 1200, y: 800}
|
||||
m_ScreenMatchMode: 0
|
||||
m_Match: 0
|
||||
m_SortingOrder: 10
|
||||
m_TargetDisplay: 0
|
||||
m_BindingLogLevel: 0
|
||||
m_ClearDepthStencil: 1
|
||||
m_ClearColor: 0
|
||||
m_ColorClearValue: {r: 0, g: 0, b: 0, a: 0}
|
||||
m_VertexBudget: 0
|
||||
m_DynamicAtlasSettings:
|
||||
m_MinAtlasSize: 64
|
||||
m_MaxAtlasSize: 4096
|
||||
m_MaxSubTextureSize: 64
|
||||
m_ActiveFilters: -1
|
||||
m_AtlasBlitShader: {fileID: 9101, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_DefaultShader: {fileID: 9100, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_SDFShader: {fileID: 19011, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_BitmapShader: {fileID: 9001, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_SpriteShader: {fileID: 19012, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ICUDataAsset: {fileID: 0}
|
||||
forceGammaRendering: 0
|
||||
textSettings: {fileID: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ad7007b08a97b54d927c352279a18b6
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Resources/UIToolkit/Window.meta
Normal file
8
Assets/Resources/UIToolkit/Window.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a4dcd369eac43a45b4170187d18edd8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
100
Assets/Resources/UIToolkit/Window/UTKTreeListWindow.uss
Normal file
100
Assets/Resources/UIToolkit/Window/UTKTreeListWindow.uss
Normal file
@@ -0,0 +1,100 @@
|
||||
/* UTKTreeListWindow 루트 요소 - 부모 높이를 꽉 채움 */
|
||||
UTKTreeListWindow {
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.tree-menu-container {
|
||||
background-color: rgb(37, 37, 38);
|
||||
flex-grow: 1; /* 부모 영역을 채우도록 확장 */
|
||||
height: 100%; /* 높이 100%로 꽉 채움 */
|
||||
align-self: flex-start; /* 왼쪽 정렬 */
|
||||
padding: 5px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 25px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.search-field {
|
||||
margin-bottom: 20px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 4px;
|
||||
height: 24px;
|
||||
width: auto;
|
||||
margin-top: 0;
|
||||
margin-right: 0;
|
||||
margin-left: 0;
|
||||
|
||||
}
|
||||
|
||||
#search-field > #unity-text-input {
|
||||
padding-top: 4px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 4px;
|
||||
padding-left: 4px;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-width: 0;
|
||||
border-right-width: 0;
|
||||
border-bottom-width: 0;
|
||||
border-left-width: 0;
|
||||
background-color: rgb(60, 60, 60);
|
||||
font-size: 13px;
|
||||
color: rgb(204, 204, 204);
|
||||
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
||||
--unity-cursor-color: rgb(255, 255, 255); /* 캐럿(커서) 색상 흰색 */
|
||||
|
||||
}
|
||||
|
||||
#search-field .unity-base-text-field__input--placeholder {
|
||||
-unity-font-style: italic;
|
||||
}
|
||||
|
||||
#unity-checkmark {
|
||||
-unity-background-image-tint-color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
#main-tree-view {
|
||||
/* 들여쓰기 폭 설정 */
|
||||
--unity-item-indent-width: 10;
|
||||
}
|
||||
|
||||
#unity-tree-view__item-toggle > VisualElement > VisualElement {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
width: 22px;
|
||||
}
|
||||
|
||||
.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');
|
||||
}
|
||||
|
||||
|
||||
13
Assets/Resources/UIToolkit/Window/UTKTreeListWindow.uxml
Normal file
13
Assets/Resources/UIToolkit/Window/UTKTreeListWindow.uxml
Normal file
@@ -0,0 +1,13 @@
|
||||
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
||||
<Style src="project://database/Assets/Resources/UIToolkit/Window/UTKTreeListWindow.uss?fileID=7433441132597879392&guid=b0076250b40d2ac45ab1bff4cd47920c&type=3#UTKTreeListWindow" />
|
||||
<ui:VisualElement name="container" class="tree-menu-container">
|
||||
<ui:VisualElement name="header" style="flex-direction: row; margin-bottom: 5px; justify-content: space-between; margin-top: 0;">
|
||||
<ui:Label text="HIERARCHY" style="color: rgb(204, 204, 204); -unity-font-style: normal; font-size: 11px; -unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium'); margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; height: 24px; -unity-text-align: middle-left;" />
|
||||
<ui:Button name="close-btn" style="width: 22px; height: 22px; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; background-color: rgba(188, 188, 188, 0); background-image: resource('UIToolkit/Images/btn_close_22'); align-self: center; align-items: auto; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0; display: none;" />
|
||||
</ui:VisualElement>
|
||||
<ui:TextField name="search-field" placeholder-text="검색" class="search-field" style="height: 24px; margin-bottom: 12px;">
|
||||
<ui:Button name="clear-btn" style="width: 16px; height: 16px; border-top-width: 0; border-right-width: 0; border-bottom-width: 0; border-left-width: 0; background-color: rgba(255, 255, 255, 0); background-image: resource('UIToolkit/Images/btn_close_16'); margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; align-self: center; position: absolute; right: 4px; -unity-background-image-tint-color: rgb(180, 180, 180);" />
|
||||
</ui:TextField>
|
||||
<ui:TreeView name="main-tree-view" view-data-key="model-tree-view" fixed-item-height="18" auto-expand="false" item-template="project://database/Assets/Resources/UIToolkit/List/UTKTreeListItem.uxml?fileID=9197481963319205126&guid=87efc218ceca98347841e1e40ae18e7f&type=3#UTKTreeListItem" horizontal-scrolling="true" selection-type="Multiple" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@@ -471,17 +471,23 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Version: 3
|
||||
m_UsePipelineSettings: 1
|
||||
m_AdditionalLightsShadowResolutionTier: 2
|
||||
m_LightLayerMask: 1
|
||||
m_RenderingLayers: 1
|
||||
m_CustomShadowLayers: 0
|
||||
m_ShadowLayerMask: 1
|
||||
m_ShadowRenderingLayers: 1
|
||||
m_LightCookieSize: {x: 1, y: 1}
|
||||
m_LightCookieOffset: {x: 0, y: 0}
|
||||
m_SoftShadowQuality: 0
|
||||
m_RenderingLayersMask:
|
||||
serializedVersion: 0
|
||||
m_Bits: 1
|
||||
m_ShadowRenderingLayersMask:
|
||||
serializedVersion: 0
|
||||
m_Bits: 1
|
||||
m_Version: 4
|
||||
m_LightLayerMask: 1
|
||||
m_ShadowLayerMask: 1
|
||||
m_RenderingLayers: 1
|
||||
m_ShadowRenderingLayers: 1
|
||||
--- !u!1 &2136621999
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -582,6 +588,14 @@ PrefabInstance:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 1218340765}
|
||||
m_Modifications:
|
||||
- target: {fileID: 798050974035107396, guid: 55334174237ec37438ae05ee0b89079a, type: 3}
|
||||
propertyPath: m_Pivot.y
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 798050974035107396, guid: 55334174237ec37438ae05ee0b89079a, type: 3}
|
||||
propertyPath: m_AnchoredPosition.y
|
||||
value: 12
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1574318677252675885, guid: 55334174237ec37438ae05ee0b89079a, type: 3}
|
||||
propertyPath: m_Pivot.x
|
||||
value: 0
|
||||
|
||||
8
Assets/Sample/UIToolkit.meta
Normal file
8
Assets/Sample/UIToolkit.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a42e38042c76a7c478b6f7ef53780744
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
145
Assets/Sample/UIToolkit/UTKTreeListWindowSample.cs
Normal file
145
Assets/Sample/UIToolkit/UTKTreeListWindowSample.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UVC.UIToolkit.List;
|
||||
using UVC.UIToolkit.Window;
|
||||
|
||||
/// <summary>
|
||||
/// UTKTreeListWindow의 기능을 테스트하기 위한 샘플 MonoBehaviour입니다.
|
||||
/// 계층적 트리 데이터를 생성하고 다양한 이벤트 핸들러를 등록하여 동작을 확인합니다.
|
||||
/// </summary>
|
||||
public class UTKTreeListWindowSample : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
public UIDocument uiDocument;
|
||||
|
||||
private UTKTreeListWindow treeListWindow;
|
||||
|
||||
void Start()
|
||||
{
|
||||
|
||||
uiDocument ??= GetComponent<UIDocument>();
|
||||
|
||||
// UIDocument에서 UTKTreeListWindow 인스턴스 생성해서 할당
|
||||
treeListWindow = new UTKTreeListWindow();
|
||||
uiDocument.rootVisualElement.Add(treeListWindow);
|
||||
|
||||
// UTKTreeListWindow가 할당되지 않은 경우 경고
|
||||
if (treeListWindow == null)
|
||||
{
|
||||
Debug.LogWarning("[UTKTreeListWindowSample] treeListWindow가 할당되지 않았습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 테스트용 계층적 트리 데이터 생성
|
||||
CreateTestData();
|
||||
|
||||
// 이벤트 핸들러 등록
|
||||
RegisterEventHandlers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 테스트용 계층적 트리 데이터를 생성합니다.
|
||||
/// 10개의 루트 항목을 생성하고, 각 루트에 5개의 자식,
|
||||
/// 각 자식에 3개의 손자, 각 손자에 2개의 증손자를 추가합니다.
|
||||
/// </summary>
|
||||
private void CreateTestData()
|
||||
{
|
||||
// 10개의 루트 항목 생성
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
// 루트 항목 생성 (긴 이름으로 가로 스크롤 테스트)
|
||||
UTKTreeListItemData itemData = new UTKTreeListItemData { name = $"RootItem_{i}_TestLongName" };
|
||||
|
||||
// 각 루트에 5개의 자식 항목 추가
|
||||
int childCount = 5;
|
||||
for (int j = 0; j < childCount; j++)
|
||||
{
|
||||
UTKTreeListItemData childData = new UTKTreeListItemData { name = $"ChildItem_{i}_{j}_WithExtendedDescription" };
|
||||
itemData.Add(childData);
|
||||
|
||||
// 각 자식에 3개의 손자 항목 추가
|
||||
int grandChildCount = 3;
|
||||
for (int k = 0; k < grandChildCount; k++)
|
||||
{
|
||||
UTKTreeListItemData grandChildData = new UTKTreeListItemData { name = $"GrandChild_{i}_{j}_{k}_VeryLongItemNameForScrollTest" };
|
||||
childData.Add(grandChildData);
|
||||
|
||||
// 각 손자에 2개의 증손자 항목 추가
|
||||
for (int l = 0; l < 2; l++)
|
||||
{
|
||||
UTKTreeListItemData greatGrandChildData = new UTKTreeListItemData { name = $"GreatGrandChild_{i}_{j}_{k}_{l}_ExtremelyLongNameToTestHorizontalScrolling" };
|
||||
grandChildData.Add(greatGrandChildData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 루트 항목을 트리에 추가
|
||||
treeListWindow.AddItem(itemData);
|
||||
}
|
||||
|
||||
Debug.Log("[UTKTreeListWindowSample] 테스트 데이터 생성 완료: 10개 루트 항목");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UTKTreeListWindow의 이벤트 핸들러들을 등록합니다.
|
||||
/// 선택, 선택 해제, 삭제, 더블클릭, 가시성 변경 이벤트를 처리합니다.
|
||||
/// </summary>
|
||||
private void RegisterEventHandlers()
|
||||
{
|
||||
// 항목 선택 이벤트 (다중 선택 지원)
|
||||
// 사용자가 항목을 클릭하거나 SelectItem() 호출 시 발생
|
||||
treeListWindow.OnItemSelected += (List<UTKTreeListItemData> selectedItems) =>
|
||||
{
|
||||
foreach (var item in selectedItems)
|
||||
{
|
||||
Debug.Log($"[선택됨] {item.name}");
|
||||
}
|
||||
};
|
||||
|
||||
// 항목 선택 해제 이벤트 (다중 선택 지원)
|
||||
// 사용자가 다른 항목을 선택하거나 DeselectItem() 호출 시 발생
|
||||
treeListWindow.OnItemDeselected += (List<UTKTreeListItemData> deselectedItems) =>
|
||||
{
|
||||
foreach (var item in deselectedItems)
|
||||
{
|
||||
Debug.Log($"[선택 해제됨] {item.name}");
|
||||
}
|
||||
};
|
||||
|
||||
// 항목 삭제 이벤트
|
||||
// 사용자가 Delete 또는 Backspace 키를 누를 때 발생
|
||||
// 실제 삭제는 이 핸들러에서 DeleteItem()을 호출하여 수행
|
||||
treeListWindow.OnItemDeleted += (UTKTreeListItemData deletedItem) =>
|
||||
{
|
||||
Debug.Log($"[삭제 요청] {deletedItem.name}");
|
||||
// 실제로 항목을 삭제하려면 아래 주석을 해제하세요:
|
||||
// treeListWindow.DeleteItem(deletedItem);
|
||||
};
|
||||
|
||||
// 항목 더블클릭 이벤트
|
||||
// 사용자가 항목을 더블클릭하거나 Enter 키를 누를 때 발생
|
||||
treeListWindow.OnItemDoubleClicked += (UTKTreeListItemData doubleClickedItem) =>
|
||||
{
|
||||
Debug.Log($"[더블클릭] {doubleClickedItem.name}");
|
||||
};
|
||||
|
||||
// 항목 가시성 변경 이벤트
|
||||
// 사용자가 눈 아이콘 버튼을 클릭하여 가시성을 토글할 때 발생
|
||||
treeListWindow.OnItemVisibilityChanged += (UTKTreeListItemData item, bool isVisible) =>
|
||||
{
|
||||
Debug.Log($"[가시성 변경] {item.name}, IsVisible: {isVisible}");
|
||||
};
|
||||
|
||||
Debug.Log("[UTKTreeListWindowSample] 이벤트 핸들러 등록 완료");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 컴포넌트가 파괴될 때 리소스를 정리합니다.
|
||||
/// </summary>
|
||||
private void OnDestroy()
|
||||
{
|
||||
// UTKTreeListWindow의 Dispose 호출로 이벤트 핸들러 정리
|
||||
treeListWindow?.Dispose();
|
||||
}
|
||||
}
|
||||
2
Assets/Sample/UIToolkit/UTKTreeListWindowSample.cs.meta
Normal file
2
Assets/Sample/UIToolkit/UTKTreeListWindowSample.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 193bb366f0cf1094aa11baa8a5a2e32d
|
||||
496
Assets/Sample/UIToolkit/UTKTreeListWindowSample.unity
Normal file
496
Assets/Sample/UIToolkit/UTKTreeListWindowSample.unity
Normal file
@@ -0,0 +1,496 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!29 &1
|
||||
OcclusionCullingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_OcclusionBakeSettings:
|
||||
smallestOccluder: 5
|
||||
smallestHole: 0.25
|
||||
backfaceThreshold: 100
|
||||
m_SceneGUID: 00000000000000000000000000000000
|
||||
m_OcclusionCullingData: {fileID: 0}
|
||||
--- !u!104 &2
|
||||
RenderSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 10
|
||||
m_Fog: 0
|
||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||
m_FogMode: 3
|
||||
m_FogDensity: 0.01
|
||||
m_LinearFogStart: 0
|
||||
m_LinearFogEnd: 300
|
||||
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
|
||||
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
|
||||
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
|
||||
m_AmbientIntensity: 1
|
||||
m_AmbientMode: 0
|
||||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
||||
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_HaloStrength: 0.5
|
||||
m_FlareStrength: 1
|
||||
m_FlareFadeSpeed: 3
|
||||
m_HaloTexture: {fileID: 0}
|
||||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_DefaultReflectionMode: 0
|
||||
m_DefaultReflectionResolution: 128
|
||||
m_ReflectionBounces: 1
|
||||
m_ReflectionIntensity: 1
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
m_UseRadianceAmbientProbe: 0
|
||||
--- !u!157 &3
|
||||
LightmapSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 13
|
||||
m_BakeOnSceneLoad: 0
|
||||
m_GISettings:
|
||||
serializedVersion: 2
|
||||
m_BounceScale: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_EnvironmentLightingMode: 0
|
||||
m_EnableBakedLightmaps: 1
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_LightmapEditorSettings:
|
||||
serializedVersion: 12
|
||||
m_Resolution: 2
|
||||
m_BakeResolution: 40
|
||||
m_AtlasSize: 1024
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAmbientOcclusion: 0
|
||||
m_Padding: 2
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_LightmapsBakeMode: 1
|
||||
m_TextureCompression: 1
|
||||
m_ReflectionCompression: 2
|
||||
m_MixedBakeMode: 2
|
||||
m_BakeBackend: 1
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 512
|
||||
m_PVRBounces: 2
|
||||
m_PVREnvironmentSampleCount: 256
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_PVRFilteringMode: 1
|
||||
m_PVRDenoiserTypeDirect: 1
|
||||
m_PVRDenoiserTypeIndirect: 1
|
||||
m_PVRDenoiserTypeAO: 1
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVREnvironmentMIS: 1
|
||||
m_PVRCulling: 1
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 1
|
||||
m_PVRFilteringGaussRadiusAO: 1
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_LightingDataAsset: {fileID: 20201, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_LightingSettings: {fileID: 0}
|
||||
--- !u!196 &4
|
||||
NavMeshSettings:
|
||||
serializedVersion: 2
|
||||
m_ObjectHideFlags: 0
|
||||
m_BuildSettings:
|
||||
serializedVersion: 3
|
||||
agentTypeID: 0
|
||||
agentRadius: 0.5
|
||||
agentHeight: 2
|
||||
agentSlope: 45
|
||||
agentClimb: 0.4
|
||||
ledgeDropHeight: 0
|
||||
maxJumpAcrossDistance: 0
|
||||
minRegionArea: 2
|
||||
manualCellSize: 0
|
||||
cellSize: 0.16666667
|
||||
manualTileSize: 0
|
||||
tileSize: 256
|
||||
buildHeightMesh: 0
|
||||
maxJobWorkers: 0
|
||||
preserveTilesOutsideBounds: 0
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &1097328750
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1097328752}
|
||||
- component: {fileID: 1097328754}
|
||||
- component: {fileID: 1097328753}
|
||||
m_Layer: 0
|
||||
m_Name: UTKTreeListWindowSample
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &1097328752
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1097328750}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &1097328753
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1097328750}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 193bb366f0cf1094aa11baa8a5a2e32d, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::UTKTreeListWindowSample
|
||||
uiDocument: {fileID: 1097328754}
|
||||
--- !u!114 &1097328754
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1097328750}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 19102, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.dll::UnityEngine.UIElements.UIDocument
|
||||
m_PanelSettings: {fileID: 11400000, guid: 5ad7007b08a97b54d927c352279a18b6, type: 2}
|
||||
m_ParentUI: {fileID: 0}
|
||||
sourceAsset: {fileID: 9197481963319205126, guid: 9d3024917e8d4b546943ec3f7b03d9e4, type: 3}
|
||||
m_SortingOrder: 0
|
||||
m_Position: 0
|
||||
m_WorldSpaceSizeMode: 1
|
||||
m_WorldSpaceWidth: 1920
|
||||
m_WorldSpaceHeight: 1080
|
||||
m_PivotReferenceSize: 0
|
||||
m_Pivot: 0
|
||||
m_WorldSpaceCollider: {fileID: 0}
|
||||
--- !u!1 &1331954412
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1331954415}
|
||||
- component: {fileID: 1331954414}
|
||||
- component: {fileID: 1331954413}
|
||||
m_Layer: 0
|
||||
m_Name: EventSystem
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &1331954413
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1331954412}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_SendPointerHoverToParent: 1
|
||||
m_MoveRepeatDelay: 0.5
|
||||
m_MoveRepeatRate: 0.1
|
||||
m_XRTrackingOrigin: {fileID: 0}
|
||||
m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_PointAction: {fileID: -1654692200621890270, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_MoveAction: {fileID: -8784545083839296357, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_SubmitAction: {fileID: 392368643174621059, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_CancelAction: {fileID: 7727032971491509709, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_LeftClickAction: {fileID: 3001919216989983466, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_MiddleClickAction: {fileID: -2185481485913320682, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_RightClickAction: {fileID: -4090225696740746782, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_ScrollWheelAction: {fileID: 6240969308177333660, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_TrackedDevicePositionAction: {fileID: 6564999863303420839, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_TrackedDeviceOrientationAction: {fileID: 7970375526676320489, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
|
||||
m_DeselectOnBackgroundClick: 1
|
||||
m_PointerBehavior: 0
|
||||
m_CursorLockBehavior: 0
|
||||
m_ScrollDeltaPerTick: 6
|
||||
--- !u!114 &1331954414
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1331954412}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_FirstSelected: {fileID: 0}
|
||||
m_sendNavigationEvents: 1
|
||||
m_DragThreshold: 10
|
||||
--- !u!4 &1331954415
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1331954412}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1414861612
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1414861614}
|
||||
- component: {fileID: 1414861613}
|
||||
- component: {fileID: 1414861615}
|
||||
m_Layer: 0
|
||||
m_Name: Directional Light
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!108 &1414861613
|
||||
Light:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1414861612}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 11
|
||||
m_Type: 1
|
||||
m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
|
||||
m_Intensity: 1
|
||||
m_Range: 10
|
||||
m_SpotAngle: 30
|
||||
m_InnerSpotAngle: 21.80208
|
||||
m_CookieSize: 10
|
||||
m_Shadows:
|
||||
m_Type: 2
|
||||
m_Resolution: -1
|
||||
m_CustomResolution: -1
|
||||
m_Strength: 1
|
||||
m_Bias: 0.05
|
||||
m_NormalBias: 0.4
|
||||
m_NearPlane: 0.2
|
||||
m_CullingMatrixOverride:
|
||||
e00: 1
|
||||
e01: 0
|
||||
e02: 0
|
||||
e03: 0
|
||||
e10: 0
|
||||
e11: 1
|
||||
e12: 0
|
||||
e13: 0
|
||||
e20: 0
|
||||
e21: 0
|
||||
e22: 1
|
||||
e23: 0
|
||||
e30: 0
|
||||
e31: 0
|
||||
e32: 0
|
||||
e33: 1
|
||||
m_UseCullingMatrixOverride: 0
|
||||
m_Cookie: {fileID: 0}
|
||||
m_DrawHalo: 0
|
||||
m_Flare: {fileID: 0}
|
||||
m_RenderMode: 0
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingLayerMask: 1
|
||||
m_Lightmapping: 4
|
||||
m_LightShadowCasterMode: 0
|
||||
m_AreaSize: {x: 1, y: 1}
|
||||
m_BounceIntensity: 1
|
||||
m_ColorTemperature: 6570
|
||||
m_UseColorTemperature: 0
|
||||
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_UseBoundingSphereOverride: 0
|
||||
m_UseViewFrustumForShadowCasterCull: 1
|
||||
m_ForceVisible: 0
|
||||
m_ShadowRadius: 0
|
||||
m_ShadowAngle: 0
|
||||
m_LightUnit: 1
|
||||
m_LuxAtDistance: 1
|
||||
m_EnableSpotReflector: 1
|
||||
--- !u!4 &1414861614
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1414861612}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
|
||||
m_LocalPosition: {x: 0, y: 3, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
|
||||
--- !u!114 &1414861615
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1414861612}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_UsePipelineSettings: 1
|
||||
m_AdditionalLightsShadowResolutionTier: 2
|
||||
m_CustomShadowLayers: 0
|
||||
m_LightCookieSize: {x: 1, y: 1}
|
||||
m_LightCookieOffset: {x: 0, y: 0}
|
||||
m_SoftShadowQuality: 0
|
||||
m_RenderingLayersMask:
|
||||
serializedVersion: 0
|
||||
m_Bits: 1
|
||||
m_ShadowRenderingLayersMask:
|
||||
serializedVersion: 0
|
||||
m_Bits: 1
|
||||
m_Version: 4
|
||||
m_LightLayerMask: 1
|
||||
m_ShadowLayerMask: 1
|
||||
m_RenderingLayers: 1
|
||||
m_ShadowRenderingLayers: 1
|
||||
--- !u!1 &2136621999
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2136622002}
|
||||
- component: {fileID: 2136622001}
|
||||
- component: {fileID: 2136622000}
|
||||
m_Layer: 0
|
||||
m_Name: Main Camera
|
||||
m_TagString: MainCamera
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!81 &2136622000
|
||||
AudioListener:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2136621999}
|
||||
m_Enabled: 1
|
||||
--- !u!20 &2136622001
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2136621999}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_ClearFlags: 1
|
||||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
|
||||
m_projectionMatrixMode: 1
|
||||
m_GateFitMode: 2
|
||||
m_FOVAxisMode: 0
|
||||
m_Iso: 200
|
||||
m_ShutterSpeed: 0.005
|
||||
m_Aperture: 16
|
||||
m_FocusDistance: 10
|
||||
m_FocalLength: 50
|
||||
m_BladeCount: 5
|
||||
m_Curvature: {x: 2, y: 11}
|
||||
m_BarrelClipping: 0.25
|
||||
m_Anamorphism: 0
|
||||
m_SensorSize: {x: 36, y: 24}
|
||||
m_LensShift: {x: 0, y: 0}
|
||||
m_NormalizedViewPortRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
near clip plane: 0.3
|
||||
far clip plane: 1000
|
||||
field of view: 60
|
||||
orthographic: 0
|
||||
orthographic size: 5
|
||||
m_Depth: -1
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingPath: -1
|
||||
m_TargetTexture: {fileID: 0}
|
||||
m_TargetDisplay: 0
|
||||
m_TargetEye: 3
|
||||
m_HDR: 1
|
||||
m_AllowMSAA: 1
|
||||
m_AllowDynamicResolution: 0
|
||||
m_ForceIntoRT: 0
|
||||
m_OcclusionCulling: 1
|
||||
m_StereoConvergence: 10
|
||||
m_StereoSeparation: 0.022
|
||||
--- !u!4 &2136622002
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2136621999}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 1, z: -10}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1660057539 &9223372036854775807
|
||||
SceneRoots:
|
||||
m_ObjectHideFlags: 0
|
||||
m_Roots:
|
||||
- {fileID: 2136622002}
|
||||
- {fileID: 1414861614}
|
||||
- {fileID: 1331954415}
|
||||
- {fileID: 1097328752}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8aa9dae3ce8e15489b0ce72def792b6
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -5661,6 +5661,10 @@ PrefabInstance:
|
||||
propertyPath: m_IsOn
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4845567409543997696, guid: 8103add27aa0de64a992e9faa892eea1, type: 3}
|
||||
propertyPath: m_Sprite
|
||||
value:
|
||||
objectReference: {fileID: 21300000, guid: 8b95f14855ed5cd418d3eff614dae5d4, type: 3}
|
||||
- target: {fileID: 8781706204188846678, guid: 8103add27aa0de64a992e9faa892eea1, type: 3}
|
||||
propertyPath: m_Pivot.x
|
||||
value: 1
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UVC.Factory.Component;
|
||||
using UVC.Object3d;
|
||||
|
||||
public class PortAreaTypeEditor : EditorWindow
|
||||
{
|
||||
// 저장할 데이터 구조체
|
||||
[System.Serializable]
|
||||
private class PortData
|
||||
{
|
||||
public string name;
|
||||
public AreaType areaType;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
private class PortDataList
|
||||
{
|
||||
public List<PortData> ports = new List<PortData>();
|
||||
}
|
||||
|
||||
[MenuItem("Tools/UVC/Port AreaType Manager")]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
GetWindow<PortAreaTypeEditor>("Port AreaType Manager");
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
GUILayout.Label("Port AreaType 저장 및 불러오기", EditorStyles.boldLabel);
|
||||
GUILayout.Space(10);
|
||||
|
||||
if (GUILayout.Button("AreaType 저장"))
|
||||
{
|
||||
SaveAreaTypes();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("AreaType 불러오기"))
|
||||
{
|
||||
LoadAreaTypes();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Model 설정"))
|
||||
{
|
||||
SetModel();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetModel()
|
||||
{
|
||||
GameObject selectedObject = Selection.activeGameObject;
|
||||
if (selectedObject == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("오류", "하이라키에서 부모 게임 오브젝트를 선택하세요.", "확인");
|
||||
return;
|
||||
}
|
||||
int i = 0;
|
||||
|
||||
foreach (Transform child in selectedObject.transform)
|
||||
{
|
||||
Port port = child.GetComponent<Port>();
|
||||
if (port != null)
|
||||
{
|
||||
foreach (Transform childChild in child.transform)
|
||||
{
|
||||
InteractiveObject interactiveObject = childChild.GetComponent<InteractiveObject>();
|
||||
if (interactiveObject != null)
|
||||
{
|
||||
port.modelObject = interactiveObject;
|
||||
i++;
|
||||
break; // 첫 번째 InteractiveObject만 설정
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorUtility.DisplayDialog("성공", $"총 {i}개의 Model을 설정했습니다.", "확인");
|
||||
|
||||
}
|
||||
|
||||
private void SaveAreaTypes()
|
||||
{
|
||||
GameObject selectedObject = Selection.activeGameObject;
|
||||
if (selectedObject == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("오류", "하이라키에서 부모 게임 오브젝트를 선택하세요.", "확인");
|
||||
return;
|
||||
}
|
||||
|
||||
PortDataList dataList = new PortDataList();
|
||||
foreach (Transform child in selectedObject.transform)
|
||||
{
|
||||
Port port = child.GetComponent<Port>();
|
||||
if (port != null)
|
||||
{
|
||||
dataList.ports.Add(new PortData { name = child.name, areaType = port.areaType });
|
||||
}
|
||||
}
|
||||
|
||||
if (dataList.ports.Count == 0)
|
||||
{
|
||||
EditorUtility.DisplayDialog("정보", "선택된 오브젝트의 자식 중 Port 컴포넌트를 가진 오브젝트가 없습니다.", "확인");
|
||||
return;
|
||||
}
|
||||
|
||||
string path = EditorUtility.SaveFilePanel("AreaType 데이터 저장", Application.streamingAssetsPath, "PortAreaTypes", "json");
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
string json = JsonUtility.ToJson(dataList, true);
|
||||
File.WriteAllText(path, json);
|
||||
EditorUtility.DisplayDialog("성공", $"총 {dataList.ports.Count}개의 Port AreaType 데이터를 저장했습니다.", "확인");
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadAreaTypes()
|
||||
{
|
||||
GameObject selectedObject = Selection.activeGameObject;
|
||||
if (selectedObject == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("오류", "하이라키에서 부모 게임 오브젝트를 선택하세요.", "확인");
|
||||
return;
|
||||
}
|
||||
|
||||
string path = EditorUtility.OpenFilePanel("AreaType 데이터 불러오기", Application.streamingAssetsPath, "json");
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
string json = File.ReadAllText(path);
|
||||
PortDataList dataList = JsonUtility.FromJson<PortDataList>(json);
|
||||
|
||||
int updatedCount = 0;
|
||||
foreach (var portData in dataList.ports)
|
||||
{
|
||||
Transform child = selectedObject.transform.Find(portData.name);
|
||||
if (child != null)
|
||||
{
|
||||
Port port = child.GetComponent<Port>();
|
||||
if (port != null)
|
||||
{
|
||||
Undo.RecordObject(port, "Update AreaType"); // Undo를 위해 변경사항 기록
|
||||
port.areaType = portData.areaType;
|
||||
EditorUtility.SetDirty(port); // 변경사항을 저장하도록 표시
|
||||
updatedCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
EditorUtility.DisplayDialog("성공", $"총 {updatedCount}개의 Port AreaType 데이터를 업데이트했습니다.", "확인");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c3facf639aa7ca4a9ab4253185d55ef
|
||||
@@ -1,623 +0,0 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace UVC.UIToolkit.List
|
||||
{
|
||||
/// <summary>
|
||||
/// 계층적 트리 구조를 표시하는 커스텀 UI Toolkit 컴포넌트입니다.
|
||||
///
|
||||
/// <para><b>개요:</b></para>
|
||||
/// <para>
|
||||
/// TreeList는 Unity UI Toolkit의 TreeView를 래핑하여 검색, 가시성 토글,
|
||||
/// 닫기 기능 등을 제공하는 재사용 가능한 컴포넌트입니다.
|
||||
/// UXML 파일(TreeList.uxml, TreeListItem.uxml)과 함께 사용됩니다.
|
||||
/// </para>
|
||||
///
|
||||
/// <para><b>주요 기능:</b></para>
|
||||
/// <list type="bullet">
|
||||
/// <item>계층적 트리 구조 표시 (펼치기/접기 지원)</item>
|
||||
/// <item>실시간 검색 필터링</item>
|
||||
/// <item>항목별 가시성(눈 아이콘) 토글</item>
|
||||
/// <item>선택 이벤트 처리</item>
|
||||
/// </list>
|
||||
///
|
||||
/// <para><b>UXML에서 사용:</b></para>
|
||||
/// <code>
|
||||
/// <UVC.UIToolkit.List.UIToolkitTreeList name="tree-list" />
|
||||
/// </code>
|
||||
///
|
||||
/// <para><b>코드에서 사용:</b></para>
|
||||
/// <code>
|
||||
/// var treeList = root.Q<UIToolkitTreeList>();
|
||||
/// treeList.OnSelectionChanged += (item) => Debug.Log($"선택: {item.name}");
|
||||
/// treeList.OnVisibilityChanged += (item) => model.SetActive(item.id, item.IsVisible);
|
||||
/// treeList.SetData(treeItems);
|
||||
/// </code>
|
||||
///
|
||||
/// <para><b>관련 리소스:</b></para>
|
||||
/// <list type="bullet">
|
||||
/// <item>Resources/UIToolkit/List/UIToolkitTreeList.uxml - 메인 레이아웃</item>
|
||||
/// <item>Resources/UIToolkit/List/UIToolkitTreeListItem.uxml - 개별 항목 템플릿</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public partial class UIToolkitTreeList : VisualElement, IDisposable
|
||||
{
|
||||
#region IDisposable
|
||||
private bool _disposed = false;
|
||||
#endregion
|
||||
#region 상수 (Constants)
|
||||
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
||||
private const string UXML_PATH = "SHI/Modal/TreeList";
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI 컴포넌트 참조 (UI Component References)
|
||||
/// <summary>검색어 입력 필드</summary>
|
||||
private TextField? _searchField;
|
||||
|
||||
/// <summary>Unity UI Toolkit의 TreeView 컴포넌트</summary>
|
||||
private TreeView? _treeView;
|
||||
|
||||
/// <summary>트리 리스트 닫기 버튼</summary>
|
||||
private Button? _closeButton;
|
||||
|
||||
/// <summary>검색어 지우기 버튼</summary>
|
||||
private Button? _clearButton;
|
||||
#endregion
|
||||
|
||||
#region 내부 데이터 (Internal Data)
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 원본 루트 데이터입니다.
|
||||
/// 검색 필터 해제 시 원래 데이터로 복원하는 데 사용됩니다.
|
||||
/// </summary>
|
||||
private List<UIToolkitTreeListItemData> _originalRoots = new();
|
||||
|
||||
/// <summary>
|
||||
/// TreeView에 바인딩되는 데이터 소스입니다.
|
||||
/// TreeViewItemData는 Unity의 TreeView가 요구하는 래퍼 타입입니다.
|
||||
/// </summary>
|
||||
private List<TreeViewItemData<UIToolkitTreeListItemData>>? _rootData;
|
||||
|
||||
/// <summary>
|
||||
/// 항목 ID 자동 생성을 위한 시드 값입니다.
|
||||
/// SetData() 호출 시 id가 0인 항목에 순차적으로 ID를 할당합니다.
|
||||
/// </summary>
|
||||
private int _idSeed = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 이전에 선택된 항목입니다.
|
||||
/// 선택 해제 이벤트 발송에 사용됩니다.
|
||||
/// </summary>
|
||||
private UIToolkitTreeListItemData? _previouslySelectedItem;
|
||||
#endregion
|
||||
|
||||
#region 외부 이벤트 (Public Events)
|
||||
/// <summary>
|
||||
/// 항목의 가시성(눈 아이콘)이 변경될 때 발생합니다.
|
||||
/// 3D 모델의 GameObject 활성화/비활성화에 연동합니다.
|
||||
/// </summary>
|
||||
public event Action<UIToolkitTreeListItemData>? OnVisibilityChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 항목 선택 상태가 변경될 때 발생합니다.
|
||||
/// 선택 및 선택 해제 모두에서 발생하며, item.isSelected로 구분합니다.
|
||||
/// </summary>
|
||||
public event Action<UIToolkitTreeListItemData>? OnSelectionChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 트리 리스트가 닫힐 때(숨겨질 때) 발생합니다.
|
||||
/// 닫기 버튼 클릭 시 트리거됩니다.
|
||||
/// </summary>
|
||||
public event Action? OnClosed;
|
||||
#endregion
|
||||
|
||||
#region 생성자 (Constructor)
|
||||
/// <summary>
|
||||
/// TreeList 컴포넌트를 초기화합니다.
|
||||
/// UXML 템플릿을 로드하고 내부 컴포넌트를 설정합니다.
|
||||
/// </summary>
|
||||
public TreeList()
|
||||
{
|
||||
// 1. 메인 UXML 로드 및 복제
|
||||
// CloneTree(this)로 UXML 내용이 이 클래스의 자식으로 추가됨
|
||||
var visualTree = Resources.Load<VisualTreeAsset>(UXML_PATH);
|
||||
if (visualTree == null)
|
||||
{
|
||||
Debug.LogError($"[TreeMenu] UXML not found at: {UXML_PATH}");
|
||||
return;
|
||||
}
|
||||
visualTree!.CloneTree(this);
|
||||
|
||||
|
||||
// 2. 자식 요소 참조 획득 (UXML의 name 속성으로 찾음)
|
||||
_searchField = this.Q<TextField>("search-field");
|
||||
_treeView = this.Q<TreeView>("main-tree-view");
|
||||
_closeButton = this.Q<Button>("hide-btn");
|
||||
_clearButton = this.Q<Button>("clear-btn");
|
||||
|
||||
// 3. 이벤트 연결 및 로직 초기화
|
||||
InitializeLogic();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 초기화 (Initialization)
|
||||
/// <summary>
|
||||
/// 내부 로직과 이벤트 핸들러를 초기화합니다.
|
||||
/// </summary>
|
||||
private void InitializeLogic()
|
||||
{
|
||||
// 검색창 이벤트: 입력 값이 변경될 때마다 필터링 실행
|
||||
if (_searchField != null)
|
||||
{
|
||||
_searchField.RegisterValueChangedCallback(OnSearchValueChanged);
|
||||
}
|
||||
|
||||
// TreeView 설정
|
||||
// makeItem: 새 항목 UI 생성 시 호출
|
||||
// bindItem: 데이터를 UI에 바인딩할 때 호출
|
||||
// selectionChanged: 선택 변경 시 호출
|
||||
if (_treeView != null)
|
||||
{
|
||||
_treeView.bindItem = BindTreeItem;
|
||||
_treeView.selectionChanged += OnTreeViewSelectionChanged;
|
||||
}
|
||||
|
||||
// 닫기 버튼: 트리 리스트를 숨기고 이벤트 발생
|
||||
if (_closeButton != null)
|
||||
{
|
||||
_closeButton.clicked += () =>
|
||||
{
|
||||
this.style.display = DisplayStyle.None;
|
||||
OnClosed?.Invoke();
|
||||
};
|
||||
}
|
||||
|
||||
// 검색어 지우기 버튼
|
||||
if(_clearButton != null)
|
||||
{
|
||||
_clearButton.clicked += () =>
|
||||
{
|
||||
if (_searchField.value.Length > 0)
|
||||
{
|
||||
_searchField.value = string.Empty;
|
||||
OnSearch(string.Empty);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 공개 메서드 (Public Methods)
|
||||
/// <summary>
|
||||
/// 트리 리스트를 화면에 표시합니다.
|
||||
/// </summary>
|
||||
public void Show()
|
||||
{
|
||||
this.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 트리 데이터를 설정합니다.
|
||||
/// UIToolkitTreeListItemData 리스트를 받아 TreeView에 바인딩합니다.
|
||||
/// </summary>
|
||||
/// <param name="roots">루트 항목들의 리스트 (계층 구조의 최상위 항목들)</param>
|
||||
public void SetData(List<UIToolkitTreeListItemData> roots)
|
||||
{
|
||||
// 원본 데이터 저장 (필터 복원용)
|
||||
_originalRoots = roots ?? new List<UIToolkitTreeListItemData>();
|
||||
|
||||
// ID 시드 초기화
|
||||
_idSeed = 1;
|
||||
|
||||
// 순환 참조 감지를 위한 방문 집합
|
||||
var visited = new HashSet<UIToolkitTreeListItemData>();
|
||||
|
||||
// TreeView 형식으로 데이터 변환
|
||||
_rootData = ConvertToTreeViewData(_originalRoots, visited, 0);
|
||||
|
||||
// TreeView에 데이터 설정
|
||||
_treeView!.SetRootItems<UIToolkitTreeListItemData>(_rootData);
|
||||
|
||||
// UI 갱신 및 모든 항목 펼치기
|
||||
_treeView!.Rebuild();
|
||||
_treeView!.ExpandAll();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 ID의 항목을 프로그래밍 방식으로 선택합니다.
|
||||
/// </summary>
|
||||
/// <param name="itemId">선택할 항목의 ID</param>
|
||||
public void SelectByItemId(int itemId)
|
||||
{
|
||||
_treeView.SetSelection(new List<int> { itemId });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 이름 목록에 해당하는 항목만 표시하고 나머지는 숨깁니다.
|
||||
/// </summary>
|
||||
/// <param name="items">표시할 항목들의 이름 목록</param>
|
||||
/// <param name="depth">검색 깊이 (1=1뎁스 자식만, 2=2뎁스까지, 0이하=전체)</param>
|
||||
public void ShowItems(List<string> items, int depth = 1)
|
||||
{
|
||||
if (_originalRoots == null || _originalRoots.Count == 0) return;
|
||||
|
||||
var visibleNames = new HashSet<string>(items ?? new List<string>());
|
||||
|
||||
foreach (var root in _originalRoots)
|
||||
{
|
||||
SetVisibilityByNames(root, visibleNames, depth, 0);
|
||||
}
|
||||
|
||||
// UI 갱신
|
||||
_treeView?.RefreshItems();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 재귀적으로 항목의 가시성을 이름 목록에 따라 설정합니다.
|
||||
/// </summary>
|
||||
/// <param name="node">현재 노드</param>
|
||||
/// <param name="visibleNames">표시할 이름 목록</param>
|
||||
/// <param name="maxDepth">최대 검색 깊이 (0이하=무제한)</param>
|
||||
/// <param name="currentDepth">현재 깊이</param>
|
||||
private void SetVisibilityByNames(UIToolkitTreeListItemData node, HashSet<string> visibleNames, int maxDepth, int currentDepth)
|
||||
{
|
||||
if (node == null) return;
|
||||
|
||||
// maxDepth <= 0 이면 전체 검색, 아니면 깊이 제한 체크
|
||||
bool isWithinDepth = maxDepth <= 0 || currentDepth < maxDepth;
|
||||
|
||||
if (isWithinDepth)
|
||||
{
|
||||
// 이름이 목록에 있으면 visible, 없으면 hidden
|
||||
node.IsVisible = visibleNames.Contains(node.name);
|
||||
|
||||
// 가시성 변경 이벤트 발송
|
||||
OnVisibilityChanged?.Invoke(node);
|
||||
}
|
||||
|
||||
// 자식들도 재귀적으로 처리
|
||||
if (node.children != null)
|
||||
{
|
||||
foreach (var child in node.children)
|
||||
{
|
||||
SetVisibilityByNames(child, visibleNames, maxDepth, currentDepth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 선택 처리 (Selection Handling)
|
||||
/// <summary>
|
||||
/// TreeView의 선택 변경 이벤트를 처리합니다.
|
||||
/// 외부에 OnSelectionChanged 이벤트를 발송합니다.
|
||||
/// </summary>
|
||||
/// <param name="selectedItems">선택된 항목들</param>
|
||||
private void OnTreeViewSelectionChanged(System.Collections.Generic.IEnumerable<object> selectedItems)
|
||||
{
|
||||
// 단일 선택 기준 (첫 번째 항목만 처리)
|
||||
var currentItem = selectedItems.FirstOrDefault() as UIToolkitTreeListItemData;
|
||||
|
||||
// 이전 선택 항목이 있고 현재와 다르면 선택 해제 이벤트 발송
|
||||
if (_previouslySelectedItem != null && _previouslySelectedItem != currentItem)
|
||||
{
|
||||
_previouslySelectedItem.isSelected = false;
|
||||
OnSelectionChanged?.Invoke(_previouslySelectedItem);
|
||||
}
|
||||
|
||||
// 현재 선택 항목이 있으면 선택 이벤트 발송
|
||||
if (currentItem != null)
|
||||
{
|
||||
currentItem.isSelected = true;
|
||||
OnSelectionChanged?.Invoke(currentItem);
|
||||
}
|
||||
|
||||
// 현재 선택 상태 저장
|
||||
_previouslySelectedItem = currentItem;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 데이터 변환 (Data Conversion)
|
||||
/// <summary>
|
||||
/// UIToolkitTreeListItemData 리스트를 TreeView가 요구하는 TreeViewItemData 형식으로 변환합니다.
|
||||
/// 재귀적으로 자식 항목도 변환하며, 순환 참조를 감지합니다.
|
||||
/// </summary>
|
||||
/// <param name="items">변환할 항목 리스트</param>
|
||||
/// <param name="visited">순환 참조 감지용 방문 집합</param>
|
||||
/// <param name="depth">현재 깊이 (디버깅용)</param>
|
||||
/// <returns>TreeViewItemData 래퍼 리스트</returns>
|
||||
private List<TreeViewItemData<UIToolkitTreeListItemData>> ConvertToTreeViewData(List<UIToolkitTreeListItemData> items, HashSet<UIToolkitTreeListItemData> visited, int depth)
|
||||
{
|
||||
var list = new List<TreeViewItemData<UIToolkitTreeListItemData>>(items.Count);
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item == null) continue;
|
||||
|
||||
// 순환 참조 체크: 이미 방문한 항목이면 자식 무시
|
||||
if (!visited.Add(item))
|
||||
{
|
||||
Debug.LogWarning($"[TreeList] Cycle detected at item '{item.name}' → children 무시");
|
||||
item.children = null;
|
||||
}
|
||||
|
||||
// ID가 없으면 자동 할당
|
||||
if (item.id == 0) item.id = _idSeed++;
|
||||
|
||||
// 자식 항목 재귀 변환
|
||||
List<TreeViewItemData<UIToolkitTreeListItemData>>? childData = null;
|
||||
if (item.children != null && item.children.Count > 0)
|
||||
childData = ConvertToTreeViewData(item.children, visited, depth + 1);
|
||||
|
||||
// TreeViewItemData 래퍼 생성
|
||||
var treeItem = new TreeViewItemData<UIToolkitTreeListItemData>(item.id, item, childData);
|
||||
list.Add(treeItem);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region TreeView 항목 바인딩 (TreeView Item Creation/Binding)
|
||||
|
||||
/// <summary>
|
||||
/// 데이터를 UI 요소에 바인딩합니다.
|
||||
/// TreeView의 bindItem 콜백으로 사용됩니다.
|
||||
/// 스크롤 시 재사용되는 항목에 새 데이터를 연결합니다.
|
||||
/// </summary>
|
||||
/// <param name="element">바인딩할 UI 요소</param>
|
||||
/// <param name="index">TreeView 내부 인덱스</param>
|
||||
private void BindTreeItem(VisualElement element, int index)
|
||||
{
|
||||
// 인덱스로 데이터 획득
|
||||
var item = _treeView.GetItemDataForIndex<UIToolkitTreeListItemData>(index);
|
||||
if (item == null) return;
|
||||
|
||||
// 1. 항목 이름 레이블 설정
|
||||
var label = element.Q<Label>("item-label");
|
||||
if (label != null) label.text = item.name;
|
||||
|
||||
// 2. 가시성 아이콘 버튼 설정
|
||||
var toggleBtn = element.Q<Button>("visibility-btn");
|
||||
if (toggleBtn != null) UpdateVisibilityIcon(toggleBtn, item.IsVisible);
|
||||
|
||||
// 3. 가시성 버튼 클릭 이벤트 연결
|
||||
// 주의: bindItem은 스크롤 시 재호출되므로 기존 이벤트 제거 후 재등록
|
||||
if (toggleBtn.userData is Action oldAction) toggleBtn.clicked -= oldAction;
|
||||
System.Action clickAction = () =>
|
||||
{
|
||||
// 가시성 상태 토글
|
||||
item.IsVisible = !item.IsVisible;
|
||||
UpdateVisibilityIcon(toggleBtn, item.IsVisible);
|
||||
|
||||
// 자식들에게 동일 상태 전파
|
||||
SetChildrenVisibility(item, item.IsVisible);
|
||||
|
||||
// 화면에 보이는 자식 아이콘도 갱신
|
||||
_treeView.RefreshItems();
|
||||
|
||||
// 외부에 이벤트 발송 (3D 모델 가시성 동기화)
|
||||
OnVisibilityChanged?.Invoke(item);
|
||||
};
|
||||
toggleBtn.userData = clickAction;
|
||||
toggleBtn.clicked += clickAction;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 가시성 처리 (Visibility Handling)
|
||||
/// <summary>
|
||||
/// 자식 항목들의 가시성을 재귀적으로 동기화합니다.
|
||||
/// 부모의 가시성이 변경되면 모든 하위 항목에 동일하게 적용됩니다.
|
||||
/// </summary>
|
||||
/// <param name="node">현재 노드</param>
|
||||
/// <param name="isVisible">설정할 가시성 상태</param>
|
||||
private void SetChildrenVisibility(UIToolkitTreeListItemData node, bool isVisible)
|
||||
{
|
||||
if (node.children == null || node.children.Count == 0) return;
|
||||
foreach (var child in node.children)
|
||||
{
|
||||
if (child == null) continue;
|
||||
child.IsVisible = isVisible;
|
||||
// 재귀적으로 하위 자식에도 적용
|
||||
SetChildrenVisibility(child, isVisible);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 가시성 버튼의 아이콘 스타일을 업데이트합니다.
|
||||
/// USS 클래스를 토글하여 아이콘 변경을 처리합니다.
|
||||
/// </summary>
|
||||
/// <param name="btn">가시성 토글 버튼</param>
|
||||
/// <param name="isVisible">현재 가시성 상태</param>
|
||||
private void UpdateVisibilityIcon(Button btn, bool isVisible)
|
||||
{
|
||||
if (isVisible)
|
||||
{
|
||||
btn.RemoveFromClassList("visibility-off");
|
||||
btn.AddToClassList("visibility-on");
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.RemoveFromClassList("visibility-on");
|
||||
btn.AddToClassList("visibility-off");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 검색 기능 (Search Functionality)
|
||||
/// <summary>
|
||||
/// 검색 필드 값 변경 콜백입니다.
|
||||
/// </summary>
|
||||
/// <param name="evt">값 변경 이벤트</param>
|
||||
private void OnSearchValueChanged(ChangeEvent<string> evt)
|
||||
{
|
||||
OnSearch(evt.newValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 검색어에 따라 트리를 필터링합니다.
|
||||
/// 검색어가 비어있으면 원본 데이터로 복원됩니다.
|
||||
/// </summary>
|
||||
/// <param name="query">검색어</param>
|
||||
private void OnSearch(string query)
|
||||
{
|
||||
// 검색어가 없으면 원본 데이터 복원
|
||||
if (string.IsNullOrEmpty(query))
|
||||
{
|
||||
_treeView.SetRootItems<UIToolkitTreeListItemData>(_rootData);
|
||||
_treeView.Rebuild();
|
||||
return;
|
||||
}
|
||||
|
||||
// 대소문자 무시 검색
|
||||
string qLower = query.Trim().ToLowerInvariant();
|
||||
var filteredWrappers = FilterTree(qLower);
|
||||
|
||||
// 필터링된 결과로 TreeView 갱신
|
||||
_treeView.SetRootItems<UIToolkitTreeListItemData>(filteredWrappers);
|
||||
_treeView.Rebuild();
|
||||
|
||||
// 검색 결과 모두 펼치기
|
||||
ExpandAll(filteredWrappers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 모든 루트 항목에 대해 필터링을 수행합니다.
|
||||
/// </summary>
|
||||
/// <param name="qLower">소문자로 변환된 검색어</param>
|
||||
/// <returns>필터링된 TreeViewItemData 리스트</returns>
|
||||
private List<TreeViewItemData<UIToolkitTreeListItemData>> FilterTree(string qLower)
|
||||
{
|
||||
var result = new List<TreeViewItemData<UIToolkitTreeListItemData>>();
|
||||
foreach (var root in _originalRoots)
|
||||
{
|
||||
TreeViewItemData<UIToolkitTreeListItemData>? filtered = FilterNode(root, qLower);
|
||||
if (filtered != null) result.Add(filtered.Value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 단일 노드를 필터링합니다.
|
||||
/// 자신 또는 자식이 검색어와 매치되면 결과에 포함됩니다.
|
||||
/// </summary>
|
||||
/// <param name="node">필터링할 노드</param>
|
||||
/// <param name="qLower">소문자로 변환된 검색어</param>
|
||||
/// <returns>매치된 경우 TreeViewItemData, 아니면 null</returns>
|
||||
private TreeViewItemData<UIToolkitTreeListItemData>? FilterNode(UIToolkitTreeListItemData node, string qLower)
|
||||
{
|
||||
// 자기 자신이 매치되는지 확인
|
||||
bool selfMatch = NodeMatches(node, qLower);
|
||||
List<TreeViewItemData<UIToolkitTreeListItemData>>? childFiltered = null;
|
||||
|
||||
// 자식들도 재귀적으로 필터링
|
||||
if (node.children != null && node.children.Count > 0)
|
||||
{
|
||||
foreach (var child in node.children)
|
||||
{
|
||||
TreeViewItemData<UIToolkitTreeListItemData>? f = FilterNode(child, qLower);
|
||||
if (f != null)
|
||||
{
|
||||
childFiltered ??= new List<TreeViewItemData<UIToolkitTreeListItemData>>();
|
||||
childFiltered.Add(f.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 자신이 매치되거나 매치된 자식이 있으면 포함
|
||||
if (selfMatch || (childFiltered != null && childFiltered.Count > 0))
|
||||
{
|
||||
return new TreeViewItemData<UIToolkitTreeListItemData>(node.id, node, childFiltered);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드가 검색어와 매치되는지 확인합니다.
|
||||
/// name, option, ExternalKey 필드를 검색 대상으로 합니다.
|
||||
/// </summary>
|
||||
/// <param name="item">검사할 항목</param>
|
||||
/// <param name="qLower">소문자로 변환된 검색어</param>
|
||||
/// <returns>매치 여부</returns>
|
||||
private bool NodeMatches(UIToolkitTreeListItemData item, string qLower)
|
||||
{
|
||||
if (item.name != null && item.name.ToLowerInvariant().Contains(qLower)) return true;
|
||||
if (!string.IsNullOrEmpty(item.option) && item.option.ToLowerInvariant().Contains(qLower)) return true;
|
||||
if (!string.IsNullOrEmpty(item.ExternalKey) && item.ExternalKey.ToLowerInvariant().Contains(qLower)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 필터링된 결과의 모든 항목을 펼칩니다.
|
||||
/// </summary>
|
||||
/// <param name="roots">펼칠 루트 항목들</param>
|
||||
private void ExpandAll(List<TreeViewItemData<UIToolkitTreeListItemData>> roots)
|
||||
{
|
||||
foreach (var r in roots)
|
||||
ExpandRecursive(r);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 노드와 그 자식들을 재귀적으로 펼칩니다.
|
||||
/// </summary>
|
||||
/// <param name="wrapper">펼칠 TreeViewItemData</param>
|
||||
private void ExpandRecursive(TreeViewItemData<UIToolkitTreeListItemData> wrapper)
|
||||
{
|
||||
_treeView.ExpandItem(wrapper.id);
|
||||
if (wrapper.children != null)
|
||||
{
|
||||
foreach (var c in wrapper.children)
|
||||
ExpandRecursive(c);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
/// <summary>
|
||||
/// 리소스를 해제하고 이벤트 핸들러를 정리합니다.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
|
||||
// 검색 필드 이벤트 해제
|
||||
if (_searchField != null)
|
||||
{
|
||||
_searchField.UnregisterValueChangedCallback(OnSearchValueChanged);
|
||||
}
|
||||
|
||||
// TreeView 이벤트 핸들러 해제
|
||||
if (_treeView != null)
|
||||
{
|
||||
_treeView.selectionChanged -= OnTreeViewSelectionChanged;
|
||||
_treeView.bindItem = null;
|
||||
_treeView.makeItem = null;
|
||||
}
|
||||
|
||||
// 외부 이벤트 구독자 정리
|
||||
OnVisibilityChanged = null;
|
||||
OnSelectionChanged = null;
|
||||
OnClosed = null;
|
||||
|
||||
// 데이터 정리
|
||||
_originalRoots.Clear();
|
||||
_rootData?.Clear();
|
||||
_rootData = null;
|
||||
_previouslySelectedItem = null;
|
||||
|
||||
// ID 시드 초기화
|
||||
_idSeed = 1;
|
||||
|
||||
// UI 참조 정리
|
||||
_searchField = null;
|
||||
_treeView = null;
|
||||
_closeButton = null;
|
||||
_clearButton = null;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UVC.UIToolkit.List
|
||||
@@ -8,9 +9,9 @@ namespace UVC.UIToolkit.List
|
||||
///
|
||||
/// <para><b>개요:</b></para>
|
||||
/// <para>
|
||||
/// UIToolkitTreeListItemData는 계층적 트리 구조에서 각 노드(항목)를 표현합니다.
|
||||
/// UTKTreeListItemData는 계층적 트리 구조에서 각 노드(항목)를 표현합니다.
|
||||
/// 부모-자식 관계를 통해 중첩된 트리 구조를 구성할 수 있으며,
|
||||
/// UIToolkitTreeList(UI)에서 사용됩니다.
|
||||
/// UTKTreeListWindow(UI)에서 사용됩니다.
|
||||
/// </para>
|
||||
///
|
||||
/// <para><b>주요 용도:</b></para>
|
||||
@@ -23,20 +24,20 @@ namespace UVC.UIToolkit.List
|
||||
/// <para><b>사용 예시:</b></para>
|
||||
/// <code>
|
||||
/// // 루트 항목 생성
|
||||
/// var root = new UIToolkitTreeListItemData { id = 1, name = "루트" };
|
||||
/// var root = new UTKTreeListItemData { id = 1, name = "루트" };
|
||||
///
|
||||
/// // 자식 항목 추가
|
||||
/// var child1 = new UIToolkitTreeListItemData { id = 2, name = "자식1" };
|
||||
/// var child2 = new UIToolkitTreeListItemData { id = 3, name = "자식2" };
|
||||
/// var child1 = new UTKTreeListItemData { id = 2, name = "자식1" };
|
||||
/// var child2 = new UTKTreeListItemData { id = 3, name = "자식2" };
|
||||
/// root.Add(child1);
|
||||
/// root.Add(child2);
|
||||
///
|
||||
/// // 손자 항목 추가
|
||||
/// var grandChild = new UIToolkitTreeListItemData { id = 4, name = "손자" };
|
||||
/// var grandChild = new UTKTreeListItemData { id = 4, name = "손자" };
|
||||
/// child1.Add(grandChild);
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public class UIToolkitTreeListItemData
|
||||
public class UTKTreeListItemData: IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 항목의 고유 식별자입니다.
|
||||
@@ -75,19 +76,19 @@ namespace UVC.UIToolkit.List
|
||||
/// 루트 항목의 경우 null입니다.
|
||||
/// Add() 메서드로 자식을 추가하면 자동으로 설정됩니다.
|
||||
/// </summary>
|
||||
public UIToolkitTreeListItemData parent;
|
||||
public UTKTreeListItemData? parent;
|
||||
|
||||
/// <summary>
|
||||
/// 자식 항목들의 리스트입니다.
|
||||
/// 재귀적 트리 구조를 형성합니다.
|
||||
/// Add() 메서드를 통해 자식을 추가할 수 있습니다.
|
||||
/// </summary>
|
||||
public List<UIToolkitTreeListItemData> children = new List<UIToolkitTreeListItemData>();
|
||||
public List<UTKTreeListItemData> children = new List<UTKTreeListItemData>();
|
||||
|
||||
/// <summary>
|
||||
/// 해당 항목(및 연결된 3D 오브젝트)의 가시성 상태입니다.
|
||||
/// UI의 눈 아이콘 버튼으로 토글되며,
|
||||
/// 변경 시 UIToolkitTreeList.OnVisibilityChanged 이벤트를 통해
|
||||
/// 변경 시 UTKTreeListWindow.OnVisibilityChanged 이벤트를 통해
|
||||
/// 3D 모델의 GameObject.SetActive()가 호출됩니다.
|
||||
/// </summary>
|
||||
public bool IsVisible = true;
|
||||
@@ -106,16 +107,22 @@ namespace UVC.UIToolkit.List
|
||||
/// <param name="child">추가할 자식 항목</param>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// var parent = new UIToolkitTreeListItemData { name = "부모" };
|
||||
/// var child = new UIToolkitTreeListItemData { name = "자식" };
|
||||
/// var parent = new UTKTreeListItemData { name = "부모" };
|
||||
/// var child = new UTKTreeListItemData { name = "자식" };
|
||||
/// parent.Add(child);
|
||||
/// // child.parent == parent (자동 설정됨)
|
||||
/// </code>
|
||||
/// </example>
|
||||
public void Add(UIToolkitTreeListItemData child)
|
||||
public void Add(UTKTreeListItemData child)
|
||||
{
|
||||
child.parent = this;
|
||||
children.Add(child);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
children.Clear();
|
||||
parent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
1177
Assets/Scripts/UVC/UIToolkit/Window/UTKTreeListWindow.cs
Normal file
1177
Assets/Scripts/UVC/UIToolkit/Window/UTKTreeListWindow.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,8 @@ MonoBehaviour:
|
||||
m_DisableNoThemeWarning: 0
|
||||
m_TargetTexture: {fileID: 0}
|
||||
m_RenderMode: 0
|
||||
m_WorldSpaceLayer: 0
|
||||
m_ColliderUpdateMode: 0
|
||||
m_ColliderIsTrigger: 1
|
||||
m_ScaleMode: 1
|
||||
m_ReferenceSpritePixelsPerUnit: 100
|
||||
m_PixelsPerUnit: 100
|
||||
@@ -39,8 +40,10 @@ MonoBehaviour:
|
||||
m_MaxSubTextureSize: 64
|
||||
m_ActiveFilters: -1
|
||||
m_AtlasBlitShader: {fileID: 9101, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_RuntimeShader: {fileID: 9100, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_RuntimeWorldShader: {fileID: 9102, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_DefaultShader: {fileID: 9100, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_SDFShader: {fileID: 19011, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_BitmapShader: {fileID: 9001, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_SpriteShader: {fileID: 19012, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ICUDataAsset: {fileID: 0}
|
||||
forceGammaRendering: 0
|
||||
textSettings: {fileID: 0}
|
||||
|
||||
Reference in New Issue
Block a user