UTKAccodion 완료. UTKComponentList 수정 중
This commit is contained in:
@@ -22,7 +22,8 @@
|
|||||||
"mcp__UnityMCP__manage_scene",
|
"mcp__UnityMCP__manage_scene",
|
||||||
"Bash(git checkout:*)",
|
"Bash(git checkout:*)",
|
||||||
"Bash(git -C \"d:/works/2025/02.Studio/dev/base/XRBase\" checkout HEAD -- \"Assets/Resources/UIToolkit/List/UTKMultiColumnTreeView.uss\" \"Assets/Resources/UIToolkit/List/UTKMultiColumnListView.uss\" \"Assets/Resources/UIToolkit/Style/UTKDefaultStyle.uss\" \"Assets/Resources/UIToolkit/Tab/UTKTabView.uss\" \"Assets/Resources/UIToolkit/List/UTKListView.uss\" \"Assets/Resources/UIToolkit/Style/UTKComponents.uss\")",
|
"Bash(git -C \"d:/works/2025/02.Studio/dev/base/XRBase\" checkout HEAD -- \"Assets/Resources/UIToolkit/List/UTKMultiColumnTreeView.uss\" \"Assets/Resources/UIToolkit/List/UTKMultiColumnListView.uss\" \"Assets/Resources/UIToolkit/Style/UTKDefaultStyle.uss\" \"Assets/Resources/UIToolkit/Tab/UTKTabView.uss\" \"Assets/Resources/UIToolkit/List/UTKListView.uss\" \"Assets/Resources/UIToolkit/Style/UTKComponents.uss\")",
|
||||||
"Bash(cmd /c \"cd /d d:\\\\works\\\\2025\\\\02.Studio\\\\dev\\\\base\\\\XRBase && git log --oneline -10 -- Assets/Resources/UIToolkit/Style/UTKDefaultStyle.uss\")"
|
"Bash(cmd /c \"cd /d d:\\\\works\\\\2025\\\\02.Studio\\\\dev\\\\base\\\\XRBase && git log --oneline -10 -- Assets/Resources/UIToolkit/Style/UTKDefaultStyle.uss\")",
|
||||||
|
"Bash(New-Item -ItemType Directory -Path \"d:\\\\works\\\\2025\\\\02.Studio\\\\dev\\\\base\\\\XRBase\\\\Assets\\\\Resources\\\\UIToolkit\\\\Sample\\\\Window\" -Force)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
|
|||||||
@@ -287,6 +287,9 @@ namespace UVC.UIToolkit.Editor
|
|||||||
sb.AppendLine($" /// // 아이콘 존재 여부 확인");
|
sb.AppendLine($" /// // 아이콘 존재 여부 확인");
|
||||||
sb.AppendLine($" /// if ({className}.HasIcon(\"search\")) {{ }}");
|
sb.AppendLine($" /// if ({className}.HasIcon(\"search\")) {{ }}");
|
||||||
sb.AppendLine(" /// ");
|
sb.AppendLine(" /// ");
|
||||||
|
sb.AppendLine($" /// // 존재하는 유니코드 문자인지 확인");
|
||||||
|
sb.AppendLine($" /// if ({className}.IsIconChar(\"□\")) {{ }}");
|
||||||
|
sb.AppendLine(" /// ");
|
||||||
sb.AppendLine($" /// // 전체 아이콘 이름 순회");
|
sb.AppendLine($" /// // 전체 아이콘 이름 순회");
|
||||||
sb.AppendLine($" /// foreach (var name in {className}.GetAllIconNames()) {{ }}");
|
sb.AppendLine($" /// foreach (var name in {className}.GetAllIconNames()) {{ }}");
|
||||||
sb.AppendLine(" /// ");
|
sb.AppendLine(" /// ");
|
||||||
@@ -397,10 +400,10 @@ namespace UVC.UIToolkit.Editor
|
|||||||
sb.AppendLine(" /// </summary>");
|
sb.AppendLine(" /// </summary>");
|
||||||
sb.AppendLine(" /// <param name=\"element\">스타일을 적용할 요소</param>");
|
sb.AppendLine(" /// <param name=\"element\">스타일을 적용할 요소</param>");
|
||||||
sb.AppendLine(" /// <param name=\"fontSize\">폰트 크기 (기본값: 24)</param>");
|
sb.AppendLine(" /// <param name=\"fontSize\">폰트 크기 (기본값: 24)</param>");
|
||||||
sb.AppendLine(" public static void ApplyIconStyle(VisualElement element, int fontSize = 24)");
|
sb.AppendLine(" public static void ApplyIconStyle(VisualElement element, int? fontSize = 24)");
|
||||||
sb.AppendLine(" {");
|
sb.AppendLine(" {");
|
||||||
sb.AppendLine(" element.style.unityFontDefinition = GetFontDefinition();");
|
sb.AppendLine(" element.style.unityFontDefinition = GetFontDefinition();");
|
||||||
sb.AppendLine(" element.style.fontSize = fontSize;");
|
sb.AppendLine(" if(fontSize != null) element.style.fontSize = fontSize.Value;");
|
||||||
sb.AppendLine(" }");
|
sb.AppendLine(" }");
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
sb.AppendLine(" /// <summary>");
|
sb.AppendLine(" /// <summary>");
|
||||||
@@ -462,6 +465,7 @@ namespace UVC.UIToolkit.Editor
|
|||||||
sb.AppendLine(" /// <returns>아이콘 문자, 없으면 빈 문자열</returns>");
|
sb.AppendLine(" /// <returns>아이콘 문자, 없으면 빈 문자열</returns>");
|
||||||
sb.AppendLine(" public static string GetIcon(string iconName)");
|
sb.AppendLine(" public static string GetIcon(string iconName)");
|
||||||
sb.AppendLine(" {");
|
sb.AppendLine(" {");
|
||||||
|
sb.AppendLine(" if(IsIconChar(iconName)) return iconName;");
|
||||||
sb.AppendLine(" return _iconsByName.TryGetValue(iconName, out var icon) ? icon : string.Empty;");
|
sb.AppendLine(" return _iconsByName.TryGetValue(iconName, out var icon) ? icon : string.Empty;");
|
||||||
sb.AppendLine(" }");
|
sb.AppendLine(" }");
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
@@ -472,6 +476,12 @@ namespace UVC.UIToolkit.Editor
|
|||||||
sb.AppendLine(" public static bool HasIcon(string iconName) => _iconsByName.ContainsKey(iconName);");
|
sb.AppendLine(" public static bool HasIcon(string iconName) => _iconsByName.ContainsKey(iconName);");
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
|
|
||||||
|
sb.AppendLine(" /// <summary>");
|
||||||
|
sb.AppendLine(" /// 유니코드 문자로 아이콘이 존재하는지 확인합니다.");
|
||||||
|
sb.AppendLine(" /// </summary>");
|
||||||
|
sb.AppendLine(" public static bool IsIconChar(string iconChar) => _iconsByName.Values.Contains(iconChar);");
|
||||||
|
sb.AppendLine();
|
||||||
|
|
||||||
sb.AppendLine(" /// <summary>");
|
sb.AppendLine(" /// <summary>");
|
||||||
sb.AppendLine(" /// 모든 아이콘 이름 목록을 반환합니다.");
|
sb.AppendLine(" /// 모든 아이콘 이름 목록을 반환합니다.");
|
||||||
sb.AppendLine(" /// </summary>");
|
sb.AppendLine(" /// </summary>");
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:ui="UnityEngine.UIElements"
|
xmlns:ui="UnityEngine.UIElements"
|
||||||
|
xmlns:utk="UVC.UIToolkit"
|
||||||
noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd"
|
noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd"
|
||||||
editor-extension-mode="False">
|
editor-extension-mode="False">
|
||||||
<!--
|
<!--
|
||||||
@@ -13,7 +14,7 @@
|
|||||||
- container: 메인 컨테이너
|
- container: 메인 컨테이너
|
||||||
- search-container: 검색 영역
|
- search-container: 검색 영역
|
||||||
- search-field: 검색어 입력 필드
|
- search-field: 검색어 입력 필드
|
||||||
- clear-btn: 검색어 지우기 버튼
|
- clear-btn: UTKButton 검색어 지우기 버튼
|
||||||
- search-result-label: 검색 결과 건수 표시
|
- search-result-label: 검색 결과 건수 표시
|
||||||
- accordion-tree-view: TreeView (가상화 지원)
|
- accordion-tree-view: TreeView (가상화 지원)
|
||||||
-->
|
-->
|
||||||
@@ -23,7 +24,7 @@
|
|||||||
<ui:TextField name="search-field"
|
<ui:TextField name="search-field"
|
||||||
placeholder-text="검색"
|
placeholder-text="검색"
|
||||||
class="accordion-search-field">
|
class="accordion-search-field">
|
||||||
<ui:Button name="clear-btn" class="accordion-clear-button" />
|
<utk:UTKButton name="clear-btn" variant="Text" icon-only="true" class="accordion-clear-button" />
|
||||||
</ui:TextField>
|
</ui:TextField>
|
||||||
|
|
||||||
<!-- 검색 결과 라벨 (기본 숨김) -->
|
<!-- 검색 결과 라벨 (기본 숨김) -->
|
||||||
|
|||||||
@@ -22,22 +22,21 @@
|
|||||||
margin: 0 0 var(--space-m) 0;
|
margin: 0 0 var(--space-m) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
Clear 버튼 (Clear Button) - UTKButton 스타일 오버라이드
|
||||||
|
============================================ */
|
||||||
|
|
||||||
.accordion-clear-button {
|
.accordion-clear-button {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
|
min-width: 16px;
|
||||||
|
min-height: 16px;
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: transparent;
|
|
||||||
background-image: resource('UIToolkit/Images/btn_close_16');
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: var(--space-s);
|
right: var(--space-s);
|
||||||
align-self: center;
|
align-self: center;
|
||||||
-unity-background-image-tint-color: var(--color-text-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.accordion-clear-button:hover {
|
|
||||||
-unity-background-image-tint-color: var(--color-text-primary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-search-result-label {
|
.accordion-search-result-label {
|
||||||
@@ -220,6 +219,10 @@
|
|||||||
-unity-background-scale-mode: scale-to-fit;
|
-unity-background-scale-mode: scale-to-fit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.accordion-head-image .unity-label {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.accordion-content-button {
|
.accordion-content-button {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -228,6 +231,7 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
-unity-text-align: middle-left;
|
-unity-text-align: middle-left;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-content-button:hover {
|
.accordion-content-button:hover {
|
||||||
@@ -1,9 +1,35 @@
|
|||||||
<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">
|
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
<Style src="project://database/Assets/Resources/UIToolkit/List/UTKComponentList.uss?fileID=7433441132597879392&guid=71cac0276293ce2479851f572ffbda27&type=3#UTKComponentList" />
|
xmlns:ui="UnityEngine.UIElements"
|
||||||
|
xmlns:utk="UVC.UIToolkit"
|
||||||
|
noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd"
|
||||||
|
editor-extension-mode="False">
|
||||||
|
<!--
|
||||||
|
UTKComponentList.uxml
|
||||||
|
|
||||||
|
컴포넌트 리스트의 메인 레이아웃입니다.
|
||||||
|
검색 필드와 TreeView로 구성됩니다.
|
||||||
|
|
||||||
|
구조:
|
||||||
|
- container: 메인 컨테이너
|
||||||
|
- search-field: 검색어 입력 필드
|
||||||
|
- clear-btn: UTKButton 검색어 지우기 버튼
|
||||||
|
- main-tree-view: 트리뷰
|
||||||
|
-->
|
||||||
|
<Style src="project://database/Assets/Resources/UIToolkit/List/UTKComponentList.uss" />
|
||||||
<ui:VisualElement name="container" class="tree-menu-container">
|
<ui:VisualElement name="container" class="tree-menu-container">
|
||||||
<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 name="search-field"
|
||||||
|
placeholder-text="검색"
|
||||||
|
class="search-field">
|
||||||
|
<utk:UTKButton name="clear-btn" variant="Text" icon-only="true" class="search-clear-button" />
|
||||||
</ui:TextField>
|
</ui:TextField>
|
||||||
<ui:TreeView name="main-tree-view" view-data-key="model-tree-view" fixed-item-height="18" auto-expand="false" horizontal-scrolling="true" selection-type="Multiple" style="flex-grow: 1;" />
|
<!-- 트리뷰 -->
|
||||||
|
<ui:TreeView name="main-tree-view"
|
||||||
|
view-data-key="model-tree-view"
|
||||||
|
fixed-item-height="18"
|
||||||
|
auto-expand="false"
|
||||||
|
horizontal-scrolling="true"
|
||||||
|
selection-type="Multiple"
|
||||||
|
style="flex-grow: 1;" />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:UXML>
|
</ui:UXML>
|
||||||
|
|||||||
@@ -1,7 +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">
|
<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/UTKComponentListWindow.uss?fileID=7433441132597879392&guid=3df97248d26591046ab077258a2e2e44&type=3#UTKComponentListWindow" />
|
<Style src="project://database/Assets/Resources/UIToolkit/Window/UTKComponentListWindow.uss?fileID=7433441132597879392&guid=3df97248d26591046ab077258a2e2e44&type=3#UTKComponentListWindow" />
|
||||||
<ui:VisualElement name="item-root" class="tree-item-container" style="flex-direction: row; justify-content: space-between; height: 22px; padding-left: 0; padding-right: 8px; align-items: center; padding-top: 0; padding-bottom: 0;">
|
<ui:VisualElement name="item-root" class="tree-item-container" style="flex-direction: row; justify-content: space-between; height: 22px; padding-left: 0; padding-right: 8px; align-items: center; padding-top: 0; padding-bottom: 0;">
|
||||||
<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'); -unity-text-align: middle-left; height: 22px;" />
|
<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: 12px; -unity-font-definition: resource('Fonts/Pretendard/Pretendard-Bold'); -unity-text-align: middle-left; height: 22px;" />
|
||||||
<ui:Button name="setting-btn" class="visibility-toggle" style="background-image: resource('UIToolkit/Images/icon_setting_22'); -unity-text-align: middle-right; width: 22px; height: 22px;" />
|
<ui:Button name="setting-btn" class="visibility-toggle" style="background-image: resource('UIToolkit/Images/icon_setting_22'); -unity-text-align: middle-right; width: 22px; height: 22px;" />
|
||||||
<ui:Label name="badge-label" text="0" class="item-label-style" style="flex-grow: 0; 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: 9px; -unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium'); min-width: 18px; height: 18px; -unity-text-align: middle-center; align-items: center; border-top-left-radius: 9px; border-top-right-radius: 9px; border-bottom-left-radius: 9px; border-bottom-right-radius: 9px; background-color: rgb(69, 69, 69);" />
|
<ui:Label name="badge-label" text="0" class="item-label-style" style="flex-grow: 0; 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: 9px; -unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium'); min-width: 18px; height: 18px; -unity-text-align: middle-center; align-items: center; border-top-left-radius: 9px; border-top-right-radius: 9px; border-bottom-left-radius: 9px; border-bottom-right-radius: 9px; background-color: rgb(69, 69, 69);" />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
|
|||||||
@@ -1,7 +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">
|
<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/UTKComponentListWindow.uss?fileID=7433441132597879392&guid=3df97248d26591046ab077258a2e2e44&type=3#UTKComponentListWindow" />
|
<Style src="project://database/Assets/Resources/UIToolkit/Window/UTKComponentListWindow.uss?fileID=7433441132597879392&guid=3df97248d26591046ab077258a2e2e44&type=3#UTKComponentListWindow" />
|
||||||
<ui:VisualElement name="item-root" class="tree-item-container" style="flex-direction: row; justify-content: space-between; height: 22px; padding-left: 0; padding-right: 8px; align-items: center; padding-top: 0; padding-bottom: 0;">
|
<ui:VisualElement name="item-root" class="tree-item-container" style="flex-direction: row; justify-content: space-between; height: 22px; padding-left: 0; padding-right: 8px; align-items: center; padding-top: 0; padding-bottom: 0;">
|
||||||
<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: 13px; -unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium'); -unity-text-align: middle-left;" />
|
<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-Medium'); -unity-text-align: middle-left;" />
|
||||||
<ui:Button name="search-btn" class="visibility-toggle" style="width: 22px; background-image: resource('UIToolkit/Images/icon_search_22x16');" />
|
<ui:Button name="search-btn" class="visibility-toggle" style="width: 22px; background-image: resource('UIToolkit/Images/icon_search_22x16');" />
|
||||||
<ui:Button name="visibility-btn" class="visibility-toggle" style="width: 22px;" />
|
<ui:Button name="visibility-btn" class="visibility-toggle" style="width: 22px;" />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* UTKComponentList.uss
|
||||||
|
*
|
||||||
|
* UTKComponentList 컴포넌트의 스타일 정의입니다.
|
||||||
|
* 테마 지원: var(--color-*) 변수 사용
|
||||||
|
*/
|
||||||
|
|
||||||
.tree-menu-container {
|
.tree-menu-container {
|
||||||
background-color: rgb(37, 37, 38);
|
background-color: var(--color-bg-panel);
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
@@ -14,6 +21,24 @@
|
|||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
Clear 버튼 (Clear Button) - UTKButton 스타일 오버라이드
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
.search-clear-button {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
min-width: 16px;
|
||||||
|
min-height: 16px;
|
||||||
|
border-width: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
align-self: center;
|
||||||
|
position: absolute;
|
||||||
|
right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 카테고리 확장/축소 토글 화살표 스타일 */
|
/* 카테고리 확장/축소 토글 화살표 스타일 */
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:ui="UnityEngine.UIElements"
|
xmlns:ui="UnityEngine.UIElements"
|
||||||
|
xmlns:utk="UVC.UIToolkit"
|
||||||
noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd"
|
noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd"
|
||||||
editor-extension-mode="False">
|
editor-extension-mode="False">
|
||||||
<!--
|
<!--
|
||||||
@@ -11,7 +12,7 @@
|
|||||||
구조:
|
구조:
|
||||||
- container: 메인 컨테이너
|
- container: 메인 컨테이너
|
||||||
- search-field: 검색어 입력 필드
|
- search-field: 검색어 입력 필드
|
||||||
- clear-btn: 검색어 지우기 버튼
|
- clear-btn: UTKButton 검색어 지우기 버튼
|
||||||
- search-result-label: 검색 결과 건수 표시
|
- search-result-label: 검색 결과 건수 표시
|
||||||
- main-list-view: 아이템 목록 표시
|
- main-list-view: 아이템 목록 표시
|
||||||
-->
|
-->
|
||||||
@@ -21,7 +22,7 @@
|
|||||||
<ui:TextField name="search-field"
|
<ui:TextField name="search-field"
|
||||||
placeholder-text="검색"
|
placeholder-text="검색"
|
||||||
class="search-field">
|
class="search-field">
|
||||||
<ui:Button name="clear-btn" class="clear-button" />
|
<utk:UTKButton name="clear-btn" variant="Text" icon-only="true" class="clear-button" />
|
||||||
</ui:TextField>
|
</ui:TextField>
|
||||||
|
|
||||||
<!-- 검색 결과 라벨 (기본 숨김) -->
|
<!-- 검색 결과 라벨 (기본 숨김) -->
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
.image-list-container {
|
.image-list-container {
|
||||||
background-color: rgb(37, 37, 38);
|
background-color: var(--color-bg-panel);
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -13,27 +13,26 @@
|
|||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
Clear 버튼 (Clear Button) - UTKButton 스타일 오버라이드
|
||||||
|
============================================ */
|
||||||
|
|
||||||
.clear-button {
|
.clear-button {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
|
min-width: 16px;
|
||||||
|
min-height: 16px;
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: rgba(255, 255, 255, 0);
|
|
||||||
background-image: resource('UIToolkit/Images/btn_close_16');
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 4px;
|
right: 4px;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
-unity-background-image-tint-color: rgb(180, 180, 180);
|
|
||||||
}
|
|
||||||
|
|
||||||
.clear-button:hover {
|
|
||||||
-unity-background-image-tint-color: rgb(220, 220, 220);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-result-label {
|
.search-result-label {
|
||||||
color: rgb(180, 180, 180);
|
color: var(--color-text-secondary);
|
||||||
font-size: 11px;
|
font-size: var(--font-size-label4);
|
||||||
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
@@ -127,8 +126,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.item-label {
|
.item-label {
|
||||||
color: rgb(204, 204, 204);
|
color: var(--color-text-primary);
|
||||||
font-size: 11px;
|
font-size: var(--font-size-label4);
|
||||||
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
||||||
-unity-text-align: upper-left;
|
-unity-text-align: upper-left;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
8
Assets/Resources/UIToolkit/Sample/Window.meta
Normal file
8
Assets/Resources/UIToolkit/Sample/Window.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a5464101e260c7c47924298006864957
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<UXML xmlns="UnityEngine.UIElements" xmlns:utk="UVC.UIToolkit">
|
||||||
|
<Style src="../UTKSampleCommon.uss" />
|
||||||
|
<Style src="UTKWindowSample.uss" />
|
||||||
|
|
||||||
|
<VisualElement class="utk-sample-container">
|
||||||
|
<Label class="utk-sample-desc" text="아코디언 리스트를 윈도우 형태로 래핑한 컴포넌트입니다. 헤더(타이틀, 닫기 버튼)와 내부 UTKAccordionList로 구성됩니다." />
|
||||||
|
|
||||||
|
<VisualElement class="utk-sample-section">
|
||||||
|
<Label class="utk-sample-section__title" text="UTKAccordionListWindow" />
|
||||||
|
<VisualElement name="accordion-list-window-container" class="utk-window-sample-container" />
|
||||||
|
</VisualElement>
|
||||||
|
|
||||||
|
<!-- Code Sample -->
|
||||||
|
<VisualElement class="utk-code-sample-container">
|
||||||
|
<utk:UTKCodeBlock title="C#" code="// 1. 윈도우 참조 획득 var accordionWindow = root.Q<UTKAccordionListWindow>("accordion-window"); // 2. 윈도우 제목 및 닫기 버튼 설정 accordionWindow.Title = "프리팹 라이브러리"; accordionWindow.ShowCloseButton = true; // 3. 데이터 구성 var data = new List<UTKAccordionItemData> { new UTKAccordionItemData { nodeType = UTKAccordionNodeType.Section, name = "가구", isExpanded = true, children = new List<UTKAccordionItemData> { new UTKAccordionItemData { nodeType = UTKAccordionNodeType.GridItem, name = "의자", imagePath = "Thumbnails/chair", prefabPath = "Prefabs/Chair" } } } }; accordionWindow.SetData(data); // 4. 아이템 클릭 이벤트 accordionWindow.OnItemClick += (item) => Debug.Log($"클릭: {item.name}"); // 5. 드래그 앤 드롭 이벤트 accordionWindow.OnItemDrop += (item) => { var prefab = Resources.Load<GameObject>(item.prefabPath); Instantiate(prefab); }; // 6. 윈도우 닫힘 이벤트 accordionWindow.OnClosed += () => Debug.Log("윈도우 닫힘");" />
|
||||||
|
<utk:UTKCodeBlock title="UXML" code="<utk:UTKAccordionListWindow name="accordion-window" />" />
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
</UXML>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d73f28c7e05421d4092bae5eff8c041a
|
||||||
|
ScriptedImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<UXML xmlns="UnityEngine.UIElements" xmlns:utk="UVC.UIToolkit">
|
||||||
|
<Style src="../UTKSampleCommon.uss" />
|
||||||
|
<Style src="UTKWindowSample.uss" />
|
||||||
|
|
||||||
|
<VisualElement class="utk-sample-container">
|
||||||
|
<Label class="utk-sample-desc" text="컴포넌트 리스트를 윈도우 형태로 래핑한 컴포넌트입니다. 계층 구조(카테고리/아이템)와 가시성 토글, 검색 기능을 제공합니다." />
|
||||||
|
|
||||||
|
<VisualElement class="utk-sample-section">
|
||||||
|
<Label class="utk-sample-section__title" text="UTKComponentListWindow" />
|
||||||
|
<VisualElement name="component-list-window-container" class="utk-window-sample-container" />
|
||||||
|
</VisualElement>
|
||||||
|
|
||||||
|
<!-- Code Sample -->
|
||||||
|
<VisualElement class="utk-code-sample-container">
|
||||||
|
<utk:UTKCodeBlock title="C#" code="// 1. 윈도우 참조 획득 var componentWindow = root.Q<UTKComponentListWindow>("component-window"); // 2. 윈도우 제목 및 닫기 버튼 설정 componentWindow.Title = "모델 리스트"; componentWindow.ShowCloseButton = true; // 3. 데이터 구성 - 카테고리와 아이템 var data = new List<UTKComponentListItemDataBase> { new UTKComponentListCategoryData { name = "캐릭터", isExpanded = true, children = new List<UTKComponentListItemDataBase> { new UTKComponentListItemData { name = "플레이어", ExternalKey = "player_001", IsVisible = true } } } }; componentWindow.SetData(data); // 4. 선택 이벤트 componentWindow.OnItemSelected = (items) => { foreach (var item in items) Debug.Log($"선택됨: {item.name}"); }; // 5. 가시성 변경 이벤트 (눈 아이콘) componentWindow.OnItemVisibilityChanged += (item, isVisible) => { FindGameObject(item.ExternalKey)?.SetActive(isVisible); }; // 6. 삭제 이벤트 (Delete 키) componentWindow.EnabledDeleteItem = true; componentWindow.OnItemDeleted = (item) => { componentWindow.DeleteItem(item); }; // 7. 윈도우 표시 componentWindow.Show();" />
|
||||||
|
<utk:UTKCodeBlock title="UXML" code="<utk:UTKComponentListWindow name="component-window" />" />
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
</UXML>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 25afcb79f01aa7f4ba3c5cb0105332f8
|
||||||
|
ScriptedImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<UXML xmlns="UnityEngine.UIElements" xmlns:utk="UVC.UIToolkit">
|
||||||
|
<Style src="../UTKSampleCommon.uss" />
|
||||||
|
<Style src="UTKWindowSample.uss" />
|
||||||
|
|
||||||
|
<VisualElement class="utk-sample-container">
|
||||||
|
<Label class="utk-sample-desc" text="컴포넌트 리스트에 탭 기능을 추가한 윈도우입니다. 카테고리별 자동 탭 생성과 검색 기능을 제공합니다." />
|
||||||
|
|
||||||
|
<VisualElement class="utk-sample-section">
|
||||||
|
<Label class="utk-sample-section__title" text="UTKComponentTabListWindow" />
|
||||||
|
<VisualElement name="component-tab-list-window-container" class="utk-window-sample-container" />
|
||||||
|
</VisualElement>
|
||||||
|
|
||||||
|
<!-- Code Sample -->
|
||||||
|
<VisualElement class="utk-code-sample-container">
|
||||||
|
<utk:UTKCodeBlock title="C#" code="// 1. 윈도우 참조 획득 var tabWindow = root.Q<UTKComponentTabListWindow>("tab-window"); // 2. 윈도우 제목 설정 tabWindow.Title = "모델 라이브러리"; tabWindow.ShowCloseButton = true; // 3. 데이터 구성 (카테고리가 탭으로 자동 생성) var data = new List<UTKComponentListItemDataBase> { new UTKComponentListCategoryData { name = "캐릭터", // -> 첫 번째 탭 children = new List<UTKComponentListItemDataBase> { new UTKComponentListItemData { name = "Player" } } }, new UTKComponentListCategoryData { name = "환경", // -> 두 번째 탭 children = new List<UTKComponentListItemDataBase> { new UTKComponentListItemData { name = "Tree" } } } }; tabWindow.SetData(data); // 4. 탭 선택 (인덱스 기반) tabWindow.SelectTab(-1); // 전체 (All) tabWindow.SelectTab(0); // 첫 번째 카테고리 // 5. 탭 변경 이벤트 tabWindow.OnTabSelected = (tabIndex) => { Debug.Log($"선택된 탭: {tabIndex}"); }; // 6. 선택/가시성/삭제 이벤트 (UTKComponentListWindow와 동일) tabWindow.OnItemSelected = (items) => { }; tabWindow.OnItemVisibilityChanged += (item, visible) => { }; tabWindow.OnItemDeleted = (item) => { };" />
|
||||||
|
<utk:UTKCodeBlock title="UXML" code="<utk:UTKComponentTabListWindow name="tab-window" />" />
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
</UXML>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 35ee99024ae0d734184ea6faf770fd30
|
||||||
|
ScriptedImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<UXML xmlns="UnityEngine.UIElements" xmlns:utk="UVC.UIToolkit">
|
||||||
|
<Style src="../UTKSampleCommon.uss" />
|
||||||
|
<Style src="UTKWindowSample.uss" />
|
||||||
|
|
||||||
|
<VisualElement class="utk-sample-container">
|
||||||
|
<Label class="utk-sample-desc" text="이미지 그리드 리스트를 윈도우 형태로 래핑한 컴포넌트입니다. 썸네일 이미지와 드래그 앤 드롭 기능을 제공합니다." />
|
||||||
|
|
||||||
|
<VisualElement class="utk-sample-section">
|
||||||
|
<Label class="utk-sample-section__title" text="UTKImageListWindow" />
|
||||||
|
<VisualElement name="image-list-window-container" class="utk-window-sample-container" />
|
||||||
|
</VisualElement>
|
||||||
|
|
||||||
|
<!-- Code Sample -->
|
||||||
|
<VisualElement class="utk-code-sample-container">
|
||||||
|
<utk:UTKCodeBlock title="C#" code="// 1. 윈도우 참조 획득 var imageWindow = root.Q<UTKImageListWindow>("image-window"); // 2. 윈도우 제목 설정 imageWindow.Title = "텍스처 라이브러리"; imageWindow.ShowCloseButton = true; // 3. 데이터 구성 var data = new List<UTKImageListItemData> { new UTKImageListItemData { itemName = "Texture_01", imagePath = "Textures/texture_01", externalId = "tex_001" }, new UTKImageListItemData { itemName = "Texture_02", imagePath = "Textures/texture_02", externalId = "tex_002" } }; imageWindow.SetData(data); // 4. 클릭 이벤트 imageWindow.OnItemClicked = (item) => { Debug.Log($"클릭: {item.itemName}"); }; // 5. 드래그 앤 드롭 이벤트 imageWindow.OnItemBeginDrag += (item, screenPos) => { Debug.Log($"드래그 시작: {item.itemName}"); }; imageWindow.OnItemDrop += (item) => { Debug.Log($"드롭: {item.itemName}"); }; // 6. 리스트 영역 벗어남 감지 imageWindow.OnDragExitList += (item, screenPos) => { Show3DPreview(item.externalId); }; // 7. 드래그 고스트 표시 imageWindow.ShowDragGhost = true; // 8. 아이템 추가/삭제 imageWindow.AddItem(newItem); imageWindow.RemoveItem(item);" />
|
||||||
|
<utk:UTKCodeBlock title="UXML" code="<utk:UTKImageListWindow name="image-window" />" />
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
</UXML>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 500d626a4cd6fa3468ecb877e41f84d2
|
||||||
|
ScriptedImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<UXML xmlns="UnityEngine.UIElements" xmlns:utk="UVC.UIToolkit">
|
||||||
|
<Style src="../UTKSampleCommon.uss" />
|
||||||
|
<Style src="UTKWindowSample.uss" />
|
||||||
|
|
||||||
|
<VisualElement class="utk-sample-container">
|
||||||
|
<Label class="utk-sample-desc" text="트리뷰 리스트를 윈도우 형태로 래핑한 컴포넌트입니다. 계층적 데이터 구조와 가시성 토글, 검색 기능을 제공합니다." />
|
||||||
|
|
||||||
|
<VisualElement class="utk-sample-section">
|
||||||
|
<Label class="utk-sample-section__title" text="UTKTreeListWindow" />
|
||||||
|
<VisualElement name="tree-list-window-container" class="utk-window-sample-container" />
|
||||||
|
</VisualElement>
|
||||||
|
|
||||||
|
<!-- Code Sample -->
|
||||||
|
<VisualElement class="utk-code-sample-container">
|
||||||
|
<utk:UTKCodeBlock title="C#" code="// 1. 윈도우 참조 획득 var treeWindow = root.Q<UTKTreeListWindow>("tree-window"); // 2. 윈도우 제목 설정 treeWindow.Title = "씬 계층 구조"; treeWindow.ShowCloseButton = true; // 3. 트리 데이터 구성 var data = new List<UTKTreeListItemData> { new UTKTreeListItemData { name = "Root", isExpanded = true, children = new List<UTKTreeListItemData> { new UTKTreeListItemData { name = "Child 1", ExternalKey = "obj_001", IsVisible = true }, new UTKTreeListItemData { name = "Child 2", children = new List<UTKTreeListItemData> { new UTKTreeListItemData { name = "Grandchild" } } } } } }; treeWindow.SetData(data); // 4. 선택 이벤트 treeWindow.OnItemSelected = (items) => { foreach (var item in items) HighlightGameObject(item.ExternalKey); }; // 5. 가시성 변경 이벤트 treeWindow.OnItemVisibilityChanged += (item, isVisible) => { FindGameObject(item.ExternalKey)?.SetActive(isVisible); }; // 6. 삭제 이벤트 treeWindow.EnabledDeleteItem = true; treeWindow.OnItemDeleted = (item) => { treeWindow.DeleteItem(item); }; // 7. 프로그래밍 방식 선택 treeWindow.SelectByItemId(itemId); treeWindow.ClearSelection();" />
|
||||||
|
<utk:UTKCodeBlock title="UXML" code="<utk:UTKTreeListWindow name="tree-window" />" />
|
||||||
|
</VisualElement>
|
||||||
|
</VisualElement>
|
||||||
|
</UXML>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f7ffda55e7f57d14cbfa736a81e6edb4
|
||||||
|
ScriptedImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
24
Assets/Resources/UIToolkit/Sample/Window/UTKWindowSample.uss
Normal file
24
Assets/Resources/UIToolkit/Sample/Window/UTKWindowSample.uss
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* ===================================
|
||||||
|
* UTKWindowSample.uss
|
||||||
|
* Styles for UTK Window component samples
|
||||||
|
* ===================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ===================================
|
||||||
|
Window Sample Container
|
||||||
|
=================================== */
|
||||||
|
|
||||||
|
.utk-window-sample-container {
|
||||||
|
width: 350px;
|
||||||
|
height: 400px;
|
||||||
|
border-width: 1px;
|
||||||
|
border-color: var(--color-border-light);
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: var(--color-bg-tertiary);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.utk-window-sample-container > * {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 3df97248d26591046ab077258a2e2e44
|
guid: f29f5250983c71746a3384dd4af8a5c4
|
||||||
ScriptedImporter:
|
ScriptedImporter:
|
||||||
internalIDToNameTable: []
|
internalIDToNameTable: []
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
@@ -412,90 +412,6 @@
|
|||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ===================================
|
|
||||||
Dropdown Popup Menu
|
|
||||||
=================================== */
|
|
||||||
|
|
||||||
.unity-base-dropdown__container-outer {
|
|
||||||
border-radius: var(--radius-m);
|
|
||||||
border-width: var(--border-width);
|
|
||||||
border-color: var(--color-base-06);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-base-dropdown {
|
|
||||||
background-color: var(--color-base-01);
|
|
||||||
padding: var(--space-xs);
|
|
||||||
margin-top: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-base-dropdown__item {
|
|
||||||
height: 28px;
|
|
||||||
padding-left: var(--space-m);
|
|
||||||
padding-right: var(--space-m);
|
|
||||||
padding-top: var(--space-xs);
|
|
||||||
padding-bottom: var(--space-xs);
|
|
||||||
background-color: transparent;
|
|
||||||
border-radius: var(--radius-xs);
|
|
||||||
transition-duration: var(--anim-fast);
|
|
||||||
transition-property: background-color;
|
|
||||||
cursor: resource('UIToolkit/Images/cursor_point_white_32') 14 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-base-dropdown__item:hover:enabled {
|
|
||||||
background-color: var(--color-collection-item-hover) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-base-dropdown__item:checked {
|
|
||||||
background-color: var(--color-blue-05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-base-dropdown__item:checked:hover {
|
|
||||||
background-color: var(--color-blue-06);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 드롭다운 항목 콘텐츠 */
|
|
||||||
.unity-base-dropdown__item-content {
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-base-dropdown__item:hover .unity-base-dropdown__item-content {
|
|
||||||
background-color: var(--color-collection-item-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-base-dropdown__item:checked .unity-base-dropdown__item-content {
|
|
||||||
background-color: var(--color-blue-05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-base-dropdown__item:checked:hover .unity-base-dropdown__item-content {
|
|
||||||
background-color: var(--color-blue-06);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 드롭다운 항목 라벨 */
|
|
||||||
.unity-base-dropdown__label {
|
|
||||||
font-size: 12px;
|
|
||||||
color: var(--color-base-20);
|
|
||||||
-unity-text-align: middle-left;
|
|
||||||
padding-left: 0;
|
|
||||||
padding-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unity-base-dropdown__item:checked .unity-base-dropdown__label {
|
|
||||||
color: var(--color-base-01);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 드롭다운 체크마크 */
|
|
||||||
.unity-base-dropdown__item .unity-base-dropdown__checkmark {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
min-width: 16px;
|
|
||||||
min-height: 16px;
|
|
||||||
-unity-background-image-tint-color: var(--color-base-01);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ===================================
|
/* ===================================
|
||||||
Border Radius Utilities
|
Border Radius Utilities
|
||||||
=================================== */
|
=================================== */
|
||||||
|
|||||||
@@ -3,3 +3,5 @@
|
|||||||
@import url("UTKDefaultStyle.uss");
|
@import url("UTKDefaultStyle.uss");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,9 @@
|
|||||||
|
|
||||||
/* 드롭다운 팝업 컨테이너 - border 제거 (최외곽 컨테이너에만 border 적용) */
|
/* 드롭다운 팝업 컨테이너 - border 제거 (최외곽 컨테이너에만 border 적용) */
|
||||||
.unity-base-dropdown {
|
.unity-base-dropdown {
|
||||||
|
background-color: var(--color-base-01);
|
||||||
|
padding: var(--space-xs);
|
||||||
|
margin-top: 2px;
|
||||||
border-width: 0 ;
|
border-width: 0 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,10 +56,58 @@
|
|||||||
background-color: var(--color-collection-item-hover) ;
|
background-color: var(--color-collection-item-hover) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 드롭다운 항목 콘텐츠 */
|
||||||
|
.unity-base-dropdown__item-content {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.unity-base-dropdown__item:hover:enabled .unity-base-dropdown__item-content {
|
.unity-base-dropdown__item:hover:enabled .unity-base-dropdown__item-content {
|
||||||
background-color: var(--color-collection-item-hover) ;
|
background-color: var(--color-collection-item-hover) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unity-base-dropdown__item:checked {
|
||||||
|
background-color: var(--color-blue-05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.unity-base-dropdown__item:checked:hover {
|
||||||
|
background-color: var(--color-blue-06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.unity-base-dropdown__item:hover .unity-base-dropdown__item-content {
|
||||||
|
background-color: var(--color-collection-item-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.unity-base-dropdown__item:checked .unity-base-dropdown__item-content {
|
||||||
|
background-color: var(--color-blue-05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.unity-base-dropdown__item:checked:hover .unity-base-dropdown__item-content {
|
||||||
|
background-color: var(--color-blue-06);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 드롭다운 항목 라벨 */
|
||||||
|
.unity-base-dropdown__label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-base-20);
|
||||||
|
-unity-text-align: middle-left;
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.unity-base-dropdown__item:checked .unity-base-dropdown__label {
|
||||||
|
color: var(--color-base-01);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 드롭다운 체크마크 */
|
||||||
|
.unity-base-dropdown__item .unity-base-dropdown__checkmark {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
min-width: 16px;
|
||||||
|
min-height: 16px;
|
||||||
|
-unity-background-image-tint-color: var(--color-base-01);
|
||||||
|
}
|
||||||
|
|
||||||
/* ===================================
|
/* ===================================
|
||||||
ListView/TreeView 항목 텍스트 스타일
|
ListView/TreeView 항목 텍스트 스타일
|
||||||
@@ -92,6 +143,7 @@ ListView/TreeView 항목 텍스트 스타일
|
|||||||
|
|
||||||
.unity-tree-view__item-content {
|
.unity-tree-view__item-content {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TreeView 항목 텍스트 색상 */
|
/* TreeView 항목 텍스트 색상 */
|
||||||
@@ -135,10 +187,10 @@ TreeView 항목 스타일
|
|||||||
|
|
||||||
/* TreeView 토글 입력 영역 - 회전 중심 맞추기 */
|
/* TreeView 토글 입력 영역 - 회전 중심 맞추기 */
|
||||||
.unity-tree-view__item-toggle > .unity-toggle__input {
|
.unity-tree-view__item-toggle > .unity-toggle__input {
|
||||||
width: 16px;
|
width: 20px;
|
||||||
height: 16px;
|
height: 20px;
|
||||||
min-width: 16px;
|
min-width: 20px;
|
||||||
min-height: 16px;
|
min-height: 20px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -147,10 +199,10 @@ TreeView 항목 스타일
|
|||||||
|
|
||||||
/* TreeView 토글 체크마크(화살표 아이콘) */
|
/* TreeView 토글 체크마크(화살표 아이콘) */
|
||||||
.unity-tree-view__item-toggle > .unity-toggle__input > #unity-checkmark {
|
.unity-tree-view__item-toggle > .unity-toggle__input > #unity-checkmark {
|
||||||
width: 16px;
|
width: 20px;
|
||||||
height: 16px;
|
height: 20px;
|
||||||
min-width: 16px;
|
min-width: 20px;
|
||||||
min-height: 16px;
|
min-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TreeView 토글 체크됨(펼쳐진 상태) - 회전 없음 */
|
/* TreeView 토글 체크됨(펼쳐진 상태) - 회전 없음 */
|
||||||
@@ -170,6 +222,19 @@ TreeView 항목 스타일
|
|||||||
min-height: 16px;
|
min-height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unity-base-dropdown__item {
|
||||||
|
height: 28px;
|
||||||
|
padding-left: var(--space-m);
|
||||||
|
padding-right: var(--space-m);
|
||||||
|
padding-top: var(--space-xs);
|
||||||
|
padding-bottom: var(--space-xs);
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: var(--radius-xs);
|
||||||
|
transition-duration: var(--anim-fast);
|
||||||
|
transition-property: background-color;
|
||||||
|
cursor: resource('UIToolkit/Images/cursor_point_white_32') 14 5;
|
||||||
|
}
|
||||||
|
|
||||||
/* 드롭다운 라벨 스타일 오버라이드 */
|
/* 드롭다운 라벨 스타일 오버라이드 */
|
||||||
.unity-base-dropdown__item .unity-base-dropdown__label {
|
.unity-base-dropdown__item .unity-base-dropdown__label {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -185,6 +250,7 @@ TreeView 항목 스타일
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#unity-tree-view__item-toggle > VisualElement > VisualElement {
|
#unity-tree-view__item-toggle > VisualElement > VisualElement {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
@@ -204,9 +270,9 @@ Textfield 항목 스타일
|
|||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
||||||
/* --unity-selection-color: rgba(54, 98, 160, 0.651); 선택 색상 */
|
/* --unity-selection-color: rgba(54, 98, 160, 0.651); 선택 색상 */
|
||||||
--unity-cursor-color: rgb(255, 255, 255); /* 캐럿(커서) 색상 흰색 */
|
--unity-cursor-color: var(--color-base-01); /* 캐럿(커서) 색상 흰색 */
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: rgb(204, 204, 204);
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.unity-base-text-field__input {
|
.unity-base-text-field__input {
|
||||||
@@ -214,15 +280,10 @@ Textfield 항목 스타일
|
|||||||
padding-right: 24px;
|
padding-right: 24px;
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
border-top-left-radius: 0;
|
border-radius: var(--radius-s);
|
||||||
border-top-right-radius: 0;
|
border-width: var(--border-width);
|
||||||
border-bottom-right-radius: 0;
|
border-color: var(--color-border);
|
||||||
border-bottom-left-radius: 0;
|
background-color: var(--color-bg-input);
|
||||||
border-top-width: 0;
|
|
||||||
border-right-width: 0;
|
|
||||||
border-bottom-width: 0;
|
|
||||||
border-left-width: 0;
|
|
||||||
background-color: rgb(60, 60, 60);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.unity-base-text-field__input--placeholder {
|
.unity-base-text-field__input--placeholder {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:ui="UnityEngine.UIElements"
|
xmlns:ui="UnityEngine.UIElements"
|
||||||
xmlns:uvc="UVC.UIToolkit.List"
|
xmlns:utk="UVC.UIToolkit"
|
||||||
noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd"
|
noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd"
|
||||||
editor-extension-mode="False">
|
editor-extension-mode="False">
|
||||||
<!--
|
<!--
|
||||||
@@ -13,18 +13,18 @@
|
|||||||
- container: 메인 컨테이너
|
- container: 메인 컨테이너
|
||||||
- header: 윈도우 헤더
|
- header: 윈도우 헤더
|
||||||
- title: 윈도우 제목
|
- title: 윈도우 제목
|
||||||
- close-btn: 닫기 버튼
|
- close-btn: UTKButton 닫기 버튼
|
||||||
- UTKAccordionList: 아코디언 리스트 컴포넌트
|
- UTKAccordionList: 아코디언 리스트 컴포넌트
|
||||||
-->
|
-->
|
||||||
<Style src="project://database/Assets/Resources/UIToolkit/Window/UTKAccordionListWindow.uss" />
|
<!-- Style은 C# 코드에서 테마 적용 후 로드됩니다 -->
|
||||||
<ui:VisualElement name="container" class="accordion-list-window-container">
|
<ui:VisualElement name="container" class="accordion-list-window-container">
|
||||||
<!-- 헤더 영역 -->
|
<!-- 헤더 영역 -->
|
||||||
<ui:VisualElement name="header" class="accordion-window-header">
|
<ui:VisualElement name="header" class="accordion-window-header">
|
||||||
<ui:Label name="title" text="ACCORDION" class="accordion-window-title" />
|
<ui:Label name="title" text="ACCORDION" class="accordion-window-title" />
|
||||||
<ui:Button name="close-btn" class="accordion-window-close-button" />
|
<utk:UTKButton name="close-btn" variant="Text" icon-only="true" class="accordion-window-close-button" />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
|
|
||||||
<!-- 내부 UTKAccordionList 컴포넌트 -->
|
<!-- 내부 UTKAccordionList 컴포넌트 -->
|
||||||
<uvc:UTKAccordionList />
|
<utk:UTKAccordionList />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:UXML>
|
</ui:UXML>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
*
|
*
|
||||||
* UTKAccordionListWindow 컴포넌트의 스타일 정의입니다.
|
* UTKAccordionListWindow 컴포넌트의 스타일 정의입니다.
|
||||||
* UTKAccordionList를 래핑하는 윈도우 형태의 컨테이너입니다.
|
* UTKAccordionList를 래핑하는 윈도우 형태의 컨테이너입니다.
|
||||||
|
* 테마 지원: var(--color-*) 변수 사용
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* ============================================
|
/* ============================================
|
||||||
@@ -22,7 +23,7 @@ UTKAccordionListWindow {
|
|||||||
============================================ */
|
============================================ */
|
||||||
|
|
||||||
.accordion-list-window-container {
|
.accordion-list-window-container {
|
||||||
background-color: rgb(37, 37, 38);
|
background-color: var(--color-bg-panel);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
padding: 10px 20px 25px 20px;
|
padding: 10px 20px 25px 20px;
|
||||||
@@ -43,8 +44,8 @@ UTKAccordionListWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.accordion-window-title {
|
.accordion-window-title {
|
||||||
color: rgb(204, 204, 204);
|
color: var(--color-text-primary);
|
||||||
font-size: 11px;
|
font-size: var(--font-size-label3);
|
||||||
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
||||||
-unity-font-style: normal;
|
-unity-font-style: normal;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -53,26 +54,17 @@ UTKAccordionListWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================
|
/* ============================================
|
||||||
닫기 버튼 (Close Button)
|
닫기 버튼 (Close Button) - UTKButton 스타일 오버라이드
|
||||||
============================================ */
|
============================================ */
|
||||||
|
|
||||||
.accordion-window-close-button {
|
.accordion-window-close-button {
|
||||||
width: 22px;
|
width: 22px;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
|
min-width: 22px;
|
||||||
|
min-height: 22px;
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: rgba(0, 0, 0, 0);
|
|
||||||
background-image: resource('UIToolkit/Images/btn_close_22');
|
|
||||||
align-self: center;
|
align-self: center;
|
||||||
display: none; /* 기본 숨김, 필요시 flex로 변경 */
|
display: none; /* 기본 숨김, 필요시 flex로 변경 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordion-window-close-button:hover {
|
|
||||||
background-color: rgba(255, 255, 255, 0.1);
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.accordion-window-close-button:active {
|
|
||||||
background-color: rgba(255, 255, 255, 0.2);
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
UTKComponentListWindow {
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
UTKComponentTabListWindow {
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 400px;
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
background-color: rgb(37, 37, 38);
|
|
||||||
height: 100%;
|
|
||||||
align-self: flex-start;
|
|
||||||
padding: 5px;
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-bottom: 25px;
|
|
||||||
padding-left: 20px;
|
|
||||||
padding-right: 20px;
|
|
||||||
width: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.tab-button {
|
|
||||||
background-color: #1E1E1E;
|
|
||||||
border-width: 0;
|
|
||||||
border-radius: 0px;
|
|
||||||
padding-left: 12px;
|
|
||||||
padding-right: 12px;
|
|
||||||
padding-top: 4px;
|
|
||||||
padding-bottom: 4px;
|
|
||||||
margin-right: 1px;
|
|
||||||
margin-left: 0;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
color: #A0A0A0;
|
|
||||||
font-size: 11px;
|
|
||||||
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-button:hover {
|
|
||||||
background-color: #292929;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-button-selected {
|
|
||||||
background-color: #303031;
|
|
||||||
color: rgb(255, 255, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-button-selected:hover {
|
|
||||||
background-color: #3A3D41;
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,27 @@
|
|||||||
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xmlns:uvc="UVC.UIToolkit.List" noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
<Style src="project://database/Assets/Resources/UIToolkit/Window/UTKComponentListWindow.uss?fileID=7433441132597879392&guid=3df97248d26591046ab077258a2e2e44&type=3#UTKComponentListWindow" />
|
xmlns:ui="UnityEngine.UIElements"
|
||||||
|
xmlns:utk="UVC.UIToolkit"
|
||||||
|
noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd"
|
||||||
|
editor-extension-mode="False">
|
||||||
|
<!--
|
||||||
|
UTKComponentListWindow.uxml
|
||||||
|
|
||||||
|
UTKComponentList를 래핑하는 윈도우 컴포넌트입니다.
|
||||||
|
헤더(타이틀, 닫기 버튼)와 내부 UTKComponentList로 구성됩니다.
|
||||||
|
|
||||||
|
구조:
|
||||||
|
- container: 메인 컨테이너
|
||||||
|
- header: 윈도우 헤더
|
||||||
|
- title: 윈도우 제목
|
||||||
|
- close-btn: UTKButton 닫기 버튼
|
||||||
|
- UTKComponentList: 컴포넌트 리스트
|
||||||
|
-->
|
||||||
|
<!-- Style은 C# 코드에서 테마 적용 후 로드됩니다 -->
|
||||||
<ui:VisualElement name="container" class="container" style="flex-grow: 1; flex-shrink: 0;">
|
<ui:VisualElement name="container" class="container" style="flex-grow: 1; flex-shrink: 0;">
|
||||||
<ui:VisualElement name="header" style="flex-direction: row; margin-bottom: 5px; justify-content: space-between; margin-top: 0;">
|
<ui:VisualElement name="header" class="component-window-header">
|
||||||
<ui:Label text="EXPLORER" 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:Label name="title" text="EXPLORER" class="component-window-title" />
|
||||||
<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;" />
|
<utk:UTKButton name="close-btn" variant="Text" icon-only="true" class="component-window-close-button" />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<uvc:UTKComponentList />
|
<utk:UTKComponentList />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:UXML>
|
</ui:UXML>
|
||||||
|
|||||||
108
Assets/Resources/UIToolkit/Window/UTKComponentListWindowUss.uss
Normal file
108
Assets/Resources/UIToolkit/Window/UTKComponentListWindowUss.uss
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* UTKComponentListWindow.uss
|
||||||
|
*
|
||||||
|
* UTKComponentListWindow 및 UTKComponentTabListWindow 컴포넌트의 스타일 정의입니다.
|
||||||
|
* 테마 지원: var(--color-*) 변수 사용
|
||||||
|
*/
|
||||||
|
|
||||||
|
UTKComponentListWindow {
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UTKComponentTabListWindow {
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 400px;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
background-color: var(--color-bg-panel);
|
||||||
|
height: 100%;
|
||||||
|
align-self: flex-start;
|
||||||
|
padding: 5px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 25px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
헤더 (Header)
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
.component-window-header {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
height: 24px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.component-window-title {
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
font-size: var(--font-size-label3);
|
||||||
|
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
||||||
|
-unity-font-style: normal;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
-unity-text-align: middle-left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
닫기 버튼 (Close Button) - UTKButton 스타일 오버라이드
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
.component-window-close-button {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
min-width: 22px;
|
||||||
|
min-height: 22px;
|
||||||
|
border-width: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
align-self: center;
|
||||||
|
display: none; /* 기본 숨김, 필요시 flex로 변경 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
탭 버튼 (Tab Buttons)
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
.tab-button {
|
||||||
|
background-color: var(--color-base-03);
|
||||||
|
border-width: 0;
|
||||||
|
border-radius: 0px;
|
||||||
|
padding-left: 12px;
|
||||||
|
padding-right: 12px;
|
||||||
|
padding-top: 4px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
margin-right: 1px;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
font-size: var(--font-size-label3);
|
||||||
|
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-button:hover {
|
||||||
|
background-color: var(--color-base-05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-button-selected {
|
||||||
|
background-color: var(--color-base-07);
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-button-selected:hover {
|
||||||
|
background-color: var(--color-base-09);
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 5b2a67069d4f392478f4d1759c977c93
|
guid: 347141d660f7e3b4b8f54ced23166b82
|
||||||
ScriptedImporter:
|
ScriptedImporter:
|
||||||
internalIDToNameTable: []
|
internalIDToNameTable: []
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
@@ -1,13 +1,32 @@
|
|||||||
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xmlns:uvc="UVC.UIToolkit.List" noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
<Style src="project://database/Assets/Resources/UIToolkit/Window/UTKComponentListWindow.uss?fileID=7433441132597879392&guid=3df97248d26591046ab077258a2e2e44&type=3#UTKComponentListWindow" />
|
xmlns:ui="UnityEngine.UIElements"
|
||||||
|
xmlns:utk="UVC.UIToolkit"
|
||||||
|
noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd"
|
||||||
|
editor-extension-mode="False">
|
||||||
|
<!--
|
||||||
|
UTKComponentTabListWindow.uxml
|
||||||
|
|
||||||
|
탭 기능이 포함된 UTKComponentList 윈도우 컴포넌트입니다.
|
||||||
|
헤더(타이틀, 닫기 버튼), 탭 영역, 내부 UTKComponentList로 구성됩니다.
|
||||||
|
|
||||||
|
구조:
|
||||||
|
- container: 메인 컨테이너
|
||||||
|
- header: 윈도우 헤더
|
||||||
|
- title: 윈도우 제목
|
||||||
|
- close-btn: UTKButton 닫기 버튼
|
||||||
|
- tab-scroll-view: 탭 스크롤 영역
|
||||||
|
- tab-container: 탭 버튼 컨테이너
|
||||||
|
- UTKComponentList: 컴포넌트 리스트
|
||||||
|
-->
|
||||||
|
<!-- Style은 C# 코드에서 테마 적용 후 로드됩니다 -->
|
||||||
<ui:VisualElement name="container" class="container" style="flex-grow: 1; flex-shrink: 0;">
|
<ui:VisualElement name="container" class="container" style="flex-grow: 1; flex-shrink: 0;">
|
||||||
<ui:VisualElement name="header" style="flex-direction: row; margin-bottom: 5px; justify-content: space-between; margin-top: 0;">
|
<ui:VisualElement name="header" class="component-window-header">
|
||||||
<ui:Label text="EXPLORER" 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:Label name="title" text="EXPLORER" class="component-window-title" />
|
||||||
<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;" />
|
<utk:UTKButton name="close-btn" variant="Text" icon-only="true" class="component-window-close-button" />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<ui:ScrollView name="tab-scroll-view" mode="Horizontal" horizontal-scroller-visibility="Hidden" vertical-scroller-visibility="Hidden" style="flex-shrink: 0; margin-bottom: 8px; max-height: 28px;">
|
<ui:ScrollView name="tab-scroll-view" mode="Horizontal" horizontal-scroller-visibility="Hidden" vertical-scroller-visibility="Hidden" style="flex-shrink: 0; margin-bottom: 8px; max-height: 28px;">
|
||||||
<ui:VisualElement name="tab-container" style="flex-direction: row; flex-shrink: 0;" />
|
<ui:VisualElement name="tab-container" style="flex-direction: row; flex-shrink: 0;" />
|
||||||
</ui:ScrollView>
|
</ui:ScrollView>
|
||||||
<uvc:UTKComponentList style="flex-grow: 1; width: 100%;" />
|
<utk:UTKComponentList style="flex-grow: 1; width: 100%;" />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:UXML>
|
</ui:UXML>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:ui="UnityEngine.UIElements"
|
xmlns:ui="UnityEngine.UIElements"
|
||||||
xmlns:uvc="UVC.UIToolkit.List"
|
xmlns:utk="UVC.UIToolkit"
|
||||||
noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd"
|
noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd"
|
||||||
editor-extension-mode="False">
|
editor-extension-mode="False">
|
||||||
<!--
|
<!--
|
||||||
@@ -13,18 +13,18 @@
|
|||||||
- container: 메인 컨테이너
|
- container: 메인 컨테이너
|
||||||
- header: 윈도우 헤더
|
- header: 윈도우 헤더
|
||||||
- title: 윈도우 제목
|
- title: 윈도우 제목
|
||||||
- close-btn: 닫기 버튼
|
- close-btn: UTKButton 닫기 버튼
|
||||||
- UTKImageList: 이미지 리스트 컴포넌트
|
- UTKImageList: 이미지 리스트 컴포넌트
|
||||||
-->
|
-->
|
||||||
<Style src="project://database/Assets/Resources/UIToolkit/Window/UTKImageListWindow.uss" />
|
<!-- Style은 C# 코드에서 테마 적용 후 로드됩니다 -->
|
||||||
<ui:VisualElement name="container" class="image-list-window-container">
|
<ui:VisualElement name="container" class="image-list-window-container">
|
||||||
<!-- 헤더 영역 -->
|
<!-- 헤더 영역 -->
|
||||||
<ui:VisualElement name="header" class="window-header">
|
<ui:VisualElement name="header" class="window-header">
|
||||||
<ui:Label name="title" text="LIBRARY" class="window-title" />
|
<ui:Label name="title" text="LIBRARY" class="window-title" />
|
||||||
<ui:Button name="close-btn" class="window-close-button" />
|
<utk:UTKButton name="close-btn" variant="Text" icon-only="true" class="window-close-button" />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
|
|
||||||
<!-- 내부 UTKImageList 컴포넌트 -->
|
<!-- 내부 UTKImageList 컴포넌트 -->
|
||||||
<uvc:UTKImageList />
|
<utk:UTKImageList />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:UXML>
|
</ui:UXML>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
*
|
*
|
||||||
* UTKImageListWindow 컴포넌트의 스타일 정의입니다.
|
* UTKImageListWindow 컴포넌트의 스타일 정의입니다.
|
||||||
* UTKImageList를 래핑하는 윈도우 형태의 컨테이너입니다.
|
* UTKImageList를 래핑하는 윈도우 형태의 컨테이너입니다.
|
||||||
|
* 테마 지원: var(--color-*) 변수 사용
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* ============================================
|
/* ============================================
|
||||||
@@ -22,7 +23,7 @@ UTKImageListWindow {
|
|||||||
============================================ */
|
============================================ */
|
||||||
|
|
||||||
.image-list-window-container {
|
.image-list-window-container {
|
||||||
background-color: rgb(37, 37, 38);
|
background-color: var(--color-bg-panel);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
padding: 10px 20px 25px 20px;
|
padding: 10px 20px 25px 20px;
|
||||||
@@ -43,8 +44,8 @@ UTKImageListWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.window-title {
|
.window-title {
|
||||||
color: rgb(204, 204, 204);
|
color: var(--color-text-primary);
|
||||||
font-size: 11px;
|
font-size: var(--font-size-label3);
|
||||||
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
||||||
-unity-font-style: normal;
|
-unity-font-style: normal;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -53,26 +54,17 @@ UTKImageListWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================
|
/* ============================================
|
||||||
닫기 버튼 (Close Button)
|
닫기 버튼 (Close Button) - UTKButton 스타일 오버라이드
|
||||||
============================================ */
|
============================================ */
|
||||||
|
|
||||||
.window-close-button {
|
.window-close-button {
|
||||||
width: 22px;
|
width: 22px;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
|
min-width: 22px;
|
||||||
|
min-height: 22px;
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: rgba(0, 0, 0, 0);
|
|
||||||
background-image: resource('UIToolkit/Images/btn_close_22');
|
|
||||||
align-self: center;
|
align-self: center;
|
||||||
display: none; /* 기본 숨김, 필요시 flex로 변경 */
|
display: none; /* 기본 숨김, 필요시 flex로 변경 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.window-close-button:hover {
|
|
||||||
background-color: rgba(255, 255, 255, 0.1);
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.window-close-button:active {
|
|
||||||
background-color: rgba(255, 255, 255, 0.2);
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: b0076250b40d2ac45ab1bff4cd47920c
|
guid: e1cdefa2dbb1dd7419c0f16ba456d4ab
|
||||||
ScriptedImporter:
|
ScriptedImporter:
|
||||||
internalIDToNameTable: []
|
internalIDToNameTable: []
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
UTKTreeListWindow {
|
|
||||||
flex-grow: 1;
|
|
||||||
height: 100%;
|
|
||||||
align-self: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tree-menu-container {
|
|
||||||
background-color: rgb(37, 37, 38);
|
|
||||||
flex-grow: 1;
|
|
||||||
height: 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;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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('UIToolkit/Images/icon_eye_22x16');
|
|
||||||
}
|
|
||||||
|
|
||||||
.visibility-on {
|
|
||||||
background-image: resource('UIToolkit/Images/icon_eye_22x16');
|
|
||||||
}
|
|
||||||
|
|
||||||
.visibility-off {
|
|
||||||
background-image: resource('UIToolkit/Images/icon_eye_close_22x16');
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,33 @@
|
|||||||
<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">
|
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
<Style src="project://database/Assets/Resources/UIToolkit/Window/UTKTreeListWindow.uss?fileID=7433441132597879392&guid=b0076250b40d2ac45ab1bff4cd47920c&type=3#UTKTreeListWindow" />
|
xmlns:ui="UnityEngine.UIElements"
|
||||||
|
xmlns:uie="UnityEditor.UIElements"
|
||||||
|
xmlns:utk="UVC.UIToolkit"
|
||||||
|
noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd"
|
||||||
|
editor-extension-mode="False">
|
||||||
|
<!--
|
||||||
|
UTKTreeListWindow.uxml
|
||||||
|
|
||||||
|
TreeView 기반의 계층 리스트 윈도우 컴포넌트입니다.
|
||||||
|
헤더(타이틀, 닫기 버튼), 검색 필드, TreeView로 구성됩니다.
|
||||||
|
|
||||||
|
구조:
|
||||||
|
- container: 메인 컨테이너
|
||||||
|
- header: 윈도우 헤더
|
||||||
|
- title: 윈도우 제목
|
||||||
|
- close-btn: UTKButton 닫기 버튼
|
||||||
|
- search-field: 검색 입력 필드
|
||||||
|
- clear-btn: UTKButton 검색어 지우기 버튼
|
||||||
|
- main-tree-view: TreeView
|
||||||
|
-->
|
||||||
|
<!-- Style은 C# 코드에서 테마 적용 후 로드됩니다 -->
|
||||||
<ui:VisualElement name="container" class="tree-menu-container">
|
<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:VisualElement name="header" class="tree-window-header">
|
||||||
<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:Label name="title" text="HIERARCHY" class="tree-window-title" />
|
||||||
<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;" />
|
<utk:UTKButton name="close-btn" variant="Ghost" icon-only="true" class="tree-window-close-button" />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<ui:TextField name="search-field" placeholder-text="검색" class="search-field" style="height: 24px; margin-bottom: 12px;">
|
<ui:TextField name="search-field" placeholder-text="검색" class="search-field">
|
||||||
<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);" />
|
<utk:UTKButton name="clear-btn" variant="Text" icon-only="true" class="search-clear-button" />
|
||||||
</ui:TextField>
|
</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: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" horizontal-scrolling="true" selection-type="Multiple" style="flex-grow: 1;" />
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:UXML>
|
</ui:UXML>
|
||||||
|
|||||||
124
Assets/Resources/UIToolkit/Window/UTKTreeListWindowUss.uss
Normal file
124
Assets/Resources/UIToolkit/Window/UTKTreeListWindowUss.uss
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* UTKTreeListWindow.uss
|
||||||
|
*
|
||||||
|
* UTKTreeListWindow 컴포넌트의 스타일 정의입니다.
|
||||||
|
* 테마 지원: var(--color-*) 변수 사용
|
||||||
|
*/
|
||||||
|
|
||||||
|
UTKTreeListWindow {
|
||||||
|
flex-grow: 1;
|
||||||
|
height: 100%;
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-menu-container {
|
||||||
|
background-color: var(--color-bg-panel);
|
||||||
|
flex-grow: 1;
|
||||||
|
height: 100%;
|
||||||
|
align-self: flex-start;
|
||||||
|
padding: 5px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 25px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
헤더 (Header)
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
.tree-window-header {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
height: 24px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-window-title {
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
font-size: var(--font-size-label3);
|
||||||
|
-unity-font-definition: resource('Fonts/Pretendard/Pretendard-Medium');
|
||||||
|
-unity-font-style: normal;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
-unity-text-align: middle-left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
닫기 버튼 (Close Button) - UTKButton 스타일 오버라이드
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
.tree-window-close-button {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
min-width: 22px;
|
||||||
|
min-height: 22px;
|
||||||
|
border-width: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
align-self: center;
|
||||||
|
display: none; /* 기본 숨김, 필요시 flex로 변경 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
검색 필드 (Search Field)
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
.search-field {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
Clear 버튼 (Clear Button) - UTKButton 스타일 오버라이드
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
.search-clear-button {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
min-width: 16px;
|
||||||
|
min-height: 16px;
|
||||||
|
border-width: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
align-self: center;
|
||||||
|
position: absolute;
|
||||||
|
right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================
|
||||||
|
Visibility 토글 (Visibility Toggle)
|
||||||
|
============================================ */
|
||||||
|
|
||||||
|
.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('UIToolkit/Images/icon_eye_22x16');
|
||||||
|
}
|
||||||
|
|
||||||
|
.visibility-on {
|
||||||
|
background-image: resource('UIToolkit/Images/icon_eye_22x16');
|
||||||
|
}
|
||||||
|
|
||||||
|
.visibility-off {
|
||||||
|
background-image: resource('UIToolkit/Images/icon_eye_close_22x16');
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 94bace9f4fd4e854b80330dc68b0ebed
|
||||||
|
ScriptedImporter:
|
||||||
|
internalIDToNameTable: []
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
disableValidation: 0
|
||||||
@@ -118,8 +118,8 @@ public class UTKAccordionListWindowSample : MonoBehaviour
|
|||||||
Content = UTKAccordionContentSpec.FromText("Graphics", "open_graphics"),
|
Content = UTKAccordionContentSpec.FromText("Graphics", "open_graphics"),
|
||||||
Tail = new List<UTKAccordionContentSpec>
|
Tail = new List<UTKAccordionContentSpec>
|
||||||
{
|
{
|
||||||
UTKAccordionContentSpec.FromIconButton("Prefabs/UI/images/icon_refresh_22x22", "refresh_graphics", "새로고침"),
|
UTKAccordionContentSpec.FromIconButton(UTKMaterialIcons.Refresh, 12, "refresh_graphics", "새로고침"),
|
||||||
UTKAccordionContentSpec.FromIconButton("Prefabs/UI/images/icon_setting_22x22", "setting_graphics", "설정"),
|
UTKAccordionContentSpec.FromIconButton(UTKMaterialIcons.Settings, 12, "setting_graphics", "설정"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new UTKAccordionHorizontalItemData
|
new UTKAccordionHorizontalItemData
|
||||||
@@ -128,8 +128,8 @@ public class UTKAccordionListWindowSample : MonoBehaviour
|
|||||||
Content = UTKAccordionContentSpec.FromText("Audio", "open_audio"),
|
Content = UTKAccordionContentSpec.FromText("Audio", "open_audio"),
|
||||||
Tail = new List<UTKAccordionContentSpec>
|
Tail = new List<UTKAccordionContentSpec>
|
||||||
{
|
{
|
||||||
UTKAccordionContentSpec.FromIconButton("Prefabs/UI/images/icon_refresh_22x22", "refresh_audio", "새로고침"),
|
UTKAccordionContentSpec.FromIconButton(UTKMaterialIcons.Refresh, 12, "refresh_audio", "새로고침"),
|
||||||
UTKAccordionContentSpec.FromIconButton("Prefabs/UI/images/icon_setting_22x22", "setting_audio", "설정"),
|
UTKAccordionContentSpec.FromIconButton(UTKMaterialIcons.Settings, 12, "setting_audio", "설정"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new UTKAccordionHorizontalItemData
|
new UTKAccordionHorizontalItemData
|
||||||
@@ -138,7 +138,7 @@ public class UTKAccordionListWindowSample : MonoBehaviour
|
|||||||
Content = UTKAccordionContentSpec.FromText("Network", "open_network"),
|
Content = UTKAccordionContentSpec.FromText("Network", "open_network"),
|
||||||
Tail = new List<UTKAccordionContentSpec>
|
Tail = new List<UTKAccordionContentSpec>
|
||||||
{
|
{
|
||||||
UTKAccordionContentSpec.FromIconButton("Prefabs/UI/images/icon_refresh_22x22", "refresh_network", "새로고침"),
|
UTKAccordionContentSpec.FromIconButton(UTKMaterialIcons.Refresh, 12, "refresh_network", "새로고침"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -695,15 +695,15 @@ public class UTKAccordionListWindowSample : MonoBehaviour
|
|||||||
content: UTKAccordionContentSpec.FromText("Graphics", "open_graphics"),
|
content: UTKAccordionContentSpec.FromText("Graphics", "open_graphics"),
|
||||||
tail: new List<UTKAccordionContentSpec>
|
tail: new List<UTKAccordionContentSpec>
|
||||||
{
|
{
|
||||||
UTKAccordionContentSpec.FromIconButton("Prefabs/UI/images/icon_refresh_22x22", "refresh_graphics", "새로고침"),
|
UTKAccordionContentSpec.FromIconButton(UTKMaterialIcons.Refresh, 12, "refresh_graphics", "새로고침"),
|
||||||
UTKAccordionContentSpec.FromIconButton("Prefabs/UI/images/icon_setting_22x22", "setting_graphics", "설정"),
|
UTKAccordionContentSpec.FromIconButton(UTKMaterialIcons.Settings, 12, "setting_graphics", "설정"),
|
||||||
})
|
})
|
||||||
.AddHorizontalItem(
|
.AddHorizontalItem(
|
||||||
head: UTKAccordionContentSpec.FromImage("Prefabs/UI/images/icon_side_tab_fleet_128"),
|
head: UTKAccordionContentSpec.FromImage("Prefabs/UI/images/icon_side_tab_fleet_128"),
|
||||||
content: UTKAccordionContentSpec.FromText("Audio", "open_audio"),
|
content: UTKAccordionContentSpec.FromText("Audio", "open_audio"),
|
||||||
tail: new List<UTKAccordionContentSpec>
|
tail: new List<UTKAccordionContentSpec>
|
||||||
{
|
{
|
||||||
UTKAccordionContentSpec.FromIconButton("Prefabs/UI/images/icon_refresh_22x22", "refresh_audio", "새로고침"),
|
UTKAccordionContentSpec.FromIconButton(UTKMaterialIcons.Refresh, 12, "refresh_audio", "새로고침"),
|
||||||
});
|
});
|
||||||
roots.Add(settingsSection);
|
roots.Add(settingsSection);
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,12 @@ public class UTKStyleGuideSample : MonoBehaviour
|
|||||||
// Picker
|
// Picker
|
||||||
["UTKColorPicker"] = "UIToolkit/Sample/Picker/UTKColorPickerSample",
|
["UTKColorPicker"] = "UIToolkit/Sample/Picker/UTKColorPickerSample",
|
||||||
["UTKDatePicker"] = "UIToolkit/Sample/Picker/UTKDatePickerSample",
|
["UTKDatePicker"] = "UIToolkit/Sample/Picker/UTKDatePickerSample",
|
||||||
|
// Window
|
||||||
|
["UTKAccordionListWindow"] = "UIToolkit/Sample/Window/UTKAccordionListWindowSample",
|
||||||
|
["UTKComponentListWindow"] = "UIToolkit/Sample/Window/UTKComponentListWindowSample",
|
||||||
|
["UTKComponentTabListWindow"] = "UIToolkit/Sample/Window/UTKComponentTabListWindowSample",
|
||||||
|
["UTKImageListWindow"] = "UIToolkit/Sample/Window/UTKImageListWindowSample",
|
||||||
|
["UTKTreeListWindow"] = "UIToolkit/Sample/Window/UTKTreeListWindowSample",
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly Dictionary<string, string[]> ControlCategories = new()
|
private static readonly Dictionary<string, string[]> ControlCategories = new()
|
||||||
@@ -112,6 +118,7 @@ public class UTKStyleGuideSample : MonoBehaviour
|
|||||||
["Tab"] = new[] { "UTKTabView" },
|
["Tab"] = new[] { "UTKTabView" },
|
||||||
["Modal"] = new[] { "UTKAlert", "UTKToast", "UTKTooltip" },
|
["Modal"] = new[] { "UTKAlert", "UTKToast", "UTKTooltip" },
|
||||||
["Picker"] = new[] { "UTKColorPicker", "UTKDatePicker" },
|
["Picker"] = new[] { "UTKColorPicker", "UTKDatePicker" },
|
||||||
|
["Window"] = new[] { "UTKAccordionListWindow", "UTKComponentListWindow", "UTKComponentTabListWindow", "UTKImageListWindow", "UTKTreeListWindow" },
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -449,6 +456,21 @@ public class UTKStyleGuideSample : MonoBehaviour
|
|||||||
case "UTKImage":
|
case "UTKImage":
|
||||||
InitializeUTKImageSample(root);
|
InitializeUTKImageSample(root);
|
||||||
break;
|
break;
|
||||||
|
case "UTKAccordionListWindow":
|
||||||
|
InitializeAccordionListWindowSample(root);
|
||||||
|
break;
|
||||||
|
case "UTKComponentListWindow":
|
||||||
|
InitializeComponentListWindowSample(root);
|
||||||
|
break;
|
||||||
|
case "UTKComponentTabListWindow":
|
||||||
|
InitializeComponentTabListWindowSample(root);
|
||||||
|
break;
|
||||||
|
case "UTKImageListWindow":
|
||||||
|
InitializeImageListWindowSample(root);
|
||||||
|
break;
|
||||||
|
case "UTKTreeListWindow":
|
||||||
|
InitializeTreeListWindowSample(root);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1642,4 +1664,303 @@ public class UTKStyleGuideSample : MonoBehaviour
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Window Initializers
|
||||||
|
|
||||||
|
private void InitializeAccordionListWindowSample(VisualElement root)
|
||||||
|
{
|
||||||
|
var container = root.Q<VisualElement>("accordion-list-window-container");
|
||||||
|
if (container == null) return;
|
||||||
|
|
||||||
|
var accordionWindow = new UTKAccordionListWindow();
|
||||||
|
accordionWindow.Title = "프리팹 라이브러리";
|
||||||
|
accordionWindow.ShowCloseButton = true;
|
||||||
|
|
||||||
|
var data = new UTKAccordionData();
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 수평 레이아웃 섹션 1: Settings
|
||||||
|
// ========================================
|
||||||
|
var settingsSection = new UTKAccordionSectionData
|
||||||
|
{
|
||||||
|
Title = "Settings",
|
||||||
|
IsExpanded = true,
|
||||||
|
LayoutType = UTKAccordionLayoutType.Horizontal,
|
||||||
|
HorizontalItems = new List<UTKAccordionHorizontalItemData>
|
||||||
|
{
|
||||||
|
new UTKAccordionHorizontalItemData
|
||||||
|
{
|
||||||
|
Head = UTKAccordionContentSpec.FromImage(UTKMaterialIcons.LibraryAdd),
|
||||||
|
Content = UTKAccordionContentSpec.FromText("Graphics", "open_graphics"),
|
||||||
|
Tail = new List<UTKAccordionContentSpec>
|
||||||
|
{
|
||||||
|
UTKAccordionContentSpec.FromIconButton(UTKMaterialIcons.Refresh, 12, "refresh_graphics", "새로고침"),
|
||||||
|
UTKAccordionContentSpec.FromIconButton(UTKMaterialIcons.Settings, 12, "setting_graphics", "설정"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new UTKAccordionHorizontalItemData
|
||||||
|
{
|
||||||
|
Head = UTKAccordionContentSpec.FromImage(UTKMaterialIcons.AudioFile),
|
||||||
|
Content = UTKAccordionContentSpec.FromText("Audio", "open_audio"),
|
||||||
|
Tail = new List<UTKAccordionContentSpec>
|
||||||
|
{
|
||||||
|
UTKAccordionContentSpec.FromIconButton(UTKMaterialIcons.Refresh, 12, "refresh_audio", "새로고침"),
|
||||||
|
UTKAccordionContentSpec.FromIconButton(UTKMaterialIcons.Settings, 12, "setting_audio", "설정"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new UTKAccordionHorizontalItemData
|
||||||
|
{
|
||||||
|
Head = UTKAccordionContentSpec.FromImage(UTKMaterialIcons.Explore),
|
||||||
|
Content = UTKAccordionContentSpec.FromText("Network", "open_network"),
|
||||||
|
Tail = new List<UTKAccordionContentSpec>
|
||||||
|
{
|
||||||
|
UTKAccordionContentSpec.FromIconButton(UTKMaterialIcons.Refresh, 12, "refresh_network", "새로고침"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
data.Sections.Add(settingsSection);
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 수평 레이아웃 섹션 2: Components
|
||||||
|
// ========================================
|
||||||
|
var componentsSection = new UTKAccordionSectionData
|
||||||
|
{
|
||||||
|
Title = "Components",
|
||||||
|
IsExpanded = false,
|
||||||
|
LayoutType = UTKAccordionLayoutType.Horizontal,
|
||||||
|
HorizontalItems = new List<UTKAccordionHorizontalItemData>
|
||||||
|
{
|
||||||
|
new UTKAccordionHorizontalItemData
|
||||||
|
{
|
||||||
|
Content = UTKAccordionContentSpec.FromText("Transform", "open_transform"),
|
||||||
|
},
|
||||||
|
new UTKAccordionHorizontalItemData
|
||||||
|
{
|
||||||
|
Content = UTKAccordionContentSpec.FromText("Rigidbody", "open_rigidbody"),
|
||||||
|
},
|
||||||
|
new UTKAccordionHorizontalItemData
|
||||||
|
{
|
||||||
|
Content = UTKAccordionContentSpec.FromText("Collider", "open_collider"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
data.Sections.Add(componentsSection);
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 그리드 레이아웃 섹션 1: Vehicles
|
||||||
|
// ========================================
|
||||||
|
var vehiclesSection = new UTKAccordionSectionData
|
||||||
|
{
|
||||||
|
Title = "Vehicles",
|
||||||
|
IsExpanded = true,
|
||||||
|
LayoutType = UTKAccordionLayoutType.Grid,
|
||||||
|
GridItems = new List<UTKAccordionGridItemData>
|
||||||
|
{
|
||||||
|
new UTKAccordionGridItemData
|
||||||
|
{
|
||||||
|
Caption = "Forklift",
|
||||||
|
ImagePath = "Simulator/Images/lib_forklift_400x300",
|
||||||
|
PrefabPath = "Simulator/FreeForkLift/Prefabs/Forklift",
|
||||||
|
Tag = "vehicle"
|
||||||
|
},
|
||||||
|
new UTKAccordionGridItemData
|
||||||
|
{
|
||||||
|
Caption = "Truck",
|
||||||
|
ImagePath = "Simulator/Images/lib_forklift_400x300",
|
||||||
|
PrefabPath = "Simulator/FreeForkLift/Prefabs/Forklift",
|
||||||
|
Tag = "vehicle"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
data.Sections.Add(vehiclesSection);
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 그리드 레이아웃 섹션 2: Objects
|
||||||
|
// ========================================
|
||||||
|
var objectsSection = new UTKAccordionSectionData
|
||||||
|
{
|
||||||
|
Title = "Objects",
|
||||||
|
IsExpanded = true,
|
||||||
|
LayoutType = UTKAccordionLayoutType.Grid,
|
||||||
|
GridItems = new List<UTKAccordionGridItemData>
|
||||||
|
{
|
||||||
|
new UTKAccordionGridItemData
|
||||||
|
{
|
||||||
|
Caption = "Pallet",
|
||||||
|
ImagePath = "Simulator/Images/lib_pallet_400x300",
|
||||||
|
PrefabPath = "Simulator/FreeForkLift/Prefabs/PalletEmpty",
|
||||||
|
Tag = "object"
|
||||||
|
},
|
||||||
|
new UTKAccordionGridItemData
|
||||||
|
{
|
||||||
|
Caption = "Pallet (Full)",
|
||||||
|
ImagePath = "Simulator/Images/lib_pallet_400x300",
|
||||||
|
PrefabPath = "Simulator/FreeForkLift/Prefabs/PalletEmpty",
|
||||||
|
Tag = "object"
|
||||||
|
},
|
||||||
|
new UTKAccordionGridItemData
|
||||||
|
{
|
||||||
|
Caption = "Box",
|
||||||
|
ImagePath = "Simulator/Images/lib_pallet_400x300",
|
||||||
|
PrefabPath = "Simulator/FreeForkLift/Prefabs/PalletEmpty",
|
||||||
|
Tag = "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
data.Sections.Add(objectsSection);
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 그리드 레이아웃 섹션 3: Characters
|
||||||
|
// ========================================
|
||||||
|
var charactersSection = new UTKAccordionSectionData
|
||||||
|
{
|
||||||
|
Title = "Characters",
|
||||||
|
IsExpanded = true,
|
||||||
|
LayoutType = UTKAccordionLayoutType.Grid,
|
||||||
|
GridItems = new List<UTKAccordionGridItemData>
|
||||||
|
{
|
||||||
|
new UTKAccordionGridItemData
|
||||||
|
{
|
||||||
|
Caption = "Worker",
|
||||||
|
ImagePath = "Simulator/Images/lib_worker_400x300",
|
||||||
|
PrefabPath = "Simulator/CharCrafter – Free Preset Characters Pack (Vol. 1)/Prefabs/Male Young Guy",
|
||||||
|
Tag = "character"
|
||||||
|
},
|
||||||
|
new UTKAccordionGridItemData
|
||||||
|
{
|
||||||
|
Caption = "Manager",
|
||||||
|
ImagePath = "Simulator/Images/lib_worker_400x300",
|
||||||
|
PrefabPath = "Simulator/CharCrafter – Free Preset Characters Pack (Vol. 1)/Prefabs/Male Young Guy",
|
||||||
|
Tag = "character"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
data.Sections.Add(charactersSection);
|
||||||
|
accordionWindow.SetData(data);
|
||||||
|
accordionWindow.Show();
|
||||||
|
|
||||||
|
container.Add(accordionWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeComponentListWindowSample(VisualElement root)
|
||||||
|
{
|
||||||
|
var container = root.Q<VisualElement>("component-list-window-container");
|
||||||
|
if (container == null) return;
|
||||||
|
|
||||||
|
var componentWindow = new UTKComponentListWindow();
|
||||||
|
componentWindow.Title = "모델 리스트";
|
||||||
|
componentWindow.ShowCloseButton = true;
|
||||||
|
|
||||||
|
// 테마 변경 이벤트 구독
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged += _ => UTKThemeManager.Instance.ApplyThemeToElement(componentWindow);
|
||||||
|
|
||||||
|
// 샘플 데이터
|
||||||
|
var category1 = new UTKComponentListCategoryData { name = "캐릭터", isExpanded = true };
|
||||||
|
category1.Add(new UTKComponentListItemData { name = "플레이어", ExternalKey = "player_001", IsVisible = true });
|
||||||
|
category1.Add(new UTKComponentListItemData { name = "NPC_01", ExternalKey = "npc_001", IsVisible = true });
|
||||||
|
category1.Add(new UTKComponentListItemData { name = "NPC_02", ExternalKey = "npc_002", IsVisible = false });
|
||||||
|
|
||||||
|
var category2 = new UTKComponentListCategoryData { name = "환경", isExpanded = false };
|
||||||
|
category2.Add(new UTKComponentListItemData { name = "나무", ExternalKey = "tree_001", IsVisible = true });
|
||||||
|
category2.Add(new UTKComponentListItemData { name = "바위", ExternalKey = "rock_001", IsVisible = true });
|
||||||
|
|
||||||
|
var data = new List<UTKComponentListItemDataBase> { category1, category2 };
|
||||||
|
componentWindow.SetData(data);
|
||||||
|
componentWindow.Show();
|
||||||
|
|
||||||
|
container.Add(componentWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeComponentTabListWindowSample(VisualElement root)
|
||||||
|
{
|
||||||
|
var container = root.Q<VisualElement>("component-tab-list-window-container");
|
||||||
|
if (container == null) return;
|
||||||
|
|
||||||
|
var tabWindow = new UTKComponentTabListWindow();
|
||||||
|
tabWindow.Title = "모델 라이브러리";
|
||||||
|
tabWindow.ShowCloseButton = true;
|
||||||
|
|
||||||
|
// 테마 변경 이벤트 구독
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged += _ => UTKThemeManager.Instance.ApplyThemeToElement(tabWindow);
|
||||||
|
|
||||||
|
// 샘플 데이터 (카테고리가 탭으로 자동 생성됨)
|
||||||
|
var category1 = new UTKComponentListCategoryData { name = "캐릭터", isExpanded = true };
|
||||||
|
category1.Add(new UTKComponentListItemData { name = "플레이어", IsVisible = true });
|
||||||
|
category1.Add(new UTKComponentListItemData { name = "몬스터", IsVisible = true });
|
||||||
|
|
||||||
|
var category2 = new UTKComponentListCategoryData { name = "환경", isExpanded = true };
|
||||||
|
category2.Add(new UTKComponentListItemData { name = "나무", IsVisible = true });
|
||||||
|
category2.Add(new UTKComponentListItemData { name = "풀", IsVisible = true });
|
||||||
|
|
||||||
|
var category3 = new UTKComponentListCategoryData { name = "아이템", isExpanded = true };
|
||||||
|
category3.Add(new UTKComponentListItemData { name = "검", IsVisible = true });
|
||||||
|
category3.Add(new UTKComponentListItemData { name = "방패", IsVisible = true });
|
||||||
|
|
||||||
|
var data = new List<UTKComponentListItemDataBase> { category1, category2, category3 };
|
||||||
|
tabWindow.SetData(data);
|
||||||
|
tabWindow.Show();
|
||||||
|
|
||||||
|
container.Add(tabWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeImageListWindowSample(VisualElement root)
|
||||||
|
{
|
||||||
|
var container = root.Q<VisualElement>("image-list-window-container");
|
||||||
|
if (container == null) return;
|
||||||
|
|
||||||
|
var imageWindow = new UTKImageListWindow();
|
||||||
|
imageWindow.Title = "텍스처 라이브러리";
|
||||||
|
imageWindow.ShowCloseButton = true;
|
||||||
|
|
||||||
|
// 테마 변경 이벤트 구독
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged += _ => UTKThemeManager.Instance.ApplyThemeToElement(imageWindow);
|
||||||
|
|
||||||
|
// 샘플 데이터
|
||||||
|
var data = new List<UTKImageListItemData>
|
||||||
|
{
|
||||||
|
new UTKImageListItemData { itemName = "Texture_01", externalId = "tex_001" },
|
||||||
|
new UTKImageListItemData { itemName = "Texture_02", externalId = "tex_002" },
|
||||||
|
new UTKImageListItemData { itemName = "Texture_03", externalId = "tex_003" },
|
||||||
|
new UTKImageListItemData { itemName = "Texture_04", externalId = "tex_004" }
|
||||||
|
};
|
||||||
|
imageWindow.SetData(data);
|
||||||
|
imageWindow.Show();
|
||||||
|
|
||||||
|
container.Add(imageWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeTreeListWindowSample(VisualElement root)
|
||||||
|
{
|
||||||
|
var container = root.Q<VisualElement>("tree-list-window-container");
|
||||||
|
if (container == null) return;
|
||||||
|
|
||||||
|
var treeWindow = new UTKTreeListWindow();
|
||||||
|
treeWindow.Title = "씬 계층 구조";
|
||||||
|
treeWindow.ShowCloseButton = true;
|
||||||
|
|
||||||
|
// 테마 변경 이벤트 구독
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged += _ => UTKThemeManager.Instance.ApplyThemeToElement(treeWindow);
|
||||||
|
|
||||||
|
// 샘플 데이터
|
||||||
|
var environment = new UTKTreeListItemData { name = "Environment", isExpanded = true };
|
||||||
|
environment.Add(new UTKTreeListItemData { name = "Terrain", ExternalKey = "terrain_001", IsVisible = true });
|
||||||
|
environment.Add(new UTKTreeListItemData { name = "Trees", ExternalKey = "trees_001", IsVisible = true });
|
||||||
|
|
||||||
|
var characters = new UTKTreeListItemData { name = "Characters", isExpanded = false };
|
||||||
|
characters.Add(new UTKTreeListItemData { name = "Player", ExternalKey = "player_001", IsVisible = true });
|
||||||
|
characters.Add(new UTKTreeListItemData { name = "Enemies", ExternalKey = "enemies_001", IsVisible = true });
|
||||||
|
|
||||||
|
var rootNode = new UTKTreeListItemData { name = "Root", isExpanded = true };
|
||||||
|
rootNode.Add(environment);
|
||||||
|
rootNode.Add(characters);
|
||||||
|
|
||||||
|
var data = new List<UTKTreeListItemData> { rootNode };
|
||||||
|
treeWindow.SetData(data);
|
||||||
|
treeWindow.Show();
|
||||||
|
|
||||||
|
container.Add(treeWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -306,9 +306,10 @@ namespace UVC.UIToolkit
|
|||||||
if (!string.IsNullOrEmpty(icon))
|
if (!string.IsNullOrEmpty(icon))
|
||||||
{
|
{
|
||||||
// 1순위: UTKMaterialIcons에 해당하는지 확인
|
// 1순위: UTKMaterialIcons에 해당하는지 확인
|
||||||
if (UTKMaterialIcons.GetIcon(icon) != null)
|
string iconChar = UTKMaterialIcons.GetIcon(icon);
|
||||||
|
if (iconChar != string.Empty)
|
||||||
{
|
{
|
||||||
SetMaterialIcon(icon, iconSize);
|
SetMaterialIcon(iconChar, iconSize);
|
||||||
}
|
}
|
||||||
// 2순위: UTKImageIcons에 해당하는지 확인
|
// 2순위: UTKImageIcons에 해당하는지 확인
|
||||||
else if (!string.IsNullOrEmpty(UTKImageIcons.GetPath(icon)))
|
else if (!string.IsNullOrEmpty(UTKImageIcons.GetPath(icon)))
|
||||||
@@ -536,8 +537,8 @@ namespace UVC.UIToolkit
|
|||||||
/// <param name="fontSize">아이콘 폰트 크기 (null이면 버튼 크기에 맞춤)</param>
|
/// <param name="fontSize">아이콘 폰트 크기 (null이면 버튼 크기에 맞춤)</param>
|
||||||
public void SetMaterialIconByName(string iconName, int? fontSize = null)
|
public void SetMaterialIconByName(string iconName, int? fontSize = null)
|
||||||
{
|
{
|
||||||
var iconChar = UTKMaterialIcons.GetIcon(iconName);
|
string iconChar = UTKMaterialIcons.GetIcon(iconName);
|
||||||
if (!string.IsNullOrEmpty(iconChar))
|
if (iconChar != string.Empty)
|
||||||
{
|
{
|
||||||
SetMaterialIcon(iconChar, fontSize);
|
SetMaterialIcon(iconChar, fontSize);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -41,6 +42,9 @@ namespace UVC.UIToolkit
|
|||||||
/// // 아이콘 존재 여부 확인
|
/// // 아이콘 존재 여부 확인
|
||||||
/// if (UTKMaterialIcons.HasIcon("search")) { }
|
/// if (UTKMaterialIcons.HasIcon("search")) { }
|
||||||
///
|
///
|
||||||
|
/// // 존재하는 유니코드 문자인지 확인
|
||||||
|
/// if (UTKMaterialIcons.IsIconChar("□")) { }
|
||||||
|
///
|
||||||
/// // 전체 아이콘 이름 순회
|
/// // 전체 아이콘 이름 순회
|
||||||
/// foreach (var name in UTKMaterialIcons.GetAllIconNames()) { }
|
/// foreach (var name in UTKMaterialIcons.GetAllIconNames()) { }
|
||||||
///
|
///
|
||||||
@@ -152,10 +156,10 @@ namespace UVC.UIToolkit
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="element">스타일을 적용할 요소</param>
|
/// <param name="element">스타일을 적용할 요소</param>
|
||||||
/// <param name="fontSize">폰트 크기 (기본값: 24)</param>
|
/// <param name="fontSize">폰트 크기 (기본값: 24)</param>
|
||||||
public static void ApplyIconStyle(VisualElement element, int fontSize = 24)
|
public static void ApplyIconStyle(VisualElement element, int? fontSize = 24)
|
||||||
{
|
{
|
||||||
element.style.unityFontDefinition = GetFontDefinition();
|
element.style.unityFontDefinition = GetFontDefinition();
|
||||||
element.style.fontSize = fontSize;
|
if(fontSize != null) element.style.fontSize = fontSize.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -12501,6 +12505,7 @@ namespace UVC.UIToolkit
|
|||||||
/// <returns>아이콘 문자, 없으면 빈 문자열</returns>
|
/// <returns>아이콘 문자, 없으면 빈 문자열</returns>
|
||||||
public static string GetIcon(string iconName)
|
public static string GetIcon(string iconName)
|
||||||
{
|
{
|
||||||
|
if(IsIconChar(iconName)) return iconName;
|
||||||
return _iconsByName.TryGetValue(iconName, out var icon) ? icon : string.Empty;
|
return _iconsByName.TryGetValue(iconName, out var icon) ? icon : string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12509,6 +12514,11 @@ namespace UVC.UIToolkit
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool HasIcon(string iconName) => _iconsByName.ContainsKey(iconName);
|
public static bool HasIcon(string iconName) => _iconsByName.ContainsKey(iconName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 유니코드 문자로 아이콘이 존재하는지 확인합니다.
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsIconChar(string iconChar) => _iconsByName.Values.Contains(iconChar);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 모든 아이콘 이름 목록을 반환합니다.
|
/// 모든 아이콘 이름 목록을 반환합니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -694,8 +694,8 @@ namespace UVC.UIToolkit
|
|||||||
/// <param name="fontSize">아이콘 폰트 크기 (null이면 텍스트 크기에 맞춤)</param>
|
/// <param name="fontSize">아이콘 폰트 크기 (null이면 텍스트 크기에 맞춤)</param>
|
||||||
public void SetMaterialIconByName(string iconName, int? fontSize = null)
|
public void SetMaterialIconByName(string iconName, int? fontSize = null)
|
||||||
{
|
{
|
||||||
var iconChar = UTKMaterialIcons.GetIcon(iconName);
|
string iconChar = UTKMaterialIcons.GetIcon(iconName);
|
||||||
if (!string.IsNullOrEmpty(iconChar))
|
if (iconChar != string.Empty)
|
||||||
{
|
{
|
||||||
SetMaterialIcon(iconChar, fontSize);
|
SetMaterialIcon(iconChar, fontSize);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,88 @@ namespace UVC.UIToolkit
|
|||||||
/// <item>비동기 이미지 로딩 및 캐싱</item>
|
/// <item>비동기 이미지 로딩 및 캐싱</item>
|
||||||
/// </list>
|
/// </list>
|
||||||
///
|
///
|
||||||
|
/// <para><b>UXML 사용 예시:</b></para>
|
||||||
|
/// <code><![CDATA[
|
||||||
|
/// <!-- UXML 파일에서 UTKAccordionList 사용 -->
|
||||||
|
/// <ui:UXML xmlns:utk="UVC.UIToolkit">
|
||||||
|
/// <utk:UTKAccordionList name="accordion-list" />
|
||||||
|
/// </ui:UXML>
|
||||||
|
/// ]]></code>
|
||||||
|
///
|
||||||
|
/// <para><b>C# 사용 예시:</b></para>
|
||||||
|
/// <code><![CDATA[
|
||||||
|
/// // 1. 아코디언 리스트 참조 획득
|
||||||
|
/// var accordionList = root.Q<UTKAccordionList>("accordion-list");
|
||||||
|
///
|
||||||
|
/// // 2. 데이터 구성 - 섹션(카테고리)과 그리드 아이템
|
||||||
|
/// var data = new List<UTKAccordionItemData>
|
||||||
|
/// {
|
||||||
|
/// // 섹션 생성 (카테고리)
|
||||||
|
/// new UTKAccordionItemData
|
||||||
|
/// {
|
||||||
|
/// nodeType = UTKAccordionNodeType.Section,
|
||||||
|
/// name = "가구",
|
||||||
|
/// isExpanded = true,
|
||||||
|
/// children = new List<UTKAccordionItemData>
|
||||||
|
/// {
|
||||||
|
/// // 그리드 아이템 (이미지 + 캡션)
|
||||||
|
/// new UTKAccordionItemData
|
||||||
|
/// {
|
||||||
|
/// nodeType = UTKAccordionNodeType.GridItem,
|
||||||
|
/// name = "의자",
|
||||||
|
/// caption = "사무용 의자",
|
||||||
|
/// imagePath = "Prefabs/Thumbnails/chair",
|
||||||
|
/// prefabPath = "Prefabs/Furniture/Chair"
|
||||||
|
/// },
|
||||||
|
/// new UTKAccordionItemData
|
||||||
|
/// {
|
||||||
|
/// nodeType = UTKAccordionNodeType.GridItem,
|
||||||
|
/// name = "책상",
|
||||||
|
/// caption = "사무용 책상",
|
||||||
|
/// imagePath = "Prefabs/Thumbnails/desk",
|
||||||
|
/// prefabPath = "Prefabs/Furniture/Desk"
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 3. 데이터 설정
|
||||||
|
/// accordionList.SetData(data);
|
||||||
|
///
|
||||||
|
/// // 4. 이벤트 구독 - 아이템 클릭
|
||||||
|
/// accordionList.OnItemClick += (item) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"클릭된 아이템: {item.name}");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 5. 드래그 앤 드롭 이벤트
|
||||||
|
/// accordionList.OnItemDrop += (item) =>
|
||||||
|
/// {
|
||||||
|
/// // 드롭된 위치에 프리팹 인스턴스화
|
||||||
|
/// if (!string.IsNullOrEmpty(item.prefabPath))
|
||||||
|
/// {
|
||||||
|
/// var prefab = Resources.Load<GameObject>(item.prefabPath);
|
||||||
|
/// Instantiate(prefab, dropPosition, Quaternion.identity);
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 6. 리스트 영역 밖으로 드래그 시 3D 미리보기 표시
|
||||||
|
/// accordionList.OnDragExitList += (item, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// Show3DPreview(item.prefabPath, screenPos);
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 7. 검색 실행
|
||||||
|
/// accordionList.Search("의자");
|
||||||
|
///
|
||||||
|
/// // 8. 모든 섹션 펼치기/접기
|
||||||
|
/// accordionList.ExpandAll();
|
||||||
|
/// accordionList.CollapseAll();
|
||||||
|
///
|
||||||
|
/// // 9. 리소스 해제 (OnDestroy에서 호출)
|
||||||
|
/// accordionList.Dispose();
|
||||||
|
/// ]]></code>
|
||||||
|
///
|
||||||
/// <para><b>관련 리소스:</b></para>
|
/// <para><b>관련 리소스:</b></para>
|
||||||
/// <list type="bullet">
|
/// <list type="bullet">
|
||||||
/// <item>Resources/UIToolkit/List/UTKAccordionList.uxml - 메인 레이아웃</item>
|
/// <item>Resources/UIToolkit/List/UTKAccordionList.uxml - 메인 레이아웃</item>
|
||||||
@@ -47,6 +129,7 @@ namespace UVC.UIToolkit
|
|||||||
#region 상수 (Constants)
|
#region 상수 (Constants)
|
||||||
|
|
||||||
private const string UXML_PATH = "UIToolkit/List/UTKAccordionList";
|
private const string UXML_PATH = "UIToolkit/List/UTKAccordionList";
|
||||||
|
private const string USS_PATH = "UIToolkit/List/UTKAccordionListUss";
|
||||||
private const string SECTION_UXML_PATH = "UIToolkit/List/UTKAccordionSection";
|
private const string SECTION_UXML_PATH = "UIToolkit/List/UTKAccordionSection";
|
||||||
private const string HORIZONTAL_ITEM_UXML_PATH = "UIToolkit/List/UTKAccordionHorizontalItem";
|
private const string HORIZONTAL_ITEM_UXML_PATH = "UIToolkit/List/UTKAccordionHorizontalItem";
|
||||||
private const string GRID_ITEM_UXML_PATH = "UIToolkit/List/UTKAccordionGridItem";
|
private const string GRID_ITEM_UXML_PATH = "UIToolkit/List/UTKAccordionGridItem";
|
||||||
@@ -67,7 +150,7 @@ namespace UVC.UIToolkit
|
|||||||
#region UI 컴포넌트 참조 (UI Component References)
|
#region UI 컴포넌트 참조 (UI Component References)
|
||||||
|
|
||||||
private TextField? _searchField;
|
private TextField? _searchField;
|
||||||
private Button? _clearButton;
|
private UTKButton? _clearButton;
|
||||||
private Label? _searchResultLabel;
|
private Label? _searchResultLabel;
|
||||||
private TreeView? _treeView;
|
private TreeView? _treeView;
|
||||||
|
|
||||||
@@ -179,9 +262,6 @@ namespace UVC.UIToolkit
|
|||||||
|
|
||||||
public UTKAccordionList()
|
public UTKAccordionList()
|
||||||
{
|
{
|
||||||
// 테마 적용
|
|
||||||
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
|
||||||
|
|
||||||
// 메인 UXML 로드
|
// 메인 UXML 로드
|
||||||
var visualTree = Resources.Load<VisualTreeAsset>(UXML_PATH);
|
var visualTree = Resources.Load<VisualTreeAsset>(UXML_PATH);
|
||||||
if (visualTree == null)
|
if (visualTree == null)
|
||||||
@@ -194,10 +274,27 @@ namespace UVC.UIToolkit
|
|||||||
// 템플릿 로드
|
// 템플릿 로드
|
||||||
LoadTemplates();
|
LoadTemplates();
|
||||||
|
|
||||||
|
// 테마 적용 및 변경 구독
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
SubscribeToThemeChanges();
|
||||||
|
|
||||||
|
// USS 로드 (테마 변수 스타일시트 이후에 로드되어야 변수가 해석됨)
|
||||||
|
var uss = Resources.Load<StyleSheet>(USS_PATH);
|
||||||
|
if (uss != null)
|
||||||
|
{
|
||||||
|
styleSheets.Add(uss);
|
||||||
|
}
|
||||||
|
|
||||||
// UI 요소 참조 획득
|
// UI 요소 참조 획득
|
||||||
_searchField = this.Q<TextField>("search-field");
|
_searchField = this.Q<TextField>("search-field");
|
||||||
_clearButton = this.Q<Button>("clear-btn");
|
_clearButton = this.Q<UTKButton>("clear-btn");
|
||||||
_searchResultLabel = this.Q<Label>("search-result-label");
|
_searchResultLabel = this.Q<Label>("search-result-label");
|
||||||
|
|
||||||
|
// Clear 버튼 아이콘 설정
|
||||||
|
if (_clearButton != null)
|
||||||
|
{
|
||||||
|
_clearButton.SetMaterialIcon(UTKMaterialIcons.Close, 12);
|
||||||
|
}
|
||||||
_treeView = this.Q<TreeView>("accordion-tree-view");
|
_treeView = this.Q<TreeView>("accordion-tree-view");
|
||||||
|
|
||||||
// 초기화
|
// 초기화
|
||||||
@@ -234,7 +331,7 @@ namespace UVC.UIToolkit
|
|||||||
// 검색어 지우기 버튼
|
// 검색어 지우기 버튼
|
||||||
if (_clearButton != null)
|
if (_clearButton != null)
|
||||||
{
|
{
|
||||||
_clearButton.clicked += OnClearButtonClicked;
|
_clearButton.OnClicked += OnClearButtonClicked;
|
||||||
// 초기에는 숨김
|
// 초기에는 숨김
|
||||||
_clearButton.style.display = DisplayStyle.None;
|
_clearButton.style.display = DisplayStyle.None;
|
||||||
}
|
}
|
||||||
@@ -734,7 +831,7 @@ namespace UVC.UIToolkit
|
|||||||
var tailBtn = CreateTailButton(tailSpec);
|
var tailBtn = CreateTailButton(tailSpec);
|
||||||
if (tailBtn != null)
|
if (tailBtn != null)
|
||||||
{
|
{
|
||||||
tailBtn.clicked += () =>
|
tailBtn.OnClicked += () =>
|
||||||
{
|
{
|
||||||
// 레거시 이벤트
|
// 레거시 이벤트
|
||||||
var legacyItem = ConvertToLegacyHorizontalItem(item);
|
var legacyItem = ConvertToLegacyHorizontalItem(item);
|
||||||
@@ -897,21 +994,11 @@ namespace UVC.UIToolkit
|
|||||||
}, TrickleDown.TrickleDown);
|
}, TrickleDown.TrickleDown);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Button CreateTailButton(UTKAccordionContentSpec spec)
|
private UTKButton CreateTailButton(UTKAccordionContentSpec spec)
|
||||||
{
|
{
|
||||||
var btn = new Button();
|
var btn = new UTKButton("", spec.IconName ?? "", UTKButton.ButtonVariant.Text, spec.IconSize ?? 12) { IconOnly = true };
|
||||||
btn.AddToClassList("accordion-tail-button");
|
btn.AddToClassList("accordion-tail-button");
|
||||||
|
|
||||||
var icon = new VisualElement();
|
|
||||||
icon.AddToClassList("accordion-tail-icon");
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(spec.IconName))
|
|
||||||
{
|
|
||||||
LoadIconAsync(icon, spec.IconName).Forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
btn.Add(icon);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(spec.Tooltip))
|
if (!string.IsNullOrEmpty(spec.Tooltip))
|
||||||
{
|
{
|
||||||
btn.tooltip = spec.Tooltip;
|
btn.tooltip = spec.Tooltip;
|
||||||
@@ -924,8 +1011,24 @@ namespace UVC.UIToolkit
|
|||||||
{
|
{
|
||||||
if (spec.Kind == UTKAccordionContentKind.Image && !string.IsNullOrEmpty(spec.ImagePath))
|
if (spec.Kind == UTKAccordionContentKind.Image && !string.IsNullOrEmpty(spec.ImagePath))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
string iconChar = UTKMaterialIcons.GetIcon(spec.ImagePath);
|
||||||
|
Debug.Log($"[UTKAccordionList] Content image path: '{spec.ImagePath} ' → icon char: '{iconChar}'");
|
||||||
|
if (iconChar != string.Empty)
|
||||||
|
{
|
||||||
|
Debug.Log($"[UTKAccordionList] Using material icon '{spec.ImagePath}' for content image.");
|
||||||
|
// 머티리얼 아이콘 사용
|
||||||
|
Label iconLabel = new Label(iconChar);
|
||||||
|
UTKMaterialIcons.ApplyIconStyle(iconLabel, null); //uss에서 설정하기에 null 전달
|
||||||
|
imageElement.Add(iconLabel);
|
||||||
|
if(spec.ImageColor != null) iconLabel.style.color = spec.ImageColor.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 일반 이미지 로드
|
||||||
BindImageAsync(imageElement, spec.ImagePath).Forget();
|
BindImageAsync(imageElement, spec.ImagePath).Forget();
|
||||||
imageElement.style.unityBackgroundImageTintColor = spec.ImageColor;
|
if(spec.ImageColor != null) imageElement.style.unityBackgroundImageTintColor = spec.ImageColor.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1586,6 +1689,24 @@ namespace UVC.UIToolkit
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 테마 (Theme)
|
||||||
|
|
||||||
|
private void SubscribeToThemeChanges()
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
|
||||||
|
RegisterCallback<DetachFromPanelEvent>(_ =>
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnThemeChanged(UTKTheme theme)
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -1593,6 +1714,9 @@ namespace UVC.UIToolkit
|
|||||||
if (_disposed) return;
|
if (_disposed) return;
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
|
// 테마 변경 이벤트 해제
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
|
||||||
// 이미지 로딩 취소
|
// 이미지 로딩 취소
|
||||||
CancelImageLoading();
|
CancelImageLoading();
|
||||||
|
|
||||||
@@ -1614,7 +1738,8 @@ namespace UVC.UIToolkit
|
|||||||
|
|
||||||
if (_clearButton != null)
|
if (_clearButton != null)
|
||||||
{
|
{
|
||||||
_clearButton.clicked -= OnClearButtonClicked;
|
_clearButton.OnClicked -= OnClearButtonClicked;
|
||||||
|
_clearButton.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TreeView 이벤트 해제
|
// TreeView 이벤트 해제
|
||||||
|
|||||||
@@ -47,11 +47,14 @@ namespace UVC.UIToolkit
|
|||||||
public string? ImagePath { get; set; }
|
public string? ImagePath { get; set; }
|
||||||
|
|
||||||
/// <summary>이미지 색상</summary>
|
/// <summary>이미지 색상</summary>
|
||||||
public Color ImageColor { get; set; } = Color.white;
|
public Color? ImageColor { get; set; }
|
||||||
|
|
||||||
/// <summary>아이콘 이름 또는 경로</summary>
|
/// <summary>아이콘 이름 또는 경로</summary>
|
||||||
public string? IconName { get; set; }
|
public string? IconName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>아이콘 크기 (정사각형 기준, 픽셀 단위)</summary>
|
||||||
|
public int? IconSize { get; set; }
|
||||||
|
|
||||||
/// <summary>툴팁 텍스트</summary>
|
/// <summary>툴팁 텍스트</summary>
|
||||||
public string? Tooltip { get; set; }
|
public string? Tooltip { get; set; }
|
||||||
|
|
||||||
@@ -77,16 +80,17 @@ namespace UVC.UIToolkit
|
|||||||
{
|
{
|
||||||
Kind = UTKAccordionContentKind.Image,
|
Kind = UTKAccordionContentKind.Image,
|
||||||
ImagePath = path,
|
ImagePath = path,
|
||||||
ImageColor = color ?? Color.white,
|
ImageColor = color,
|
||||||
Tooltip = tooltip
|
Tooltip = tooltip
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>아이콘 버튼 스펙을 생성합니다.</summary>
|
/// <summary>아이콘 버튼 스펙을 생성합니다.</summary>
|
||||||
public static UTKAccordionContentSpec FromIconButton(string iconName, string? actionId = null, string? tooltip = null, object? userData = null)
|
public static UTKAccordionContentSpec FromIconButton(string iconName, int iconSize, string? actionId = null, string? tooltip = null, object? userData = null)
|
||||||
=> new UTKAccordionContentSpec
|
=> new UTKAccordionContentSpec
|
||||||
{
|
{
|
||||||
Kind = UTKAccordionContentKind.IconButton,
|
Kind = UTKAccordionContentKind.IconButton,
|
||||||
IconName = iconName,
|
IconName = iconName,
|
||||||
|
IconSize = iconSize,
|
||||||
ActionId = actionId,
|
ActionId = actionId,
|
||||||
Tooltip = tooltip,
|
Tooltip = tooltip,
|
||||||
UserData = userData
|
UserData = userData
|
||||||
|
|||||||
@@ -27,22 +27,123 @@ namespace UVC.UIToolkit
|
|||||||
/// <item>선택 이벤트 처리</item>
|
/// <item>선택 이벤트 처리</item>
|
||||||
/// </list>
|
/// </list>
|
||||||
///
|
///
|
||||||
/// <para><b>UXML에서 사용:</b></para>
|
/// <para><b>UXML 사용 예시:</b></para>
|
||||||
/// <code>
|
/// <code><![CDATA[
|
||||||
/// <UVC.UIToolkit.Window.UTKComponentList name="tree-list" />
|
/// <!-- UXML 파일에서 UTKComponentList 사용 -->
|
||||||
/// </code>
|
/// <ui:UXML xmlns:utk="UVC.UIToolkit">
|
||||||
|
/// <utk:UTKComponentList name="component-list" />
|
||||||
|
/// </ui:UXML>
|
||||||
|
/// ]]></code>
|
||||||
///
|
///
|
||||||
/// <para><b>코드에서 사용:</b></para>
|
/// <para><b>C# 사용 예시:</b></para>
|
||||||
/// <code>
|
/// <code><![CDATA[
|
||||||
/// var list = root.Q<UTKComponentList>();
|
/// // 1. 컴포넌트 리스트 참조 획득
|
||||||
/// list.OnSelectionChanged += (item) => Debug.Log($"선택: {item.name}");
|
/// var componentList = root.Q<UTKComponentList>("component-list");
|
||||||
/// list.OnVisibilityChanged += (item) => model.SetActive(item.id, item.IsVisible);
|
///
|
||||||
/// list.SetData(treeItems);
|
/// // 2. 데이터 구성 - 카테고리(그룹)와 일반 아이템
|
||||||
/// </code>
|
/// var data = new List<UTKComponentListItemDataBase>
|
||||||
|
/// {
|
||||||
|
/// // 카테고리(그룹) 생성
|
||||||
|
/// new UTKComponentListCategoryData
|
||||||
|
/// {
|
||||||
|
/// name = "모델 그룹 A",
|
||||||
|
/// isExpanded = true,
|
||||||
|
/// children = new List<UTKComponentListItemDataBase>
|
||||||
|
/// {
|
||||||
|
/// // 일반 아이템
|
||||||
|
/// new UTKComponentListItemData
|
||||||
|
/// {
|
||||||
|
/// name = "의자 모델",
|
||||||
|
/// ExternalKey = "chair_001",
|
||||||
|
/// IsVisible = true
|
||||||
|
/// },
|
||||||
|
/// new UTKComponentListItemData
|
||||||
|
/// {
|
||||||
|
/// name = "책상 모델",
|
||||||
|
/// ExternalKey = "desk_001",
|
||||||
|
/// IsVisible = true
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 3. 데이터 설정
|
||||||
|
/// componentList.SetData(data);
|
||||||
|
///
|
||||||
|
/// // 4. 선택 이벤트 구독 - 아이템 선택 시 호출
|
||||||
|
/// componentList.OnItemSelected += (selectedItems) =>
|
||||||
|
/// {
|
||||||
|
/// foreach (var item in selectedItems)
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"선택됨: {item.name}");
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 5. 선택 해제 이벤트 구독
|
||||||
|
/// componentList.OnItemDeselected += (deselectedItems) =>
|
||||||
|
/// {
|
||||||
|
/// foreach (var item in deselectedItems)
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"선택 해제: {item.name}");
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 6. 가시성 변경 이벤트 구독 - 눈 아이콘 클릭 시 호출
|
||||||
|
/// componentList.OnItemVisibilityChanged += (item, isVisible) =>
|
||||||
|
/// {
|
||||||
|
/// // 3D 모델의 GameObject 활성화/비활성화
|
||||||
|
/// var gameObject = FindGameObjectByKey(item.ExternalKey);
|
||||||
|
/// if (gameObject != null)
|
||||||
|
/// {
|
||||||
|
/// gameObject.SetActive(isVisible);
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 7. 삭제 이벤트 구독 (Delete/Backspace 키)
|
||||||
|
/// componentList.EnabledDeleteItem = true; // 삭제 기능 활성화 필수
|
||||||
|
/// componentList.OnItemDeleted += (item) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"삭제 요청: {item.name}");
|
||||||
|
/// componentList.DeleteItem(item); // 리스트에서 제거
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 8. 더블클릭 이벤트 구독
|
||||||
|
/// componentList.OnItemDoubleClicked += (item) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"더블클릭: {item.name}");
|
||||||
|
/// // 카메라 포커스 등의 동작 수행
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 9. 아이콘 클릭 이벤트 (setting-btn, search-btn)
|
||||||
|
/// componentList.OnItemIconClicked += (iconName, item) =>
|
||||||
|
/// {
|
||||||
|
/// if (iconName == "setting-btn")
|
||||||
|
/// {
|
||||||
|
/// ShowCategorySettings(item);
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 10. 검색 실행
|
||||||
|
/// componentList.ApplySearch("의자");
|
||||||
|
///
|
||||||
|
/// // 11. 프로그래밍 방식 선택
|
||||||
|
/// componentList.SelectItem("의자 모델", notify: true);
|
||||||
|
/// componentList.DeselectItem("의자 모델", notify: false);
|
||||||
|
/// componentList.ClearSelection();
|
||||||
|
///
|
||||||
|
/// // 12. 아이템 추가/삭제
|
||||||
|
/// var newItem = new UTKComponentListItemData { name = "새 아이템" };
|
||||||
|
/// componentList.AddItem(newItem); // 루트에 추가
|
||||||
|
/// componentList.AddItem(categoryData, newItem); // 특정 카테고리에 추가
|
||||||
|
/// componentList.DeleteItem(newItem); // 삭제
|
||||||
|
///
|
||||||
|
/// // 13. 리소스 해제 (OnDestroy에서 호출)
|
||||||
|
/// componentList.Dispose();
|
||||||
|
/// ]]></code>
|
||||||
///
|
///
|
||||||
/// <para><b>관련 리소스:</b></para>
|
/// <para><b>관련 리소스:</b></para>
|
||||||
/// <list type="bullet">
|
/// <list type="bullet">
|
||||||
/// <item>Resources/UIToolkit/Window/UTKComponentList.uxml - 메인 레이아웃</item>
|
/// <item>Resources/UIToolkit/List/UTKComponentList.uxml - 메인 레이아웃</item>
|
||||||
/// <item>Resources/UIToolkit/List/UTKComponentListItem.uxml - 개별 항목 템플릿</item>
|
/// <item>Resources/UIToolkit/List/UTKComponentListItem.uxml - 개별 항목 템플릿</item>
|
||||||
/// <item>Resources/UIToolkit/List/UTKComponentListGroupItem.uxml - 그룹 항목 템플릿</item>
|
/// <item>Resources/UIToolkit/List/UTKComponentListGroupItem.uxml - 그룹 항목 템플릿</item>
|
||||||
/// </list>
|
/// </list>
|
||||||
@@ -63,6 +164,8 @@ namespace UVC.UIToolkit
|
|||||||
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
||||||
private const string UXML_PATH = "UIToolkit/List/UTKComponentList";
|
private const string UXML_PATH = "UIToolkit/List/UTKComponentList";
|
||||||
|
|
||||||
|
private const string USS_PATH = "UIToolkit/List/UTKComponentListUss";
|
||||||
|
|
||||||
/// <summary>일반 항목 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
/// <summary>일반 항목 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
||||||
private const string ITEM_UXML_PATH = "UIToolkit/List/UTKComponentListItem";
|
private const string ITEM_UXML_PATH = "UIToolkit/List/UTKComponentListItem";
|
||||||
|
|
||||||
@@ -85,8 +188,8 @@ namespace UVC.UIToolkit
|
|||||||
/// <summary>Unity UI Toolkit의 TreeView 컴포넌트</summary>
|
/// <summary>Unity UI Toolkit의 TreeView 컴포넌트</summary>
|
||||||
private TreeView? _treeView;
|
private TreeView? _treeView;
|
||||||
|
|
||||||
/// <summary>검색어 지우기 버튼</summary>
|
/// <summary>검색어 지우기 버튼 (UTKButton)</summary>
|
||||||
private Button? _clearButton;
|
private UTKButton? _clearButton;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 내부 데이터 (Internal Data)
|
#region 내부 데이터 (Internal Data)
|
||||||
@@ -199,6 +302,8 @@ namespace UVC.UIToolkit
|
|||||||
}
|
}
|
||||||
visualTree!.CloneTree(this);
|
visualTree!.CloneTree(this);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 2. 항목 템플릿 로드
|
// 2. 항목 템플릿 로드
|
||||||
_itemTemplate = Resources.Load<VisualTreeAsset>(ITEM_UXML_PATH);
|
_itemTemplate = Resources.Load<VisualTreeAsset>(ITEM_UXML_PATH);
|
||||||
_groupItemTemplate = Resources.Load<VisualTreeAsset>(GROUP_ITEM_UXML_PATH);
|
_groupItemTemplate = Resources.Load<VisualTreeAsset>(GROUP_ITEM_UXML_PATH);
|
||||||
@@ -207,13 +312,29 @@ namespace UVC.UIToolkit
|
|||||||
if (_groupItemTemplate == null)
|
if (_groupItemTemplate == null)
|
||||||
Debug.LogError($"[UTKComponentList] Group Item UXML not found at: {GROUP_ITEM_UXML_PATH}");
|
Debug.LogError($"[UTKComponentList] Group Item UXML not found at: {GROUP_ITEM_UXML_PATH}");
|
||||||
|
|
||||||
|
// 테마 적용 및 변경 구독
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
SubscribeToThemeChanges();
|
||||||
|
|
||||||
// 2. 자식 요소 참조 획득 (UXML의 name 속성으로 찾음)
|
// USS 로드 (테마 변수 스타일시트 이후에 로드되어야 변수가 해석됨)
|
||||||
|
var uss = Resources.Load<StyleSheet>(USS_PATH);
|
||||||
|
if (uss != null)
|
||||||
|
{
|
||||||
|
styleSheets.Add(uss);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 자식 요소 참조 획득 (UXML의 name 속성으로 찾음)
|
||||||
_searchField = this.Q<TextField>("search-field");
|
_searchField = this.Q<TextField>("search-field");
|
||||||
_treeView = this.Q<TreeView>("main-tree-view");
|
_treeView = this.Q<TreeView>("main-tree-view");
|
||||||
_clearButton = this.Q<Button>("clear-btn");
|
_clearButton = this.Q<UTKButton>("clear-btn");
|
||||||
|
|
||||||
// 3. 이벤트 연결 및 로직 초기화
|
// 4. Clear 버튼 아이콘 설정
|
||||||
|
if (_clearButton != null)
|
||||||
|
{
|
||||||
|
_clearButton.SetMaterialIcon(UTKMaterialIcons.Close, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 이벤트 연결 및 로직 초기화
|
||||||
InitializeLogic();
|
InitializeLogic();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -251,15 +372,7 @@ namespace UVC.UIToolkit
|
|||||||
if(_clearButton != null)
|
if(_clearButton != null)
|
||||||
{
|
{
|
||||||
_clearButton.style.display = DisplayStyle.None; // 초기에는 숨김
|
_clearButton.style.display = DisplayStyle.None; // 초기에는 숨김
|
||||||
_clearButton.clicked += () =>
|
_clearButton.OnClicked += OnClearButtonClicked;
|
||||||
{
|
|
||||||
if (_searchField.value.Length > 0)
|
|
||||||
{
|
|
||||||
_searchField.value = string.Empty;
|
|
||||||
OnSearch(string.Empty);
|
|
||||||
}
|
|
||||||
_clearButton.style.display = DisplayStyle.None; // 클리어 후 숨김
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 스크롤바 hover/active 색상 설정
|
// 스크롤바 hover/active 색상 설정
|
||||||
@@ -1372,6 +1485,22 @@ namespace UVC.UIToolkit
|
|||||||
OnSearch(_searchField?.value ?? string.Empty);
|
OnSearch(_searchField?.value ?? string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clear 버튼 클릭 이벤트를 처리합니다.
|
||||||
|
/// </summary>
|
||||||
|
private void OnClearButtonClicked()
|
||||||
|
{
|
||||||
|
if (_searchField != null && _searchField.value.Length > 0)
|
||||||
|
{
|
||||||
|
_searchField.value = string.Empty;
|
||||||
|
OnSearch(string.Empty);
|
||||||
|
}
|
||||||
|
if (_clearButton != null)
|
||||||
|
{
|
||||||
|
_clearButton.style.display = DisplayStyle.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 검색어에 따라 트리를 필터링합니다.
|
/// 검색어에 따라 트리를 필터링합니다.
|
||||||
/// 검색어가 비어있으면 원본 데이터로 복원됩니다.
|
/// 검색어가 비어있으면 원본 데이터로 복원됩니다.
|
||||||
@@ -1562,6 +1691,24 @@ namespace UVC.UIToolkit
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 테마 (Theme)
|
||||||
|
|
||||||
|
private void SubscribeToThemeChanges()
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
|
||||||
|
RegisterCallback<DetachFromPanelEvent>(_ =>
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnThemeChanged(UTKTheme theme)
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 리소스를 해제하고 이벤트 핸들러를 정리합니다.
|
/// 리소스를 해제하고 이벤트 핸들러를 정리합니다.
|
||||||
@@ -1571,6 +1718,9 @@ namespace UVC.UIToolkit
|
|||||||
if (_disposed) return;
|
if (_disposed) return;
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
|
// 테마 변경 이벤트 해제
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
|
||||||
// 검색 필드 이벤트 해제
|
// 검색 필드 이벤트 해제
|
||||||
if (_searchField != null)
|
if (_searchField != null)
|
||||||
{
|
{
|
||||||
@@ -1589,6 +1739,13 @@ namespace UVC.UIToolkit
|
|||||||
_treeView.makeItem = null;
|
_treeView.makeItem = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear 버튼 이벤트 해제 및 정리
|
||||||
|
if (_clearButton != null)
|
||||||
|
{
|
||||||
|
_clearButton.OnClicked -= OnClearButtonClicked;
|
||||||
|
_clearButton.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// 외부 이벤트 구독자 정리
|
// 외부 이벤트 구독자 정리
|
||||||
OnItemVisibilityChanged = null;
|
OnItemVisibilityChanged = null;
|
||||||
OnItemSelected = null;
|
OnItemSelected = null;
|
||||||
|
|||||||
@@ -23,22 +23,125 @@ namespace UVC.UIToolkit
|
|||||||
/// <para><b>주요 기능:</b></para>
|
/// <para><b>주요 기능:</b></para>
|
||||||
/// <list type="bullet">
|
/// <list type="bullet">
|
||||||
/// <item>이미지+텍스트 형태의 아이템을 2열 그리드로 표시</item>
|
/// <item>이미지+텍스트 형태의 아이템을 2열 그리드로 표시</item>
|
||||||
/// <item>실시간 검색 필터링 (3글자 이상)</item>
|
/// <item>실시간 검색 필터링 (2글자 이상)</item>
|
||||||
/// <item>드래그 앤 드롭 지원</item>
|
/// <item>드래그 앤 드롭 지원</item>
|
||||||
/// <item>가상화를 통한 대량 데이터 성능 최적화</item>
|
/// <item>가상화를 통한 대량 데이터 성능 최적화</item>
|
||||||
/// </list>
|
/// </list>
|
||||||
///
|
///
|
||||||
/// <para><b>UXML에서 사용:</b></para>
|
/// <para><b>UXML 사용 예시:</b></para>
|
||||||
/// <code>
|
/// <code><![CDATA[
|
||||||
/// <uvc:UTKImageList name="image-list" />
|
/// <!-- UXML 파일에서 UTKImageList 사용 -->
|
||||||
/// </code>
|
/// <ui:UXML xmlns:utk="UVC.UIToolkit">
|
||||||
|
/// <utk:UTKImageList name="image-list" />
|
||||||
|
/// </ui:UXML>
|
||||||
|
/// ]]></code>
|
||||||
///
|
///
|
||||||
/// <para><b>코드에서 사용:</b></para>
|
/// <para><b>C# 사용 예시:</b></para>
|
||||||
/// <code>
|
/// <code><![CDATA[
|
||||||
/// var list = root.Q<UTKImageList>();
|
/// // 1. 이미지 리스트 참조 획득
|
||||||
/// list.OnItemClick += (item) => Debug.Log($"클릭: {item.itemName}");
|
/// var imageList = root.Q<UTKImageList>("image-list");
|
||||||
/// list.SetData(imageItems);
|
///
|
||||||
/// </code>
|
/// // 2. 데이터 구성 - 이미지 경로와 이름을 가진 아이템들
|
||||||
|
/// var data = new List<UTKImageListItemData>
|
||||||
|
/// {
|
||||||
|
/// new UTKImageListItemData
|
||||||
|
/// {
|
||||||
|
/// itemName = "의자",
|
||||||
|
/// imagePath = "Prefabs/Thumbnails/chair",
|
||||||
|
/// prefabPath = "Prefabs/Furniture/Chair"
|
||||||
|
/// },
|
||||||
|
/// new UTKImageListItemData
|
||||||
|
/// {
|
||||||
|
/// itemName = "책상",
|
||||||
|
/// imagePath = "Prefabs/Thumbnails/desk",
|
||||||
|
/// prefabPath = "Prefabs/Furniture/Desk"
|
||||||
|
/// },
|
||||||
|
/// new UTKImageListItemData
|
||||||
|
/// {
|
||||||
|
/// itemName = "소파",
|
||||||
|
/// imagePath = "Prefabs/Thumbnails/sofa",
|
||||||
|
/// prefabPath = "Prefabs/Furniture/Sofa"
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 3. 데이터 설정
|
||||||
|
/// imageList.SetData(data);
|
||||||
|
///
|
||||||
|
/// // 4. 아이템 클릭 이벤트 구독
|
||||||
|
/// imageList.OnItemClick += (item) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"클릭된 아이템: {item.itemName}");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 5. 드래그 앤 드롭 이벤트 (씬에 프리팹 배치용)
|
||||||
|
/// imageList.OnItemBeginDrag += (item, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"드래그 시작: {item.itemName}");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// imageList.OnItemDrag += (item, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// // 드래그 중 - 3D 미리보기 위치 업데이트 등
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// imageList.OnItemEndDrag += (item, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"드래그 종료: {item.itemName}");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// imageList.OnItemDrop += (item) =>
|
||||||
|
/// {
|
||||||
|
/// // 드롭 완료 - 프리팹 인스턴스화
|
||||||
|
/// if (!string.IsNullOrEmpty(item.prefabPath))
|
||||||
|
/// {
|
||||||
|
/// var prefab = Resources.Load<GameObject>(item.prefabPath);
|
||||||
|
/// Instantiate(prefab, dropPosition, Quaternion.identity);
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 6. 리스트 영역 밖으로 드래그 시 3D 미리보기 표시
|
||||||
|
/// imageList.OnDragExitList += (item, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// // 리스트 밖 = 3D 씬 영역
|
||||||
|
/// Show3DPreview(item.prefabPath, screenPos);
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 7. 리스트 영역 안으로 다시 들어왔을 때 미리보기 숨김
|
||||||
|
/// imageList.OnDragEnterList += (item, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// Hide3DPreview();
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 8. 드래그 영역 설정 (부모 윈도우 영역 기준으로 체크)
|
||||||
|
/// imageList.DragBoundsElement = parentWindow;
|
||||||
|
///
|
||||||
|
/// // 9. 드래그 고스트 이미지 따라다니기 설정
|
||||||
|
/// imageList.DragImageFollowCursor = true;
|
||||||
|
///
|
||||||
|
/// // 10. 검색 실행 (2글자 이상)
|
||||||
|
/// imageList.ApplySearch("의자");
|
||||||
|
///
|
||||||
|
/// // 11. 현재 검색어 확인
|
||||||
|
/// string currentQuery = imageList.SearchQuery;
|
||||||
|
///
|
||||||
|
/// // 12. 아이템 추가/제거
|
||||||
|
/// var newItem = new UTKImageListItemData { itemName = "새 아이템" };
|
||||||
|
/// imageList.AddItem(newItem);
|
||||||
|
/// imageList.RemoveItem(newItem);
|
||||||
|
///
|
||||||
|
/// // 13. 전체 삭제
|
||||||
|
/// imageList.Clear();
|
||||||
|
///
|
||||||
|
/// // 14. 아이템 개수 확인
|
||||||
|
/// int count = imageList.ItemCount;
|
||||||
|
///
|
||||||
|
/// // 15. 리스트 표시/숨김
|
||||||
|
/// imageList.Show();
|
||||||
|
/// imageList.Hide();
|
||||||
|
///
|
||||||
|
/// // 16. 리소스 해제 (OnDestroy에서 호출)
|
||||||
|
/// imageList.Dispose();
|
||||||
|
/// ]]></code>
|
||||||
///
|
///
|
||||||
/// <para><b>관련 리소스:</b></para>
|
/// <para><b>관련 리소스:</b></para>
|
||||||
/// <list type="bullet">
|
/// <list type="bullet">
|
||||||
@@ -54,6 +157,7 @@ namespace UVC.UIToolkit
|
|||||||
|
|
||||||
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
||||||
private const string UXML_PATH = "UIToolkit/List/UTKImageList";
|
private const string UXML_PATH = "UIToolkit/List/UTKImageList";
|
||||||
|
private const string USS_PATH = "UIToolkit/List/UTKImageListUss";
|
||||||
|
|
||||||
/// <summary>아이템 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
/// <summary>아이템 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
||||||
private const string ITEM_UXML_PATH = "UIToolkit/List/UTKImageListItem";
|
private const string ITEM_UXML_PATH = "UIToolkit/List/UTKImageListItem";
|
||||||
@@ -84,8 +188,8 @@ namespace UVC.UIToolkit
|
|||||||
/// <summary>Unity UI Toolkit의 ListView 컴포넌트</summary>
|
/// <summary>Unity UI Toolkit의 ListView 컴포넌트</summary>
|
||||||
private ListView? _listView;
|
private ListView? _listView;
|
||||||
|
|
||||||
/// <summary>검색어 지우기 버튼</summary>
|
/// <summary>검색어 지우기 버튼 (UTKButton)</summary>
|
||||||
private Button? _clearButton;
|
private UTKButton? _clearButton;
|
||||||
|
|
||||||
/// <summary>검색 결과 건수 라벨</summary>
|
/// <summary>검색 결과 건수 라벨</summary>
|
||||||
private Label? _searchResultLabel;
|
private Label? _searchResultLabel;
|
||||||
@@ -248,13 +352,30 @@ namespace UVC.UIToolkit
|
|||||||
Debug.LogError($"[UTKImageList] Item UXML not found at: {ITEM_UXML_PATH}");
|
Debug.LogError($"[UTKImageList] Item UXML not found at: {ITEM_UXML_PATH}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. UI 요소 참조 획득
|
// 3. 테마 적용 및 변경 구독
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
SubscribeToThemeChanges();
|
||||||
|
|
||||||
|
// USS 로드 (테마 변수 스타일시트 이후에 로드되어야 변수가 해석됨)
|
||||||
|
var uss = Resources.Load<StyleSheet>(USS_PATH);
|
||||||
|
if (uss != null)
|
||||||
|
{
|
||||||
|
styleSheets.Add(uss);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. UI 요소 참조 획득
|
||||||
_searchField = this.Q<TextField>("search-field");
|
_searchField = this.Q<TextField>("search-field");
|
||||||
_listView = this.Q<ListView>("main-list-view");
|
_listView = this.Q<ListView>("main-list-view");
|
||||||
_clearButton = this.Q<Button>("clear-btn");
|
_clearButton = this.Q<UTKButton>("clear-btn");
|
||||||
_searchResultLabel = this.Q<Label>("search-result-label");
|
_searchResultLabel = this.Q<Label>("search-result-label");
|
||||||
|
|
||||||
// 4. 이벤트 연결 및 로직 초기화
|
// 5. Clear 버튼 아이콘 설정
|
||||||
|
if (_clearButton != null)
|
||||||
|
{
|
||||||
|
_clearButton.SetMaterialIcon(UTKMaterialIcons.Close, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 이벤트 연결 및 로직 초기화
|
||||||
InitializeLogic();
|
InitializeLogic();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +398,7 @@ namespace UVC.UIToolkit
|
|||||||
// 검색어 지우기 버튼 이벤트 등록
|
// 검색어 지우기 버튼 이벤트 등록
|
||||||
if (_clearButton != null)
|
if (_clearButton != null)
|
||||||
{
|
{
|
||||||
_clearButton.clicked += OnClearButtonClicked;
|
_clearButton.OnClicked += OnClearButtonClicked;
|
||||||
_clearButton.style.display = DisplayStyle.None; // 초기에는 숨김
|
_clearButton.style.display = DisplayStyle.None; // 초기에는 숨김
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1144,6 +1265,24 @@ namespace UVC.UIToolkit
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 테마 (Theme)
|
||||||
|
|
||||||
|
private void SubscribeToThemeChanges()
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
|
||||||
|
RegisterCallback<DetachFromPanelEvent>(_ =>
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnThemeChanged(UTKTheme theme)
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1154,6 +1293,9 @@ namespace UVC.UIToolkit
|
|||||||
if (_disposed) return;
|
if (_disposed) return;
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
|
// 테마 변경 이벤트 해제
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
|
||||||
// 이미지 로딩 취소
|
// 이미지 로딩 취소
|
||||||
CancelImageLoading();
|
CancelImageLoading();
|
||||||
|
|
||||||
@@ -1176,7 +1318,8 @@ namespace UVC.UIToolkit
|
|||||||
|
|
||||||
if (_clearButton != null)
|
if (_clearButton != null)
|
||||||
{
|
{
|
||||||
_clearButton.clicked -= OnClearButtonClicked;
|
_clearButton.OnClicked -= OnClearButtonClicked;
|
||||||
|
_clearButton.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 드래그 고스트 정리
|
// 드래그 고스트 정리
|
||||||
|
|||||||
@@ -22,6 +22,113 @@ namespace UVC.UIToolkit
|
|||||||
/// <item>드래그 앤 드롭 이벤트 전달</item>
|
/// <item>드래그 앤 드롭 이벤트 전달</item>
|
||||||
/// </list>
|
/// </list>
|
||||||
///
|
///
|
||||||
|
/// <para><b>UXML 사용 예시:</b></para>
|
||||||
|
/// <code><![CDATA[
|
||||||
|
/// <!-- UXML 파일에서 UTKAccordionListWindow 사용 -->
|
||||||
|
/// <ui:UXML xmlns:utk="UVC.UIToolkit">
|
||||||
|
/// <utk:UTKAccordionListWindow name="accordion-window" />
|
||||||
|
/// </ui:UXML>
|
||||||
|
/// ]]></code>
|
||||||
|
///
|
||||||
|
/// <para><b>C# 사용 예시:</b></para>
|
||||||
|
/// <code><![CDATA[
|
||||||
|
/// // 1. 윈도우 참조 획득
|
||||||
|
/// var accordionWindow = root.Q<UTKAccordionListWindow>("accordion-window");
|
||||||
|
///
|
||||||
|
/// // 2. 윈도우 제목 설정
|
||||||
|
/// accordionWindow.Title = "프리팹 라이브러리";
|
||||||
|
///
|
||||||
|
/// // 3. 닫기 버튼 표시 설정
|
||||||
|
/// accordionWindow.ShowCloseButton = true;
|
||||||
|
///
|
||||||
|
/// // 4. 데이터 구성 및 설정
|
||||||
|
/// var data = new List<UTKAccordionItemData>
|
||||||
|
/// {
|
||||||
|
/// new UTKAccordionItemData
|
||||||
|
/// {
|
||||||
|
/// nodeType = UTKAccordionNodeType.Section,
|
||||||
|
/// name = "가구",
|
||||||
|
/// isExpanded = true,
|
||||||
|
/// children = new List<UTKAccordionItemData>
|
||||||
|
/// {
|
||||||
|
/// new UTKAccordionItemData
|
||||||
|
/// {
|
||||||
|
/// nodeType = UTKAccordionNodeType.GridItem,
|
||||||
|
/// name = "의자",
|
||||||
|
/// imagePath = "Prefabs/Thumbnails/chair",
|
||||||
|
/// prefabPath = "Prefabs/Furniture/Chair"
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
/// accordionWindow.SetData(data);
|
||||||
|
///
|
||||||
|
/// // 5. 아이템 클릭 이벤트 구독 (통합 API)
|
||||||
|
/// accordionWindow.OnItemClick += (item) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"클릭된 아이템: {item.name}");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 6. 드래그 앤 드롭 이벤트 구독
|
||||||
|
/// accordionWindow.OnItemBeginDrag += (item, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"드래그 시작: {item.name}");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// accordionWindow.OnItemDrop += (item) =>
|
||||||
|
/// {
|
||||||
|
/// // 프리팹 인스턴스화
|
||||||
|
/// if (!string.IsNullOrEmpty(item.prefabPath))
|
||||||
|
/// {
|
||||||
|
/// var prefab = Resources.Load<GameObject>(item.prefabPath);
|
||||||
|
/// Instantiate(prefab, dropPosition, Quaternion.identity);
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 7. 리스트 영역 밖으로 드래그 시 3D 미리보기 표시
|
||||||
|
/// accordionWindow.OnDragExitList += (gridItem, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// Show3DPreview(gridItem.PrefabPath, screenPos);
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 8. 리스트 영역으로 다시 들어오면 미리보기 숨김
|
||||||
|
/// accordionWindow.OnDragEnterList += (gridItem, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// Hide3DPreview();
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 9. 섹션 펼침/접힘 이벤트
|
||||||
|
/// accordionWindow.OnSectionToggled += (section, isExpanded) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"섹션 '{section.Title}': {(isExpanded ? "펼침" : "접힘")}");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 10. 윈도우 닫힘 이벤트
|
||||||
|
/// accordionWindow.OnClosed += () =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log("윈도우가 닫혔습니다.");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 11. 드래그 고스트 이미지 설정
|
||||||
|
/// accordionWindow.ShowDragGhost = true;
|
||||||
|
///
|
||||||
|
/// // 12. 검색 실행
|
||||||
|
/// accordionWindow.Search("의자");
|
||||||
|
/// accordionWindow.ClearSearch();
|
||||||
|
///
|
||||||
|
/// // 13. 섹션 제어
|
||||||
|
/// accordionWindow.ExpandAll();
|
||||||
|
/// accordionWindow.CollapseAll();
|
||||||
|
/// accordionWindow.SetSectionExpanded(sectionId, true);
|
||||||
|
///
|
||||||
|
/// // 14. 윈도우 표시/닫기
|
||||||
|
/// accordionWindow.Show();
|
||||||
|
/// accordionWindow.Close();
|
||||||
|
///
|
||||||
|
/// // 15. 리소스 해제 (OnDestroy에서 호출)
|
||||||
|
/// accordionWindow.Dispose();
|
||||||
|
/// ]]></code>
|
||||||
|
///
|
||||||
/// <para><b>관련 리소스:</b></para>
|
/// <para><b>관련 리소스:</b></para>
|
||||||
/// <list type="bullet">
|
/// <list type="bullet">
|
||||||
/// <item>Resources/UIToolkit/Window/UTKAccordionListWindow.uxml - 윈도우 레이아웃</item>
|
/// <item>Resources/UIToolkit/Window/UTKAccordionListWindow.uxml - 윈도우 레이아웃</item>
|
||||||
@@ -34,13 +141,14 @@ namespace UVC.UIToolkit
|
|||||||
#region 상수 (Constants)
|
#region 상수 (Constants)
|
||||||
|
|
||||||
private const string UXML_PATH = "UIToolkit/Window/UTKAccordionListWindow";
|
private const string UXML_PATH = "UIToolkit/Window/UTKAccordionListWindow";
|
||||||
|
private const string USS_PATH = "UIToolkit/Window/UTKAccordionListWindowUss";
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region UI 컴포넌트 참조 (UI Component References)
|
#region UI 컴포넌트 참조 (UI Component References)
|
||||||
|
|
||||||
private UTKAccordionList? _accordionList;
|
private UTKAccordionList? _accordionList;
|
||||||
private Button? _closeButton;
|
private UTKButton? _closeButton;
|
||||||
private Label? _titleLabel;
|
private Label? _titleLabel;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -226,6 +334,17 @@ namespace UVC.UIToolkit
|
|||||||
}
|
}
|
||||||
visualTree.CloneTree(this);
|
visualTree.CloneTree(this);
|
||||||
|
|
||||||
|
// 테마 적용 및 변경 구독
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
SubscribeToThemeChanges();
|
||||||
|
|
||||||
|
// USS 로드 (테마 변수 스타일시트 이후에 로드되어야 변수가 해석됨)
|
||||||
|
var uss = Resources.Load<StyleSheet>(USS_PATH);
|
||||||
|
if (uss != null)
|
||||||
|
{
|
||||||
|
styleSheets.Add(uss);
|
||||||
|
}
|
||||||
|
|
||||||
// 내부 UTKAccordionList 찾기
|
// 내부 UTKAccordionList 찾기
|
||||||
_accordionList = this.Q<UTKAccordionList>();
|
_accordionList = this.Q<UTKAccordionList>();
|
||||||
if (_accordionList == null)
|
if (_accordionList == null)
|
||||||
@@ -240,12 +359,13 @@ namespace UVC.UIToolkit
|
|||||||
|
|
||||||
// 헤더 요소 참조
|
// 헤더 요소 참조
|
||||||
_titleLabel = this.Q<Label>("title");
|
_titleLabel = this.Q<Label>("title");
|
||||||
_closeButton = this.Q<Button>("close-btn");
|
_closeButton = this.Q<UTKButton>("close-btn");
|
||||||
|
|
||||||
// 닫기 버튼 이벤트
|
// 닫기 버튼 설정 및 이벤트 연결
|
||||||
if (_closeButton != null)
|
if (_closeButton != null)
|
||||||
{
|
{
|
||||||
_closeButton.clicked += OnCloseButtonClicked;
|
_closeButton.SetMaterialIcon(UTKMaterialIcons.Close, 16);
|
||||||
|
_closeButton.OnClicked += OnCloseButtonClicked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,6 +446,24 @@ namespace UVC.UIToolkit
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 테마 (Theme)
|
||||||
|
|
||||||
|
private void SubscribeToThemeChanges()
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
|
||||||
|
RegisterCallback<DetachFromPanelEvent>(_ =>
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnThemeChanged(UTKTheme theme)
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -333,14 +471,18 @@ namespace UVC.UIToolkit
|
|||||||
if (_disposed) return;
|
if (_disposed) return;
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
|
// 테마 변경 이벤트 해제
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
|
||||||
// 내부 UTKAccordionList 정리
|
// 내부 UTKAccordionList 정리
|
||||||
_accordionList?.Dispose();
|
_accordionList?.Dispose();
|
||||||
_accordionList = null;
|
_accordionList = null;
|
||||||
|
|
||||||
// 닫기 버튼 이벤트 해제
|
// 닫기 버튼 이벤트 해제 및 정리
|
||||||
if (_closeButton != null)
|
if (_closeButton != null)
|
||||||
{
|
{
|
||||||
_closeButton.clicked -= OnCloseButtonClicked;
|
_closeButton.OnClicked -= OnCloseButtonClicked;
|
||||||
|
_closeButton.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 외부 이벤트 정리
|
// 외부 이벤트 정리
|
||||||
|
|||||||
@@ -14,17 +14,119 @@ namespace UVC.UIToolkit
|
|||||||
/// 윈도우 형태의 컴포넌트입니다. 모든 트리 관련 기능은 내부 UTKComponentList에 위임됩니다.
|
/// 윈도우 형태의 컴포넌트입니다. 모든 트리 관련 기능은 내부 UTKComponentList에 위임됩니다.
|
||||||
/// </para>
|
/// </para>
|
||||||
///
|
///
|
||||||
/// <para><b>UXML에서 사용:</b></para>
|
/// <para><b>UXML 사용 예시:</b></para>
|
||||||
/// <code>
|
/// <code><![CDATA[
|
||||||
/// <UVC.UIToolkit.Window.UTKComponentListWindow name="tree-list-window" />
|
/// <!-- UXML 파일에서 UTKComponentListWindow 사용 -->
|
||||||
/// </code>
|
/// <ui:UXML xmlns:utk="UVC.UIToolkit">
|
||||||
|
/// <utk:UTKComponentListWindow name="component-window" />
|
||||||
|
/// </ui:UXML>
|
||||||
|
/// ]]></code>
|
||||||
///
|
///
|
||||||
/// <para><b>코드에서 사용:</b></para>
|
/// <para><b>C# 사용 예시:</b></para>
|
||||||
/// <code>
|
/// <code><![CDATA[
|
||||||
/// var window = root.Q<UTKComponentListWindow>();
|
/// // 1. 윈도우 참조 획득
|
||||||
/// window.OnItemSelected += (items) => Debug.Log($"선택: {items[0].name}");
|
/// var componentWindow = root.Q<UTKComponentListWindow>("component-window");
|
||||||
/// window.SetData(treeItems);
|
///
|
||||||
/// </code>
|
/// // 2. 윈도우 제목 및 닫기 버튼 설정
|
||||||
|
/// componentWindow.Title = "모델 리스트";
|
||||||
|
/// componentWindow.ShowCloseButton = true;
|
||||||
|
///
|
||||||
|
/// // 3. 데이터 구성 - 카테고리와 아이템
|
||||||
|
/// var data = new List<UTKComponentListItemDataBase>
|
||||||
|
/// {
|
||||||
|
/// new UTKComponentListCategoryData
|
||||||
|
/// {
|
||||||
|
/// name = "캐릭터",
|
||||||
|
/// isExpanded = true,
|
||||||
|
/// children = new List<UTKComponentListItemDataBase>
|
||||||
|
/// {
|
||||||
|
/// new UTKComponentListItemData
|
||||||
|
/// {
|
||||||
|
/// name = "플레이어",
|
||||||
|
/// ExternalKey = "player_001",
|
||||||
|
/// IsVisible = true
|
||||||
|
/// },
|
||||||
|
/// new UTKComponentListItemData
|
||||||
|
/// {
|
||||||
|
/// name = "NPC",
|
||||||
|
/// ExternalKey = "npc_001",
|
||||||
|
/// IsVisible = true
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
/// componentWindow.SetData(data);
|
||||||
|
///
|
||||||
|
/// // 4. 선택 이벤트 구독
|
||||||
|
/// componentWindow.OnItemSelected = (selectedItems) =>
|
||||||
|
/// {
|
||||||
|
/// foreach (var item in selectedItems)
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"선택됨: {item.name}");
|
||||||
|
/// // 3D 뷰에서 해당 모델 하이라이트
|
||||||
|
/// HighlightModel(item.ExternalKey);
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 5. 선택 해제 이벤트
|
||||||
|
/// componentWindow.OnItemDeselected = (deselectedItems) =>
|
||||||
|
/// {
|
||||||
|
/// foreach (var item in deselectedItems)
|
||||||
|
/// {
|
||||||
|
/// UnhighlightModel(item.ExternalKey);
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 6. 가시성 변경 이벤트 (눈 아이콘)
|
||||||
|
/// componentWindow.OnItemVisibilityChanged += (item, isVisible) =>
|
||||||
|
/// {
|
||||||
|
/// var gameObject = FindGameObjectByKey(item.ExternalKey);
|
||||||
|
/// if (gameObject != null)
|
||||||
|
/// {
|
||||||
|
/// gameObject.SetActive(isVisible);
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 7. 삭제 이벤트 (Delete/Backspace 키)
|
||||||
|
/// componentWindow.EnabledDeleteItem = true;
|
||||||
|
/// componentWindow.OnItemDeleted = (item) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"삭제 요청: {item.name}");
|
||||||
|
/// componentWindow.DeleteItem(item);
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 8. 더블클릭 이벤트
|
||||||
|
/// componentWindow.OnItemDoubleClicked = (item) =>
|
||||||
|
/// {
|
||||||
|
/// // 카메라 포커스
|
||||||
|
/// FocusCameraOn(item.ExternalKey);
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 9. 윈도우 닫힘 이벤트
|
||||||
|
/// componentWindow.OnClosed += () =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log("윈도우가 닫혔습니다.");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 10. 프로그래밍 방식 선택
|
||||||
|
/// componentWindow.SelectItem("플레이어", notify: true);
|
||||||
|
/// componentWindow.DeselectItem("플레이어", notify: false);
|
||||||
|
/// componentWindow.ClearSelection();
|
||||||
|
/// componentWindow.SelectByItemId(itemId);
|
||||||
|
///
|
||||||
|
/// // 11. 아이템 추가/삭제
|
||||||
|
/// var newItem = new UTKComponentListItemData { name = "새 캐릭터" };
|
||||||
|
/// componentWindow.AddItem(newItem);
|
||||||
|
/// componentWindow.AddItem(categoryData, newItem);
|
||||||
|
/// componentWindow.DeleteItem(newItem);
|
||||||
|
/// componentWindow.SetItemName(newItem, "수정된 이름");
|
||||||
|
///
|
||||||
|
/// // 12. 윈도우 표시
|
||||||
|
/// componentWindow.Show();
|
||||||
|
///
|
||||||
|
/// // 13. 리소스 해제 (OnDestroy에서 호출)
|
||||||
|
/// componentWindow.Dispose();
|
||||||
|
/// ]]></code>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[UxmlElement]
|
[UxmlElement]
|
||||||
public partial class UTKComponentListWindow : VisualElement, IDisposable
|
public partial class UTKComponentListWindow : VisualElement, IDisposable
|
||||||
@@ -36,14 +138,20 @@ namespace UVC.UIToolkit
|
|||||||
#region 상수 (Constants)
|
#region 상수 (Constants)
|
||||||
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
||||||
private const string UXML_PATH = "UIToolkit/Window/UTKComponentListWindow";
|
private const string UXML_PATH = "UIToolkit/Window/UTKComponentListWindow";
|
||||||
|
|
||||||
|
/// <summary>USS 파일 경로 (Resources 폴더 기준)</summary>
|
||||||
|
private const string USS_PATH = "UIToolkit/Window/UTKComponentListWindowUss";
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region UI 컴포넌트 참조 (UI Component References)
|
#region UI 컴포넌트 참조 (UI Component References)
|
||||||
/// <summary>내부 UTKComponentList 컴포넌트</summary>
|
/// <summary>내부 UTKComponentList 컴포넌트</summary>
|
||||||
private UTKComponentList? _componentList;
|
private UTKComponentList? _componentList;
|
||||||
|
|
||||||
/// <summary>트리 리스트 닫기 버튼</summary>
|
/// <summary>트리 리스트 닫기 버튼 (UTKButton)</summary>
|
||||||
private Button? _closeButton;
|
private UTKButton? _closeButton;
|
||||||
|
|
||||||
|
/// <summary>윈도우 제목 라벨</summary>
|
||||||
|
private Label? _titleLabel;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 공개 속성 (Public Properties)
|
#region 공개 속성 (Public Properties)
|
||||||
@@ -57,6 +165,20 @@ namespace UVC.UIToolkit
|
|||||||
get => _componentList?.EnabledDeleteItem ?? false;
|
get => _componentList?.EnabledDeleteItem ?? false;
|
||||||
set { if (_componentList != null) _componentList.EnabledDeleteItem = value; }
|
set { if (_componentList != null) _componentList.EnabledDeleteItem = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>윈도우 제목을 가져오거나 설정합니다.</summary>
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get => _titleLabel?.text ?? string.Empty;
|
||||||
|
set { if (_titleLabel != null) _titleLabel.text = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>닫기 버튼 표시 여부를 설정합니다.</summary>
|
||||||
|
public bool ShowCloseButton
|
||||||
|
{
|
||||||
|
get => _closeButton?.style.display == DisplayStyle.Flex;
|
||||||
|
set { if (_closeButton != null) _closeButton.style.display = value ? DisplayStyle.Flex : DisplayStyle.None; }
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 외부 이벤트 (Public Events)
|
#region 외부 이벤트 (Public Events)
|
||||||
@@ -145,16 +267,34 @@ namespace UVC.UIToolkit
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 닫기 버튼 찾기 및 이벤트 연결
|
// 3. 테마 적용 및 변경 구독
|
||||||
_closeButton = this.Q<Button>("close-btn");
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
SubscribeToThemeChanges();
|
||||||
|
|
||||||
|
// USS 로드 (테마 변수 스타일시트 이후에 로드되어야 변수가 해석됨)
|
||||||
|
var uss = Resources.Load<StyleSheet>(USS_PATH);
|
||||||
|
if (uss != null)
|
||||||
|
{
|
||||||
|
styleSheets.Add(uss);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 헤더 요소 참조
|
||||||
|
_titleLabel = this.Q<Label>("title");
|
||||||
|
_closeButton = this.Q<UTKButton>("close-btn");
|
||||||
|
|
||||||
|
// 5. 닫기 버튼 설정 및 이벤트 연결
|
||||||
if (_closeButton != null)
|
if (_closeButton != null)
|
||||||
{
|
{
|
||||||
_closeButton.clicked += () =>
|
_closeButton.SetMaterialIcon(UTKMaterialIcons.Close, 16);
|
||||||
|
_closeButton.OnClicked += OnCloseButtonClicked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>닫기 버튼 클릭 이벤트 핸들러</summary>
|
||||||
|
private void OnCloseButtonClicked()
|
||||||
{
|
{
|
||||||
this.style.display = DisplayStyle.None;
|
this.style.display = DisplayStyle.None;
|
||||||
OnClosed?.Invoke();
|
OnClosed?.Invoke();
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -263,6 +403,24 @@ namespace UVC.UIToolkit
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 테마 (Theme)
|
||||||
|
|
||||||
|
private void SubscribeToThemeChanges()
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
|
||||||
|
RegisterCallback<DetachFromPanelEvent>(_ =>
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnThemeChanged(UTKTheme theme)
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 리소스를 해제하고 이벤트 핸들러를 정리합니다.
|
/// 리소스를 해제하고 이벤트 핸들러를 정리합니다.
|
||||||
@@ -272,15 +430,26 @@ namespace UVC.UIToolkit
|
|||||||
if (_disposed) return;
|
if (_disposed) return;
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
|
// 테마 변경 이벤트 해제
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
|
||||||
// 내부 UTKComponentList 정리
|
// 내부 UTKComponentList 정리
|
||||||
_componentList?.Dispose();
|
_componentList?.Dispose();
|
||||||
_componentList = null;
|
_componentList = null;
|
||||||
|
|
||||||
|
// 닫기 버튼 이벤트 해제 및 정리
|
||||||
|
if (_closeButton != null)
|
||||||
|
{
|
||||||
|
_closeButton.OnClicked -= OnCloseButtonClicked;
|
||||||
|
_closeButton.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// 외부 이벤트 구독자 정리
|
// 외부 이벤트 구독자 정리
|
||||||
OnClosed = null;
|
OnClosed = null;
|
||||||
|
|
||||||
// UI 참조 정리
|
// UI 참조 정리
|
||||||
_closeButton = null;
|
_closeButton = null;
|
||||||
|
_titleLabel = null;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,18 +15,132 @@ namespace UVC.UIToolkit
|
|||||||
/// 탭 버튼들을 추가한 윈도우 형태의 컴포넌트입니다. 탭을 통해 카테고리별 필터링이 가능합니다.
|
/// 탭 버튼들을 추가한 윈도우 형태의 컴포넌트입니다. 탭을 통해 카테고리별 필터링이 가능합니다.
|
||||||
/// </para>
|
/// </para>
|
||||||
///
|
///
|
||||||
/// <para><b>UXML에서 사용:</b></para>
|
/// <para><b>UXML 사용 예시:</b></para>
|
||||||
/// <code>
|
/// <code><![CDATA[
|
||||||
/// <UVC.UIToolkit.Window.UTKComponentTabListWindow name="tab-list-window" />
|
/// <!-- UXML 파일에서 UTKComponentTabListWindow 사용 -->
|
||||||
/// </code>
|
/// <ui:UXML xmlns:utk="UVC.UIToolkit">
|
||||||
|
/// <utk:UTKComponentTabListWindow name="tab-list-window" />
|
||||||
|
/// </ui:UXML>
|
||||||
|
/// ]]></code>
|
||||||
///
|
///
|
||||||
/// <para><b>코드에서 사용:</b></para>
|
/// <para><b>C# 사용 예시:</b></para>
|
||||||
/// <code>
|
/// <code><![CDATA[
|
||||||
/// var window = root.Q<UTKComponentTabListWindow>();
|
/// // 1. 윈도우 참조 획득
|
||||||
/// window.OnItemSelected += (items) => Debug.Log($"선택: {items[0].name}");
|
/// var tabWindow = root.Q<UTKComponentTabListWindow>("tab-list-window");
|
||||||
/// window.SetData(treeItems);
|
///
|
||||||
/// window.SelectTab(0); // 첫 번째 카테고리 탭 선택
|
/// // 2. 윈도우 제목 및 닫기 버튼 설정
|
||||||
/// </code>
|
/// tabWindow.Title = "에셋 라이브러리";
|
||||||
|
/// tabWindow.ShowCloseButton = true;
|
||||||
|
///
|
||||||
|
/// // 3. 데이터 구성 - 카테고리별로 자동 탭 생성됨
|
||||||
|
/// var data = new List<UTKComponentListItemDataBase>
|
||||||
|
/// {
|
||||||
|
/// // 첫 번째 카테고리 → "캐릭터" 탭 자동 생성
|
||||||
|
/// new UTKComponentListCategoryData
|
||||||
|
/// {
|
||||||
|
/// name = "캐릭터",
|
||||||
|
/// isExpanded = true,
|
||||||
|
/// children = new List<UTKComponentListItemDataBase>
|
||||||
|
/// {
|
||||||
|
/// new UTKComponentListItemData { name = "플레이어", ExternalKey = "player" },
|
||||||
|
/// new UTKComponentListItemData { name = "NPC", ExternalKey = "npc" }
|
||||||
|
/// }
|
||||||
|
/// },
|
||||||
|
/// // 두 번째 카테고리 → "오브젝트" 탭 자동 생성
|
||||||
|
/// new UTKComponentListCategoryData
|
||||||
|
/// {
|
||||||
|
/// name = "오브젝트",
|
||||||
|
/// isExpanded = true,
|
||||||
|
/// children = new List<UTKComponentListItemDataBase>
|
||||||
|
/// {
|
||||||
|
/// new UTKComponentListItemData { name = "상자", ExternalKey = "box" },
|
||||||
|
/// new UTKComponentListItemData { name = "나무", ExternalKey = "tree" }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
/// tabWindow.SetData(data);
|
||||||
|
/// // → "All" 탭과 "캐릭터", "오브젝트" 탭이 자동 생성됨
|
||||||
|
///
|
||||||
|
/// // 4. 탭 선택 (프로그래밍 방식)
|
||||||
|
/// tabWindow.SelectTab(-1); // -1 = "All" 전체 탭
|
||||||
|
/// tabWindow.SelectTab(0); // 0 = 첫 번째 카테고리 ("캐릭터")
|
||||||
|
/// tabWindow.SelectTab(1); // 1 = 두 번째 카테고리 ("오브젝트")
|
||||||
|
///
|
||||||
|
/// // 5. 선택 이벤트 구독
|
||||||
|
/// tabWindow.OnItemSelected = (selectedItems) =>
|
||||||
|
/// {
|
||||||
|
/// foreach (var item in selectedItems)
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"선택됨: {item.name}");
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 6. 선택 해제 이벤트
|
||||||
|
/// tabWindow.OnItemDeselected = (deselectedItems) =>
|
||||||
|
/// {
|
||||||
|
/// foreach (var item in deselectedItems)
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"선택 해제: {item.name}");
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 7. 가시성 변경 이벤트 (눈 아이콘)
|
||||||
|
/// tabWindow.OnItemVisibilityChanged += (item, isVisible) =>
|
||||||
|
/// {
|
||||||
|
/// var gameObject = FindGameObjectByKey(item.ExternalKey);
|
||||||
|
/// if (gameObject != null)
|
||||||
|
/// {
|
||||||
|
/// gameObject.SetActive(isVisible);
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 8. 삭제 이벤트 (Delete/Backspace 키)
|
||||||
|
/// tabWindow.EnabledDeleteItem = true;
|
||||||
|
/// tabWindow.OnItemDeleted = (item) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"삭제 요청: {item.name}");
|
||||||
|
/// tabWindow.DeleteItem(item); // 탭 목록도 자동 갱신됨
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 9. 더블클릭 이벤트
|
||||||
|
/// tabWindow.OnItemDoubleClicked = (item) =>
|
||||||
|
/// {
|
||||||
|
/// FocusCameraOn(item.ExternalKey);
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 10. 윈도우 닫힘 이벤트
|
||||||
|
/// tabWindow.OnClosed += () =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log("윈도우가 닫혔습니다.");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 11. 프로그래밍 방식 선택
|
||||||
|
/// tabWindow.SelectItem("플레이어", notify: true);
|
||||||
|
/// tabWindow.DeselectItem("플레이어", notify: false);
|
||||||
|
/// tabWindow.ClearSelection();
|
||||||
|
///
|
||||||
|
/// // 12. 아이템 추가/삭제 (탭 자동 갱신)
|
||||||
|
/// var newCategory = new UTKComponentListCategoryData { name = "이펙트" };
|
||||||
|
/// tabWindow.AddItem(newCategory); // "이펙트" 탭 자동 생성
|
||||||
|
///
|
||||||
|
/// var newItem = new UTKComponentListItemData { name = "폭발" };
|
||||||
|
/// tabWindow.AddItem(newCategory, newItem); // 카테고리에 아이템 추가
|
||||||
|
///
|
||||||
|
/// tabWindow.DeleteItem(newItem); // 아이템 삭제
|
||||||
|
///
|
||||||
|
/// // 13. 윈도우 표시
|
||||||
|
/// tabWindow.Show();
|
||||||
|
///
|
||||||
|
/// // 14. 리소스 해제 (OnDestroy에서 호출)
|
||||||
|
/// tabWindow.Dispose();
|
||||||
|
/// ]]></code>
|
||||||
|
///
|
||||||
|
/// <para><b>탭 동작 설명:</b></para>
|
||||||
|
/// <list type="bullet">
|
||||||
|
/// <item>"All" 탭: 모든 카테고리와 아이템을 표시합니다.</item>
|
||||||
|
/// <item>카테고리 탭: 해당 카테고리의 자식 아이템만 표시합니다 (부모 카테고리 없이).</item>
|
||||||
|
/// <item>탭별 검색어가 저장되어, 탭 전환 시 해당 탭의 검색어가 복원됩니다.</item>
|
||||||
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[UxmlElement]
|
[UxmlElement]
|
||||||
public partial class UTKComponentTabListWindow : VisualElement, IDisposable
|
public partial class UTKComponentTabListWindow : VisualElement, IDisposable
|
||||||
@@ -39,6 +153,9 @@ namespace UVC.UIToolkit
|
|||||||
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
||||||
private const string UXML_PATH = "UIToolkit/Window/UTKComponentTabListWindow";
|
private const string UXML_PATH = "UIToolkit/Window/UTKComponentTabListWindow";
|
||||||
|
|
||||||
|
/// <summary>USS 파일 경로 (Resources 폴더 기준)</summary>
|
||||||
|
private const string USS_PATH = "UIToolkit/Window/UTKComponentListWindowUss";
|
||||||
|
|
||||||
/// <summary>"전체" 탭을 나타내는 인덱스</summary>
|
/// <summary>"전체" 탭을 나타내는 인덱스</summary>
|
||||||
private const int ALL_TAB_INDEX = -1;
|
private const int ALL_TAB_INDEX = -1;
|
||||||
#endregion
|
#endregion
|
||||||
@@ -50,8 +167,11 @@ namespace UVC.UIToolkit
|
|||||||
/// <summary>탭 버튼 컨테이너</summary>
|
/// <summary>탭 버튼 컨테이너</summary>
|
||||||
private VisualElement? _tabContainer;
|
private VisualElement? _tabContainer;
|
||||||
|
|
||||||
/// <summary>트리 리스트 닫기 버튼</summary>
|
/// <summary>트리 리스트 닫기 버튼 (UTKButton)</summary>
|
||||||
private Button? _closeButton;
|
private UTKButton? _closeButton;
|
||||||
|
|
||||||
|
/// <summary>윈도우 제목 라벨</summary>
|
||||||
|
private Label? _titleLabel;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 탭 관련 데이터 (Tab Data)
|
#region 탭 관련 데이터 (Tab Data)
|
||||||
@@ -79,6 +199,20 @@ namespace UVC.UIToolkit
|
|||||||
get => _componentList?.EnabledDeleteItem ?? false;
|
get => _componentList?.EnabledDeleteItem ?? false;
|
||||||
set { if (_componentList != null) _componentList.EnabledDeleteItem = value; }
|
set { if (_componentList != null) _componentList.EnabledDeleteItem = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>윈도우 제목을 가져오거나 설정합니다.</summary>
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get => _titleLabel?.text ?? string.Empty;
|
||||||
|
set { if (_titleLabel != null) _titleLabel.text = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>닫기 버튼 표시 여부를 설정합니다.</summary>
|
||||||
|
public bool ShowCloseButton
|
||||||
|
{
|
||||||
|
get => _closeButton?.style.display == DisplayStyle.Flex;
|
||||||
|
set { if (_closeButton != null) _closeButton.style.display = value ? DisplayStyle.Flex : DisplayStyle.None; }
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 외부 이벤트 (Public Events)
|
#region 외부 이벤트 (Public Events)
|
||||||
@@ -167,19 +301,37 @@ namespace UVC.UIToolkit
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 탭 관련 요소 찾기
|
// 3. 테마 적용 및 변경 구독
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
SubscribeToThemeChanges();
|
||||||
|
|
||||||
|
// USS 로드 (테마 변수 스타일시트 이후에 로드되어야 변수가 해석됨)
|
||||||
|
var uss = Resources.Load<StyleSheet>(USS_PATH);
|
||||||
|
if (uss != null)
|
||||||
|
{
|
||||||
|
styleSheets.Add(uss);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 탭 관련 요소 찾기
|
||||||
_tabContainer = this.Q<VisualElement>("tab-container");
|
_tabContainer = this.Q<VisualElement>("tab-container");
|
||||||
|
|
||||||
// 4. 닫기 버튼 찾기 및 이벤트 연결
|
// 5. 헤더 요소 참조
|
||||||
_closeButton = this.Q<Button>("close-btn");
|
_titleLabel = this.Q<Label>("title");
|
||||||
|
_closeButton = this.Q<UTKButton>("close-btn");
|
||||||
|
|
||||||
|
// 6. 닫기 버튼 설정 및 이벤트 연결
|
||||||
if (_closeButton != null)
|
if (_closeButton != null)
|
||||||
{
|
{
|
||||||
_closeButton.clicked += () =>
|
_closeButton.SetMaterialIcon(UTKMaterialIcons.Close, 16);
|
||||||
|
_closeButton.OnClicked += OnCloseButtonClicked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>닫기 버튼 클릭 이벤트 핸들러</summary>
|
||||||
|
private void OnCloseButtonClicked()
|
||||||
{
|
{
|
||||||
this.style.display = DisplayStyle.None;
|
this.style.display = DisplayStyle.None;
|
||||||
OnClosed?.Invoke();
|
OnClosed?.Invoke();
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -507,6 +659,24 @@ namespace UVC.UIToolkit
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 테마 (Theme)
|
||||||
|
|
||||||
|
private void SubscribeToThemeChanges()
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
|
||||||
|
RegisterCallback<DetachFromPanelEvent>(_ =>
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnThemeChanged(UTKTheme theme)
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 리소스를 해제하고 이벤트 핸들러를 정리합니다.
|
/// 리소스를 해제하고 이벤트 핸들러를 정리합니다.
|
||||||
@@ -516,6 +686,9 @@ namespace UVC.UIToolkit
|
|||||||
if (_disposed) return;
|
if (_disposed) return;
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
|
// 테마 변경 이벤트 해제
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
|
||||||
// 내부 UTKComponentList 정리
|
// 내부 UTKComponentList 정리
|
||||||
_componentList?.Dispose();
|
_componentList?.Dispose();
|
||||||
_componentList = null;
|
_componentList = null;
|
||||||
@@ -524,6 +697,13 @@ namespace UVC.UIToolkit
|
|||||||
_tabButtons.Clear();
|
_tabButtons.Clear();
|
||||||
_tabContainer = null;
|
_tabContainer = null;
|
||||||
|
|
||||||
|
// 닫기 버튼 이벤트 해제 및 정리
|
||||||
|
if (_closeButton != null)
|
||||||
|
{
|
||||||
|
_closeButton.OnClicked -= OnCloseButtonClicked;
|
||||||
|
_closeButton.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// 외부 이벤트 구독자 정리
|
// 외부 이벤트 구독자 정리
|
||||||
OnClosed = null;
|
OnClosed = null;
|
||||||
|
|
||||||
@@ -533,6 +713,7 @@ namespace UVC.UIToolkit
|
|||||||
|
|
||||||
// UI 참조 정리
|
// UI 참조 정리
|
||||||
_closeButton = null;
|
_closeButton = null;
|
||||||
|
_titleLabel = null;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,17 +22,116 @@ namespace UVC.UIToolkit
|
|||||||
/// <item>드래그 앤 드롭 이벤트 전달</item>
|
/// <item>드래그 앤 드롭 이벤트 전달</item>
|
||||||
/// </list>
|
/// </list>
|
||||||
///
|
///
|
||||||
/// <para><b>UXML에서 사용:</b></para>
|
/// <para><b>UXML 사용 예시:</b></para>
|
||||||
/// <code>
|
/// <code><![CDATA[
|
||||||
/// <uvc:UTKImageListWindow name="library-window" />
|
/// <!-- UXML 파일에서 UTKImageListWindow 사용 -->
|
||||||
/// </code>
|
/// <ui:UXML xmlns:utk="UVC.UIToolkit">
|
||||||
|
/// <utk:UTKImageListWindow name="library-window" />
|
||||||
|
/// </ui:UXML>
|
||||||
|
/// ]]></code>
|
||||||
///
|
///
|
||||||
/// <para><b>코드에서 사용:</b></para>
|
/// <para><b>C# 사용 예시:</b></para>
|
||||||
/// <code>
|
/// <code><![CDATA[
|
||||||
/// var window = root.Q<UTKImageListWindow>();
|
/// // 1. 윈도우 참조 획득
|
||||||
/// window.OnItemClick += (item) => Debug.Log($"클릭: {item.itemName}");
|
/// var imageWindow = root.Q<UTKImageListWindow>("library-window");
|
||||||
/// window.SetData(imageItems);
|
///
|
||||||
/// </code>
|
/// // 2. 윈도우 제목 및 닫기 버튼 설정
|
||||||
|
/// imageWindow.Title = "프리팹 라이브러리";
|
||||||
|
/// imageWindow.ShowCloseButton = true;
|
||||||
|
///
|
||||||
|
/// // 3. 데이터 구성 - 이미지와 이름을 가진 아이템들
|
||||||
|
/// var data = new List<UTKImageListItemData>
|
||||||
|
/// {
|
||||||
|
/// new UTKImageListItemData
|
||||||
|
/// {
|
||||||
|
/// itemName = "의자",
|
||||||
|
/// imagePath = "Prefabs/Thumbnails/chair",
|
||||||
|
/// prefabPath = "Prefabs/Furniture/Chair"
|
||||||
|
/// },
|
||||||
|
/// new UTKImageListItemData
|
||||||
|
/// {
|
||||||
|
/// itemName = "책상",
|
||||||
|
/// imagePath = "Prefabs/Thumbnails/desk",
|
||||||
|
/// prefabPath = "Prefabs/Furniture/Desk"
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
/// imageWindow.SetData(data);
|
||||||
|
///
|
||||||
|
/// // 4. 아이템 클릭 이벤트 구독
|
||||||
|
/// imageWindow.OnItemClick = (item) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"클릭된 아이템: {item.itemName}");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 5. 드래그 시작 이벤트
|
||||||
|
/// imageWindow.OnItemBeginDrag = (item, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"드래그 시작: {item.itemName}");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 6. 드래그 중 이벤트
|
||||||
|
/// imageWindow.OnItemDrag = (item, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// // 드래그 중 위치 업데이트
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 7. 드래그 종료 이벤트
|
||||||
|
/// imageWindow.OnItemEndDrag = (item, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"드래그 종료: {item.itemName}");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 8. 드롭 이벤트 (프리팹 인스턴스화)
|
||||||
|
/// imageWindow.OnItemDrop = (item) =>
|
||||||
|
/// {
|
||||||
|
/// if (!string.IsNullOrEmpty(item.prefabPath))
|
||||||
|
/// {
|
||||||
|
/// var prefab = Resources.Load<GameObject>(item.prefabPath);
|
||||||
|
/// Instantiate(prefab, dropPosition, Quaternion.identity);
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 9. 리스트 영역 밖으로 드래그 시 3D 미리보기 표시
|
||||||
|
/// imageWindow.OnDragExitList = (item, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// // 리스트 밖 = 3D 씬 영역
|
||||||
|
/// Show3DPreview(item.prefabPath, screenPos);
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 10. 리스트 영역으로 다시 들어오면 미리보기 숨김
|
||||||
|
/// imageWindow.OnDragEnterList = (item, screenPos) =>
|
||||||
|
/// {
|
||||||
|
/// Hide3DPreview();
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 11. 윈도우 닫힘 이벤트
|
||||||
|
/// imageWindow.OnClosed += () =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log("윈도우가 닫혔습니다.");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 12. 드래그 고스트 이미지 설정
|
||||||
|
/// imageWindow.DragImageFollowCursor = true;
|
||||||
|
///
|
||||||
|
/// // 13. 검색 실행
|
||||||
|
/// imageWindow.ApplySearch("의자");
|
||||||
|
///
|
||||||
|
/// // 14. 아이템 추가/제거
|
||||||
|
/// var newItem = new UTKImageListItemData { itemName = "새 아이템" };
|
||||||
|
/// imageWindow.AddItem(newItem);
|
||||||
|
/// imageWindow.RemoveItem(newItem);
|
||||||
|
/// imageWindow.Clear();
|
||||||
|
///
|
||||||
|
/// // 15. 아이템 개수 확인
|
||||||
|
/// int count = imageWindow.ItemCount;
|
||||||
|
///
|
||||||
|
/// // 16. 윈도우 표시/닫기
|
||||||
|
/// imageWindow.Show();
|
||||||
|
/// imageWindow.Close();
|
||||||
|
///
|
||||||
|
/// // 17. 리소스 해제 (OnDestroy에서 호출)
|
||||||
|
/// imageWindow.Dispose();
|
||||||
|
/// ]]></code>
|
||||||
///
|
///
|
||||||
/// <para><b>관련 리소스:</b></para>
|
/// <para><b>관련 리소스:</b></para>
|
||||||
/// <list type="bullet">
|
/// <list type="bullet">
|
||||||
@@ -48,6 +147,9 @@ namespace UVC.UIToolkit
|
|||||||
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
||||||
private const string UXML_PATH = "UIToolkit/Window/UTKImageListWindow";
|
private const string UXML_PATH = "UIToolkit/Window/UTKImageListWindow";
|
||||||
|
|
||||||
|
/// <summary>USS 파일 경로 (Resources 폴더 기준)</summary>
|
||||||
|
private const string USS_PATH = "UIToolkit/Window/UTKImageListWindowUss";
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region UI 컴포넌트 참조 (UI Component References)
|
#region UI 컴포넌트 참조 (UI Component References)
|
||||||
@@ -55,8 +157,8 @@ namespace UVC.UIToolkit
|
|||||||
/// <summary>내부 UTKImageList 컴포넌트</summary>
|
/// <summary>내부 UTKImageList 컴포넌트</summary>
|
||||||
private UTKImageList? _imageList;
|
private UTKImageList? _imageList;
|
||||||
|
|
||||||
/// <summary>윈도우 닫기 버튼</summary>
|
/// <summary>윈도우 닫기 버튼 (UTKButton)</summary>
|
||||||
private Button? _closeButton;
|
private UTKButton? _closeButton;
|
||||||
|
|
||||||
/// <summary>윈도우 제목 라벨</summary>
|
/// <summary>윈도우 제목 라벨</summary>
|
||||||
private Label? _titleLabel;
|
private Label? _titleLabel;
|
||||||
@@ -214,7 +316,18 @@ namespace UVC.UIToolkit
|
|||||||
}
|
}
|
||||||
visualTree.CloneTree(this);
|
visualTree.CloneTree(this);
|
||||||
|
|
||||||
// 2. 내부 UTKImageList 찾기 (UXML에서 생성된 컴포넌트)
|
// 2. 테마 적용 및 변경 구독
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
SubscribeToThemeChanges();
|
||||||
|
|
||||||
|
// USS 로드 (테마 변수 스타일시트 이후에 로드되어야 변수가 해석됨)
|
||||||
|
var uss = Resources.Load<StyleSheet>(USS_PATH);
|
||||||
|
if (uss != null)
|
||||||
|
{
|
||||||
|
styleSheets.Add(uss);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 내부 UTKImageList 찾기 (UXML에서 생성된 컴포넌트)
|
||||||
_imageList = this.Q<UTKImageList>();
|
_imageList = this.Q<UTKImageList>();
|
||||||
if (_imageList == null)
|
if (_imageList == null)
|
||||||
{
|
{
|
||||||
@@ -226,14 +339,15 @@ namespace UVC.UIToolkit
|
|||||||
_imageList.DragBoundsElement = this;
|
_imageList.DragBoundsElement = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 헤더 요소 참조
|
// 4. 헤더 요소 참조
|
||||||
_titleLabel = this.Q<Label>("title");
|
_titleLabel = this.Q<Label>("title");
|
||||||
_closeButton = this.Q<Button>("close-btn");
|
_closeButton = this.Q<UTKButton>("close-btn");
|
||||||
|
|
||||||
// 4. 닫기 버튼 이벤트 연결
|
// 5. 닫기 버튼 설정 및 이벤트 연결
|
||||||
if (_closeButton != null)
|
if (_closeButton != null)
|
||||||
{
|
{
|
||||||
_closeButton.clicked += OnCloseButtonClicked;
|
_closeButton.SetMaterialIcon(UTKMaterialIcons.Close, 16);
|
||||||
|
_closeButton.OnClicked += OnCloseButtonClicked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,6 +434,24 @@ namespace UVC.UIToolkit
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 테마 (Theme)
|
||||||
|
|
||||||
|
private void SubscribeToThemeChanges()
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
|
||||||
|
RegisterCallback<DetachFromPanelEvent>(_ =>
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnThemeChanged(UTKTheme theme)
|
||||||
|
{
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -330,14 +462,18 @@ namespace UVC.UIToolkit
|
|||||||
if (_disposed) return;
|
if (_disposed) return;
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
|
// 테마 변경 이벤트 해제
|
||||||
|
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
|
||||||
|
|
||||||
// 내부 UTKImageList 정리
|
// 내부 UTKImageList 정리
|
||||||
_imageList?.Dispose();
|
_imageList?.Dispose();
|
||||||
_imageList = null;
|
_imageList = null;
|
||||||
|
|
||||||
// 닫기 버튼 이벤트 해제
|
// 닫기 버튼 이벤트 해제 및 정리
|
||||||
if (_closeButton != null)
|
if (_closeButton != null)
|
||||||
{
|
{
|
||||||
_closeButton.clicked -= OnCloseButtonClicked;
|
_closeButton.OnClicked -= OnCloseButtonClicked;
|
||||||
|
_closeButton.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 외부 이벤트 구독자 정리
|
// 외부 이벤트 구독자 정리
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ namespace UVC.UIToolkit
|
|||||||
///
|
///
|
||||||
/// <para><b>개요:</b></para>
|
/// <para><b>개요:</b></para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// TreeListWindow는 Unity UI Toolkit의 TreeView를 래핑하여 검색, 가시성 토글,
|
/// UTKTreeListWindow는 Unity UI Toolkit의 TreeView를 래핑하여 검색, 가시성 토글,
|
||||||
/// 닫기 기능 등을 제공하는 재사용 가능한 컴포넌트입니다.
|
/// 닫기 기능 등을 제공하는 재사용 가능한 컴포넌트입니다.
|
||||||
/// UXML 파일(TreeListWindow.uxml, TreeListItem.uxml)과 함께 사용됩니다.
|
/// UXML 파일(UTKTreeListWindow.uxml, UTKTreeListItem.uxml)과 함께 사용됩니다.
|
||||||
/// </para>
|
/// </para>
|
||||||
///
|
///
|
||||||
/// <para><b>주요 기능:</b></para>
|
/// <para><b>주요 기능:</b></para>
|
||||||
@@ -23,21 +23,116 @@ namespace UVC.UIToolkit
|
|||||||
/// <item>계층적 트리 구조 표시 (펼치기/접기 지원)</item>
|
/// <item>계층적 트리 구조 표시 (펼치기/접기 지원)</item>
|
||||||
/// <item>실시간 검색 필터링</item>
|
/// <item>실시간 검색 필터링</item>
|
||||||
/// <item>항목별 가시성(눈 아이콘) 토글</item>
|
/// <item>항목별 가시성(눈 아이콘) 토글</item>
|
||||||
/// <item>선택 이벤트 처리</item>
|
/// <item>다중 선택 지원</item>
|
||||||
|
/// <item>삭제 기능 (Delete/Backspace 키)</item>
|
||||||
/// </list>
|
/// </list>
|
||||||
///
|
///
|
||||||
/// <para><b>UXML에서 사용:</b></para>
|
/// <para><b>UXML 사용 예시:</b></para>
|
||||||
/// <code>
|
/// <code><![CDATA[
|
||||||
/// <UVC.UIToolkit.Window.UTKTreeListWindow name="tree-list" />
|
/// <!-- UXML 파일에서 UTKTreeListWindow 사용 -->
|
||||||
/// </code>
|
/// <ui:UXML xmlns:utk="UVC.UIToolkit">
|
||||||
|
/// <utk:UTKTreeListWindow name="tree-list-window" />
|
||||||
|
/// </ui:UXML>
|
||||||
|
/// ]]></code>
|
||||||
///
|
///
|
||||||
/// <para><b>코드에서 사용:</b></para>
|
/// <para><b>C# 사용 예시:</b></para>
|
||||||
/// <code>
|
/// <code><![CDATA[
|
||||||
/// var treeList = root.Q<UTKTreeListWindow>();
|
/// // 1. 윈도우 참조 획득
|
||||||
/// treeList.OnSelectionChanged += (item) => Debug.Log($"선택: {item.name}");
|
/// var treeWindow = root.Q<UTKTreeListWindow>("tree-list-window");
|
||||||
/// treeList.OnVisibilityChanged += (item) => model.SetActive(item.id, item.IsVisible);
|
///
|
||||||
/// treeList.SetData(treeItems);
|
/// // 2. 윈도우 제목 및 닫기 버튼 설정
|
||||||
/// </code>
|
/// treeWindow.Title = "씬 계층구조";
|
||||||
|
/// treeWindow.ShowCloseButton = true;
|
||||||
|
///
|
||||||
|
/// // 3. 데이터 구성 - 계층적 트리 구조
|
||||||
|
/// var data = new List<UTKTreeListItemData>
|
||||||
|
/// {
|
||||||
|
/// new UTKTreeListItemData
|
||||||
|
/// {
|
||||||
|
/// name = "루트 오브젝트",
|
||||||
|
/// isExpanded = true,
|
||||||
|
/// IsVisible = true,
|
||||||
|
/// children = new List<UTKTreeListItemData>
|
||||||
|
/// {
|
||||||
|
/// new UTKTreeListItemData
|
||||||
|
/// {
|
||||||
|
/// name = "자식 오브젝트 1",
|
||||||
|
/// IsVisible = true
|
||||||
|
/// },
|
||||||
|
/// new UTKTreeListItemData
|
||||||
|
/// {
|
||||||
|
/// name = "자식 오브젝트 2",
|
||||||
|
/// IsVisible = false,
|
||||||
|
/// children = new List<UTKTreeListItemData>
|
||||||
|
/// {
|
||||||
|
/// new UTKTreeListItemData { name = "손자 오브젝트" }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
/// treeWindow.SetData(data);
|
||||||
|
///
|
||||||
|
/// // 4. 선택 변경 이벤트 구독 (선택 및 해제 모두)
|
||||||
|
/// treeWindow.OnSelectionChanged += (selectedItems) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"선택된 아이템 수: {selectedItems.Count}");
|
||||||
|
/// foreach (var item in selectedItems)
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"선택: {item.name}");
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 5. 가시성 변경 이벤트 (눈 아이콘 클릭)
|
||||||
|
/// treeWindow.OnVisibilityChanged += (item) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"{item.name} 가시성: {item.IsVisible}");
|
||||||
|
/// // 3D 씬에서 해당 오브젝트 활성화/비활성화
|
||||||
|
/// var gameObject = FindGameObjectByName(item.name);
|
||||||
|
/// if (gameObject != null)
|
||||||
|
/// {
|
||||||
|
/// gameObject.SetActive(item.IsVisible);
|
||||||
|
/// }
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 6. 삭제 이벤트 (Delete/Backspace 키)
|
||||||
|
/// treeWindow.EnabledDeleteItem = true;
|
||||||
|
/// treeWindow.OnItemDeleted += (item) =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log($"삭제 요청: {item.name}");
|
||||||
|
/// // 데이터에서 제거 후 UI 갱신
|
||||||
|
/// RemoveFromData(item);
|
||||||
|
/// treeWindow.Rebuild();
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 7. 윈도우 닫힘 이벤트
|
||||||
|
/// treeWindow.OnClosed += () =>
|
||||||
|
/// {
|
||||||
|
/// Debug.Log("윈도우가 닫혔습니다.");
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // 8. 검색 실행
|
||||||
|
/// treeWindow.ApplySearch("자식");
|
||||||
|
/// // 검색어는 SearchQuery 속성으로 확인 가능
|
||||||
|
/// string currentQuery = treeWindow.SearchQuery;
|
||||||
|
///
|
||||||
|
/// // 9. 프로그래밍 방식 선택
|
||||||
|
/// treeWindow.SelectByItemId(itemId);
|
||||||
|
///
|
||||||
|
/// // 10. 전체 펼치기/접기
|
||||||
|
/// treeWindow.ExpandAll();
|
||||||
|
/// treeWindow.CollapseAll();
|
||||||
|
///
|
||||||
|
/// // 11. TreeView 갱신 (데이터 변경 후)
|
||||||
|
/// treeWindow.Rebuild();
|
||||||
|
///
|
||||||
|
/// // 12. 윈도우 표시/숨김
|
||||||
|
/// treeWindow.Show();
|
||||||
|
/// treeWindow.Hide();
|
||||||
|
///
|
||||||
|
/// // 13. 리소스 해제 (OnDestroy에서 호출)
|
||||||
|
/// treeWindow.Dispose();
|
||||||
|
/// ]]></code>
|
||||||
///
|
///
|
||||||
/// <para><b>관련 리소스:</b></para>
|
/// <para><b>관련 리소스:</b></para>
|
||||||
/// <list type="bullet">
|
/// <list type="bullet">
|
||||||
@@ -61,6 +156,8 @@ namespace UVC.UIToolkit
|
|||||||
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
/// <summary>메인 UXML 파일 경로 (Resources 폴더 기준)</summary>
|
||||||
private const string UXML_PATH = "UIToolkit/Window/UTKTreeListWindow";
|
private const string UXML_PATH = "UIToolkit/Window/UTKTreeListWindow";
|
||||||
|
|
||||||
|
/// <summary>USS 파일 경로 (Resources 폴더 기준)</summary>
|
||||||
|
private const string USS_PATH = "UIToolkit/Window/UTKTreeListWindowUss";
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region UI 컴포넌트 참조 (UI Component References)
|
#region UI 컴포넌트 참조 (UI Component References)
|
||||||
@@ -70,11 +167,14 @@ namespace UVC.UIToolkit
|
|||||||
/// <summary>Unity UI Toolkit의 TreeView 컴포넌트</summary>
|
/// <summary>Unity UI Toolkit의 TreeView 컴포넌트</summary>
|
||||||
private TreeView? _treeView;
|
private TreeView? _treeView;
|
||||||
|
|
||||||
/// <summary>트리 리스트 닫기 버튼</summary>
|
/// <summary>트리 리스트 닫기 버튼 (UTKButton)</summary>
|
||||||
private Button? _closeButton;
|
private UTKButton? _closeButton;
|
||||||
|
|
||||||
/// <summary>검색어 지우기 버튼</summary>
|
/// <summary>검색어 지우기 버튼 (UTKButton)</summary>
|
||||||
private Button? _clearButton;
|
private UTKButton? _clearButton;
|
||||||
|
|
||||||
|
/// <summary>윈도우 제목 라벨</summary>
|
||||||
|
private Label? _titleLabel;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 내부 데이터 (Internal Data)
|
#region 내부 데이터 (Internal Data)
|
||||||
@@ -124,6 +224,20 @@ namespace UVC.UIToolkit
|
|||||||
/// 기본값은 true입니다.
|
/// 기본값은 true입니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnabledDeleteItem { get; set; } = true;
|
public bool EnabledDeleteItem { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>윈도우 제목</summary>
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get => _titleLabel?.text ?? string.Empty;
|
||||||
|
set { if (_titleLabel != null) _titleLabel.text = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>닫기 버튼 표시 여부</summary>
|
||||||
|
public bool ShowCloseButton
|
||||||
|
{
|
||||||
|
get => _closeButton?.style.display == DisplayStyle.Flex;
|
||||||
|
set { if (_closeButton != null) _closeButton.style.display = value ? DisplayStyle.Flex : DisplayStyle.None; }
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 외부 이벤트 (Public Events)
|
#region 외부 이벤트 (Public Events)
|
||||||
@@ -177,14 +291,36 @@ namespace UVC.UIToolkit
|
|||||||
}
|
}
|
||||||
visualTree!.CloneTree(this);
|
visualTree!.CloneTree(this);
|
||||||
|
|
||||||
|
// 2. 테마 적용
|
||||||
|
UTKThemeManager.Instance.ApplyThemeToElement(this);
|
||||||
|
|
||||||
// 2. 자식 요소 참조 획득 (UXML의 name 속성으로 찾음)
|
// USS 로드 (테마 변수 스타일시트 이후에 로드되어야 변수가 해석됨)
|
||||||
|
var uss = Resources.Load<StyleSheet>(USS_PATH);
|
||||||
|
if (uss != null)
|
||||||
|
{
|
||||||
|
styleSheets.Add(uss);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 자식 요소 참조 획득 (UXML의 name 속성으로 찾음)
|
||||||
_searchField = this.Q<TextField>("search-field");
|
_searchField = this.Q<TextField>("search-field");
|
||||||
_treeView = this.Q<TreeView>("main-tree-view");
|
_treeView = this.Q<TreeView>("main-tree-view");
|
||||||
_closeButton = this.Q<Button>("close-btn");
|
_titleLabel = this.Q<Label>("title");
|
||||||
_clearButton = this.Q<Button>("clear-btn");
|
_closeButton = this.Q<UTKButton>("close-btn");
|
||||||
|
_clearButton = this.Q<UTKButton>("clear-btn");
|
||||||
|
|
||||||
// 3. 이벤트 연결 및 로직 초기화
|
// 4. 닫기 버튼 아이콘 설정
|
||||||
|
if (_closeButton != null)
|
||||||
|
{
|
||||||
|
_closeButton.SetMaterialIcon(UTKMaterialIcons.Close, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Clear 버튼 아이콘 설정
|
||||||
|
if (_clearButton != null)
|
||||||
|
{
|
||||||
|
_clearButton.SetMaterialIcon(UTKMaterialIcons.Close, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 이벤트 연결 및 로직 초기화
|
||||||
InitializeLogic();
|
InitializeLogic();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -218,26 +354,14 @@ namespace UVC.UIToolkit
|
|||||||
// 닫기 버튼: 트리 리스트를 숨기고 이벤트 발생
|
// 닫기 버튼: 트리 리스트를 숨기고 이벤트 발생
|
||||||
if (_closeButton != null)
|
if (_closeButton != null)
|
||||||
{
|
{
|
||||||
_closeButton.clicked += () =>
|
_closeButton.OnClicked += OnCloseButtonClicked;
|
||||||
{
|
|
||||||
this.style.display = DisplayStyle.None;
|
|
||||||
OnClosed?.Invoke();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 검색어 지우기 버튼
|
// 검색어 지우기 버튼
|
||||||
if(_clearButton != null)
|
if(_clearButton != null)
|
||||||
{
|
{
|
||||||
_clearButton.style.display = DisplayStyle.None; // 초기에는 숨김
|
_clearButton.style.display = DisplayStyle.None; // 초기에는 숨김
|
||||||
_clearButton.clicked += () =>
|
_clearButton.OnClicked += OnClearButtonClicked;
|
||||||
{
|
|
||||||
if (_searchField.value.Length > 0)
|
|
||||||
{
|
|
||||||
_searchField.value = string.Empty;
|
|
||||||
OnSearch(string.Empty);
|
|
||||||
}
|
|
||||||
_clearButton.style.display = DisplayStyle.None; // 클리어 후 숨김
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 스크롤바 hover/active 색상 설정
|
// 스크롤바 hover/active 색상 설정
|
||||||
@@ -1095,6 +1219,33 @@ namespace UVC.UIToolkit
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 버튼 이벤트 핸들러 (Button Event Handlers)
|
||||||
|
/// <summary>
|
||||||
|
/// 닫기 버튼 클릭 이벤트를 처리합니다.
|
||||||
|
/// </summary>
|
||||||
|
private void OnCloseButtonClicked()
|
||||||
|
{
|
||||||
|
this.style.display = DisplayStyle.None;
|
||||||
|
OnClosed?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clear 버튼 클릭 이벤트를 처리합니다.
|
||||||
|
/// </summary>
|
||||||
|
private void OnClearButtonClicked()
|
||||||
|
{
|
||||||
|
if (_searchField != null && _searchField.value.Length > 0)
|
||||||
|
{
|
||||||
|
_searchField.value = string.Empty;
|
||||||
|
OnSearch(string.Empty);
|
||||||
|
}
|
||||||
|
if (_clearButton != null)
|
||||||
|
{
|
||||||
|
_clearButton.style.display = DisplayStyle.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region 검색 기능 (Search Functionality)
|
#region 검색 기능 (Search Functionality)
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 검색 필드에서 Enter 키를 눌렀을 때 검색을 실행합니다.
|
/// 검색 필드에서 Enter 키를 눌렀을 때 검색을 실행합니다.
|
||||||
@@ -1270,6 +1421,20 @@ namespace UVC.UIToolkit
|
|||||||
_treeView.makeItem = null;
|
_treeView.makeItem = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 닫기 버튼 이벤트 해제 및 정리
|
||||||
|
if (_closeButton != null)
|
||||||
|
{
|
||||||
|
_closeButton.OnClicked -= OnCloseButtonClicked;
|
||||||
|
_closeButton.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear 버튼 이벤트 해제 및 정리
|
||||||
|
if (_clearButton != null)
|
||||||
|
{
|
||||||
|
_clearButton.OnClicked -= OnClearButtonClicked;
|
||||||
|
_clearButton.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// 외부 이벤트 구독자 정리
|
// 외부 이벤트 구독자 정리
|
||||||
OnItemVisibilityChanged = null;
|
OnItemVisibilityChanged = null;
|
||||||
OnClosed = null;
|
OnClosed = null;
|
||||||
@@ -1290,6 +1455,7 @@ namespace UVC.UIToolkit
|
|||||||
// UI 참조 정리
|
// UI 참조 정리
|
||||||
_searchField = null;
|
_searchField = null;
|
||||||
_treeView = null;
|
_treeView = null;
|
||||||
|
_titleLabel = null;
|
||||||
_closeButton = null;
|
_closeButton = null;
|
||||||
_clearButton = null;
|
_clearButton = null;
|
||||||
}
|
}
|
||||||
|
|||||||
29
CLAUDE.md
29
CLAUDE.md
@@ -227,6 +227,35 @@ public struct AssetRef<T> where T : UnityEngine.Object
|
|||||||
- `LoadAssetAsync` 핸들은 수명 관리 후 `Release`
|
- `LoadAssetAsync` 핸들은 수명 관리 후 `Release`
|
||||||
- GameObject 직접 참조 대신 경로 문자열 직렬화
|
- GameObject 직접 참조 대신 경로 문자열 직렬화
|
||||||
|
|
||||||
|
### UXML/USS 파일 네이밍 규칙
|
||||||
|
|
||||||
|
**⚠️ 중요: UXML과 USS 파일명은 반드시 다르게 지정해야 합니다.**
|
||||||
|
|
||||||
|
`Resources.Load<T>(path)`는 확장자 없이 경로를 받기 때문에, 동일한 경로에 UXML과 USS가 모두 존재하면 로드 충돌이 발생할 수 있습니다.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// ❌ 잘못된 예: 동일한 경로명 사용
|
||||||
|
private const string UXML_PATH = "UIToolkit/Window/UTKAccordionListWindow";
|
||||||
|
private const string USS_PATH = "UIToolkit/Window/UTKAccordionListWindow";
|
||||||
|
|
||||||
|
// Resources.Load<VisualTreeAsset>(UXML_PATH); // .uxml 로드
|
||||||
|
// Resources.Load<StyleSheet>(USS_PATH); // .uss 로드 실패 가능
|
||||||
|
|
||||||
|
// ✅ 올바른 예: USS 파일명에 접미사 추가
|
||||||
|
private const string UXML_PATH = "UIToolkit/Window/UTKAccordionListWindow";
|
||||||
|
private const string USS_PATH = "UIToolkit/Window/UTKAccordionListWindowUss";
|
||||||
|
|
||||||
|
// 파일 구조:
|
||||||
|
// - UTKAccordionListWindow.uxml
|
||||||
|
// - UTKAccordionListWindowUss.uss
|
||||||
|
```
|
||||||
|
|
||||||
|
**네이밍 규칙:**
|
||||||
|
| 파일 유형 | 네이밍 패턴 | 예시 |
|
||||||
|
|-----------|-------------|------|
|
||||||
|
| UXML | `{ComponentName}.uxml` | `UTKAccordionListWindow.uxml` |
|
||||||
|
| USS | `{ComponentName}Uss.uss` | `UTKAccordionListWindowUss.uss` |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7) USS 스타일 가이드
|
## 7) USS 스타일 가이드
|
||||||
|
|||||||
Reference in New Issue
Block a user