스타일 가이드 수정 중

This commit is contained in:
logonkhi
2026-01-23 19:04:12 +09:00
parent 59d473c87b
commit 99f9c3b26d
86 changed files with 3013 additions and 1795 deletions

View File

@@ -0,0 +1,249 @@
#nullable enable
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.UIToolkit;
/// <summary>
/// UTKStyleGuideSample의 Button 카테고리 Initialize 메서드들
/// </summary>
public partial class UTKStyleGuideSample
{
#region Button Initializers
private void InitializeButtonSample(VisualElement root)
{
// Icon Only 버튼 추가
var iconOnlyRow = root.Q<VisualElement>("icon-only-row");
if (iconOnlyRow != null)
{
iconOnlyRow.Add(new UTKButton("", UTKMaterialIcons.PlusOne, UTKButton.ButtonVariant.Primary) { IconOnly = true });
iconOnlyRow.Add(new UTKButton("", UTKMaterialIcons.Edit, UTKButton.ButtonVariant.Normal) { IconOnly = true });
iconOnlyRow.Add(new UTKButton("", UTKMaterialIcons.Close, UTKButton.ButtonVariant.Danger) { IconOnly = true });
iconOnlyRow.Add(new UTKButton("", UTKMaterialIcons.Settings, UTKButton.ButtonVariant.OutlinePrimary) { IconOnly = true });
iconOnlyRow.Add(new UTKButton("", UTKMaterialIcons.Cancel, UTKButton.ButtonVariant.Normal) { IconOnly = true });
}
// Ghost 버튼 아이콘 추가
var ghostRow = root.Q<VisualElement>("ghost-row");
if (ghostRow != null)
{
ghostRow.Add(new UTKButton("", UTKMaterialIcons.Settings, UTKButton.ButtonVariant.Ghost) { IconOnly = true });
}
// Text with icon 추가
var textRow = root.Q<VisualElement>("text-row");
if (textRow != null)
{
textRow.Add(new UTKButton("With Icon", UTKMaterialIcons.FlashOn, UTKButton.ButtonVariant.Text));
}
// Text Icon Only (Circle) 추가
var textIconOnlyRow = root.Q<VisualElement>("text-icon-only-row");
if (textIconOnlyRow != null)
{
textIconOnlyRow.Add(new UTKButton("", UTKMaterialIcons.Close, UTKButton.ButtonVariant.Text, 12) { IconOnly = true });
textIconOnlyRow.Add(new UTKButton("", UTKMaterialIcons.Check, UTKButton.ButtonVariant.Text, 12) { IconOnly = true });
textIconOnlyRow.Add(new UTKButton("", UTKMaterialIcons.Settings, UTKButton.ButtonVariant.Text, 12) { IconOnly = true });
textIconOnlyRow.Add(new UTKButton("", UTKMaterialIcons.Edit, UTKButton.ButtonVariant.Text, 12) { IconOnly = true });
textIconOnlyRow.Add(new UTKButton("", UTKMaterialIcons.Search, UTKButton.ButtonVariant.Text, 12) { IconOnly = true });
}
// C# 코드 샘플 설정
SetCodeSamples(root,
csharpCode: @"// 1. Filled Buttons (배경이 채워진 버튼)
var primaryBtn = new UTKButton(""Primary"", variant: ButtonVariant.Primary);
var normalBtn = new UTKButton(""Normal"", variant: ButtonVariant.Normal);
var dangerBtn = new UTKButton(""Danger"", variant: ButtonVariant.Danger);
primaryBtn.OnClicked += () => Debug.Log(""Primary 클릭!"");
// 2. Outline Buttons (외곽선 버튼)
var outlinePrimary = new UTKButton(""Outline Primary"", variant: ButtonVariant.OutlinePrimary);
var outlineNormal = new UTKButton(""Outline Normal"", variant: ButtonVariant.OutlineNormal);
var outlineDanger = new UTKButton(""Outline Danger"", variant: ButtonVariant.OutlineDanger);
// 3. Icon Only (아이콘만 표시)
var plusOneBtn = new UTKButton("""", UTKMaterialIcons.PlusOne, ButtonVariant.Primary) { IconOnly = true };
var editBtn = new UTKButton("""", UTKMaterialIcons.Edit, ButtonVariant.Normal) { IconOnly = true };
var closeBtn = new UTKButton("""", UTKMaterialIcons.Close, ButtonVariant.Danger) { IconOnly = true };
// 4. Ghost (반투명 배경)
var ghostBtn = new UTKButton(""Ghost"", variant: ButtonVariant.Ghost);
var ghostIconBtn = new UTKButton("""", UTKMaterialIcons.Settings, ButtonVariant.Ghost) { IconOnly = true };
// 5. Text (배경 없음)
var textOnlyBtn = new UTKButton(""Text Only"", variant: ButtonVariant.Text);
var linkStyleBtn = new UTKButton(""Link Style"", variant: ButtonVariant.Text);
var withIconBtn = new UTKButton(""With Icon"", UTKMaterialIcons.Bolt, ButtonVariant.Text);
// 6. Text Icon Only (Circle)
var circleBtn = new UTKButton("""", UTKMaterialIcons.Home, ButtonVariant.Text, 12) { IconOnly = true };
// 7. Disabled (비활성화)
var disabledBtn = new UTKButton(""Disabled"", variant: ButtonVariant.Primary);
disabledBtn.SetEnabled(false);
// 8. Action 사용 - 동기 작업
var saveBtn = new UTKButton(""저장"", UTKMaterialIcons.Save, ButtonVariant.Primary);
saveBtn.OnClicked += () => { Debug.Log(""저장 중...""); SaveData(); };
// Action 사용 - UniTask 비동기 작업
var loadBtn = new UTKButton(""로드"", UTKMaterialIcons.Download, ButtonVariant.Primary);
loadBtn.OnClicked += async () => {
Debug.Log(""로딩 시작..."");
await LoadDataAsync();
Debug.Log(""로딩 완료!"");
};
// 9. 아이콘 설정 방법
var btn = new UTKButton(""설정"");
btn.SetMaterialIcon(UTKMaterialIcons.Settings);
btn.SetImageIcon(UTKImageIcons.BtnClose22);
await btn.SetMaterialIconAsync(UTKMaterialIcons.Search);
btn.IconSize = 24;
btn.ClearIcon();
// 10. 기타 속성
btn.Size = ButtonSize.Large;
btn.BackgroundColor = new Color(0.2f, 0.4f, 0.8f);
btn.BorderWidth = 2;
btn.Text = ""새로운 텍스트"";",
uxmlCode: @"<!-- 네임스페이스 선언 -->
<ui:UXML xmlns:utk=""UVC.UIToolkit"">
<!-- 1. Filled Buttons -->
<utk:UTKButton text=""Primary"" variant=""Primary"" />
<utk:UTKButton text=""Normal"" variant=""Normal"" />
<utk:UTKButton text=""Danger"" variant=""Danger"" />
<!-- 2. Outline Buttons -->
<utk:UTKButton text=""Outline Primary"" variant=""OutlinePrimary"" />
<utk:UTKButton text=""Outline Normal"" variant=""OutlineNormal"" />
<utk:UTKButton text=""Outline Danger"" variant=""OutlineDanger"" />
<!-- 3. Icon Only -->
<utk:UTKButton icon=""close"" icon-only=""true"" variant=""Primary"" />
<utk:UTKButton icon=""settings"" icon-only=""true"" variant=""Normal"" />
<utk:UTKButton icon=""cancel"" icon-only=""true"" variant=""Danger"" />
<!-- 4. Ghost -->
<utk:UTKButton text=""Ghost"" variant=""Ghost"" />
<utk:UTKButton icon=""close"" icon-only=""true"" variant=""Ghost"" />
<!-- 5. Text -->
<utk:UTKButton text=""Text Only"" variant=""Text"" />
<utk:UTKButton text=""Link Style"" variant=""Text"" />
<utk:UTKButton text=""With Icon"" icon=""refresh"" variant=""Text"" />
<!-- 6. Text Icon Only (Circle) -->
<utk:UTKButton icon=""close"" icon-size=""12"" icon-only=""true"" variant=""Text"" />
<!-- 7. Disabled -->
<utk:UTKButton text=""Disabled"" variant=""Primary"" is-enabled=""false"" />
<utk:UTKButton text=""Disabled"" variant=""Normal"" is-enabled=""false"" />
<!-- 8. 크기 변형 -->
<utk:UTKButton text=""작은 버튼"" size=""Small"" />
<utk:UTKButton text=""큰 버튼"" size=""Large"" />
<!-- 9. 아이콘 크기 지정 -->
<utk:UTKButton icon=""close"" icon-size=""24"" icon-only=""true"" />
<!-- 10. 외곽선 굵기 -->
<utk:UTKButton text=""두꺼운 외곽선"" border-width=""2"" />
</ui:UXML>");
}
private void InitializeToggleButtonGroupSample(VisualElement root)
{
// Single Select
var singleSelectRow = root.Q<VisualElement>("single-select-row");
if (singleSelectRow != null)
{
var group1 = new UTKToggleButtonGroup();
group1.AddButton("Option 1");
group1.AddButton("Option 2");
group1.AddButton("Option 3");
singleSelectRow.Add(group1);
}
// Multi Select
var multiSelectRow = root.Q<VisualElement>("multi-select-row");
if (multiSelectRow != null)
{
var group2 = new UTKToggleButtonGroup { isMultipleSelection = true };
group2.AddButton("A");
group2.AddButton("B");
group2.AddButton("C");
group2.AddButton("D");
multiSelectRow.Add(group2);
}
// Disabled
var disabledRow = root.Q<VisualElement>("disabled-row");
if (disabledRow != null)
{
var group3 = new UTKToggleButtonGroup { IsEnabled = false };
group3.AddButton("Option 1");
group3.AddButton("Option 2");
group3.AddButton("Option 3");
disabledRow.Add(group3);
}
SetCodeSamples(root,
csharpCode: @"// Single Selection (기본)
var group1 = new UTKToggleButtonGroup();
group1.AddButton(""Option 1"");
group1.AddButton(""Option 2"");
group1.AddButton(""Option 3"");
// 선택 이벤트
group1.OnSelectionChanged += (index) =>
{
Debug.Log($""선택된 버튼: {index}"");
};
// Multiple Selection
var group2 = new UTKToggleButtonGroup { isMultipleSelection = true };
group2.AddButton(""A"");
group2.AddButton(""B"");
group2.AddButton(""C"");
group2.AddButton(""D"");
group2.OnSelectionChanged += (index) =>
{
Debug.Log($""토글된 버튼: {index}"");
};
// 선택된 인덱스 가져오기
var selectedIndex = group1.SelectedIndex; // Single
var selectedIndices = group2.SelectedIndices; // Multiple
// 프로그램으로 선택
group1.SelectButton(1); // 두 번째 버튼 선택
group2.ToggleButton(0); // 첫 번째 버튼 토글
// Disabled
var group3 = new UTKToggleButtonGroup { IsEnabled = false };
group3.AddButton(""Option 1"");
group3.AddButton(""Option 2"");
group3.AddButton(""Option 3"");" ,
uxmlCode: @"<!-- UTKToggleButtonGroup은 동적 생성 권장 -->
<!-- C# 코드에서 AddButton으로 버튼 추가 -->
<!-- Single Selection 예시 -->
<utk:UTKToggleButtonGroup name=""toggle-group-1"" />
<!-- Multiple Selection 예시 -->
<utk:UTKToggleButtonGroup name=""toggle-group-2"" is-multiple-selection=""true"" />
<!-- Disabled -->
<utk:UTKToggleButtonGroup name=""toggle-group-3"" is-enabled=""false"" />");
}
#endregion
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5eb3d381be2ce2c4db20a29ca901880c

View File

@@ -0,0 +1,511 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.UIToolkit;
/// <summary>
/// UTKStyleGuideSample의 Icon 카테고리 Initialize 메서드들
/// </summary>
public partial class UTKStyleGuideSample
{
#region Icon Initializers
private void InitializeUTKMaterialIconsSample(VisualElement root)
{
var font = UTKMaterialIcons.LoadFont();
if (font == null)
{
root.Add(new Label("Error: UTKMaterialIcons 폰트를 로드할 수 없습니다."));
return;
}
// Icon 코드 블록 참조 저장
_materialIconCodeBlock = root.Q<UTKCodeBlock>();
if (_materialIconCodeBlock != null && _materialIconCodeBlock.Title == "Icon")
{
UpdateMaterialIconCodeBlock("Home");
}
_iconNameList = UTKMaterialIcons.GetAllIconNames().ToList();
_filteredIconNameList = _iconNameList;
_iconCountLabel = root.Q<Label>("icon-count-label");
if (_iconCountLabel != null)
{
_iconCountLabel.text = $"총 {UTKMaterialIcons.Count}개의 아이콘 (가상화 적용)";
}
var searchField = root.Q<UTKInputField>("icon-search");
var gridContainer = root.Q<VisualElement>("icon-grid-container");
if (gridContainer != null)
{
var rowData = CreateIconRowData(_filteredIconNameList);
_iconListView = new ListView();
_iconListView.style.flexGrow = 1;
_iconListView.style.maxHeight = 500;
_iconListView.fixedItemHeight = IconItemHeight + IconItemMargin;
_iconListView.itemsSource = rowData;
_iconListView.makeItem = MakeIconRow;
_iconListView.bindItem = BindIconRow;
_iconListView.selectionType = SelectionType.None;
_iconListView.virtualizationMethod = CollectionVirtualizationMethod.FixedHeight;
gridContainer.Add(_iconListView);
}
if (searchField != null)
{
void PerformSearch(string searchValue)
{
if (_iconNameList == null || _iconListView == null || _iconCountLabel == null) return;
_filteredIconNameList = string.IsNullOrEmpty(searchValue)
? _iconNameList
: _iconNameList.FindAll(name => name.Contains(searchValue, StringComparison.OrdinalIgnoreCase));
var newRowData = CreateIconRowData(_filteredIconNameList);
_iconListView.itemsSource = newRowData;
_iconListView.Rebuild();
_iconCountLabel.text = string.IsNullOrEmpty(searchValue)
? $"총 {UTKMaterialIcons.Count}개의 아이콘 (가상화 적용)"
: $"{_filteredIconNameList.Count}개 / {UTKMaterialIcons.Count}개 아이콘 (가상화 적용)";
}
searchField.OnSubmit += PerformSearch;
searchField.OnBlurred += () => PerformSearch(searchField.Value);
}
}
private List<List<string>> CreateIconRowData(List<string> iconNames)
{
var rows = new List<List<string>>();
for (int i = 0; i < iconNames.Count; i += IconsPerRow)
{
var row = new List<string>();
for (int j = 0; j < IconsPerRow && i + j < iconNames.Count; j++)
{
row.Add(iconNames[i + j]);
}
rows.Add(row);
}
return rows;
}
private VisualElement MakeIconRow()
{
var row = new VisualElement();
row.style.flexDirection = FlexDirection.Row;
row.style.height = IconItemHeight;
for (int i = 0; i < IconsPerRow; i++)
{
var iconSlot = CreateIconSlot();
row.Add(iconSlot);
}
return row;
}
private VisualElement CreateIconSlot()
{
var item = new VisualElement();
item.name = "icon-slot";
item.style.width = IconItemWidth;
item.style.height = IconItemHeight;
item.style.marginRight = IconItemMargin;
item.style.alignItems = Align.Center;
item.style.justifyContent = Justify.Center;
item.style.borderTopLeftRadius = 4;
item.style.borderTopRightRadius = 4;
item.style.borderBottomLeftRadius = 4;
item.style.borderBottomRightRadius = 4;
item.AddToClassList("utk-icon-slot");
var iconLabel = new Label();
iconLabel.name = "icon-label";
UTKMaterialIcons.ApplyIconStyle(iconLabel, 28);
iconLabel.AddToClassList("utk-icon-slot__icon");
iconLabel.style.marginBottom = 4;
item.Add(iconLabel);
var nameLabel = new Label();
nameLabel.name = "name-label";
nameLabel.style.fontSize = 8;
nameLabel.style.whiteSpace = WhiteSpace.NoWrap;
nameLabel.style.overflow = Overflow.Hidden;
nameLabel.style.textOverflow = TextOverflow.Ellipsis;
nameLabel.style.maxWidth = IconItemWidth - 4;
nameLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
nameLabel.AddToClassList("utk-icon-slot__name");
item.Add(nameLabel);
return item;
}
private void BindIconRow(VisualElement row, int index)
{
if (_iconListView?.itemsSource is not List<List<string>> rowData) return;
if (index < 0 || index >= rowData.Count) return;
var iconNames = rowData[index];
var slots = row.Query<VisualElement>("icon-slot").ToList();
for (int i = 0; i < slots.Count; i++)
{
var slot = slots[i];
if (i < iconNames.Count)
{
var iconName = iconNames[i];
var iconChar = UTKMaterialIcons.GetIcon(iconName);
slot.style.display = DisplayStyle.Flex;
var iconLabel = slot.Q<Label>("icon-label");
if (iconLabel != null)
iconLabel.text = iconChar;
var nameLabel = slot.Q<Label>("name-label");
if (nameLabel != null)
nameLabel.text = iconName;
slot.tooltip = iconName;
slot.userData = iconName;
slot.UnregisterCallback<ClickEvent>(OnIconSlotClicked);
slot.RegisterCallback<ClickEvent>(OnIconSlotClicked);
}
else
{
slot.style.display = DisplayStyle.None;
}
}
}
private void OnIconSlotClicked(ClickEvent evt)
{
if (evt.currentTarget is VisualElement slot && slot.userData is string iconName)
{
UpdateMaterialIconCodeBlock(iconName);
var csharpCode = $"UTKMaterialIcons.{iconName}";
GUIUtility.systemCopyBuffer = csharpCode;
UTKToast.Show($"복사됨: {csharpCode}");
}
}
private void UpdateMaterialIconCodeBlock(string iconName)
{
if (_materialIconCodeBlock == null) return;
var iconChar = UTKMaterialIcons.GetIcon(iconName);
if (string.IsNullOrEmpty(iconChar))
{
_materialIconCodeBlock.Code = $"// 아이콘을 찾을 수 없습니다: {iconName}";
return;
}
var iconDisplayName = UTKMaterialIcons.GetIconNameByChar(iconChar);
//첫글자만 대문자로 바꾸기
var iconDisplayNameCapitalized = char.ToUpper(iconDisplayName[0]) + iconDisplayName.Substring(1);
var unicodeHex = $"\\u{((int)iconChar[0]):x4}";
var code = $"// C# 코드\n" +
$"// Material Icon과 텍스트 함께 사용\n" +
$"var iconLabel = new UTKLabel(\"\", UTKMaterialIcons.{iconDisplayNameCapitalized});\n" +
$"\n" +
$"// Material Icon만 사용\n" +
$"var iconOnly = new UTKLabel(UTKMaterialIcons.{iconDisplayNameCapitalized}, 12);\n" +
$"<utk:UTKLabel material-icon=\"{iconDisplayName}\" icon-size=\"12\" />\n" +
$"var iconLabel = new UTKLabel(\"\", UTKMaterialIcons.{iconDisplayNameCapitalized});\n" +
$"<utk:UTKLabel text=\"\" material-icon=\"{iconDisplayName}\" />\n" +
$"\n" +
$"var circleBtn1 = new UTKButton(\"\", UTKMaterialIcons.{iconDisplayNameCapitalized}, ButtonVariant.Text, 12) {{ IconOnly = true }};\n" +
$"<utk:UTKButton icon=\"{iconDisplayName}\" icon-only=\"true\" icon-size=\"12\" variant=\"Text\" />\n" +
$"\n" +
$"var label = new Label(UTKMaterialIcons.{iconDisplayNameCapitalized});\n" +
$"UTKMaterialIcons.ApplyIconStyle(label);\n" +
$"\n" +
$"/* 유니코드: {unicodeHex} */";
_materialIconCodeBlock.Code = code;
}
private void InitializeImageIconsSample(VisualElement root)
{
// Icon 코드 블록 참조 저장
var codeBlocks = root.Query<UTKCodeBlock>().ToList();
_imageIconCodeBlock = codeBlocks.FirstOrDefault(cb => cb.Title == "Icon");
if (_imageIconCodeBlock != null && _imageIconNameList != null && _imageIconNameList.Count > 0)
{
UpdateImageIconCodeBlock(_imageIconNameList[0]);
}
_imageIconNameList = UTKImageIcons.GetAllIconNames().ToList();
_filteredImageIconNameList = _imageIconNameList;
_imageIconCountLabel = root.Q<Label>("image-icon-count-label");
if (_imageIconCountLabel != null)
{
_imageIconCountLabel.text = $"총 {UTKImageIcons.Count}개의 이미지 아이콘 (가상화 적용)";
}
var searchField = root.Q<UTKInputField>("image-icon-search");
var gridContainer = root.Q<VisualElement>("image-icon-grid-container");
if (gridContainer != null)
{
var rowData = CreateImageIconRowData(_filteredImageIconNameList);
_imageIconListView = new ListView();
_imageIconListView.style.flexGrow = 1;
_imageIconListView.style.maxHeight = 500;
_imageIconListView.fixedItemHeight = ImageIconItemHeight + ImageIconItemMargin;
_imageIconListView.itemsSource = rowData;
_imageIconListView.makeItem = MakeImageIconRow;
_imageIconListView.bindItem = BindImageIconRow;
_imageIconListView.selectionType = SelectionType.None;
_imageIconListView.virtualizationMethod = CollectionVirtualizationMethod.FixedHeight;
gridContainer.Add(_imageIconListView);
}
if (searchField != null)
{
void PerformSearch(string searchValue)
{
if (_imageIconNameList == null || _imageIconListView == null || _imageIconCountLabel == null) return;
_filteredImageIconNameList = string.IsNullOrEmpty(searchValue)
? _imageIconNameList
: _imageIconNameList.FindAll(name => name.Contains(searchValue, StringComparison.OrdinalIgnoreCase));
var newRowData = CreateImageIconRowData(_filteredImageIconNameList);
_imageIconListView.itemsSource = newRowData;
_imageIconListView.Rebuild();
_imageIconCountLabel.text = string.IsNullOrEmpty(searchValue)
? $"총 {UTKImageIcons.Count}개의 이미지 아이콘 (가상화 적용)"
: $"{_filteredImageIconNameList.Count}개 / {UTKImageIcons.Count}개 이미지 아이콘 (가상화 적용)";
}
searchField.OnSubmit += PerformSearch;
searchField.OnBlurred += () => PerformSearch(searchField.Value);
}
}
private List<List<string>> CreateImageIconRowData(List<string> iconNames)
{
var rows = new List<List<string>>();
for (int i = 0; i < iconNames.Count; i += ImageIconsPerRow)
{
var row = new List<string>();
for (int j = 0; j < ImageIconsPerRow && i + j < iconNames.Count; j++)
{
row.Add(iconNames[i + j]);
}
rows.Add(row);
}
return rows;
}
private VisualElement MakeImageIconRow()
{
var row = new VisualElement();
row.style.flexDirection = FlexDirection.Row;
row.style.height = ImageIconItemHeight;
for (int i = 0; i < ImageIconsPerRow; i++)
{
var iconSlot = CreateImageIconSlot();
row.Add(iconSlot);
}
return row;
}
private VisualElement CreateImageIconSlot()
{
var item = new VisualElement();
item.name = "image-icon-slot";
item.style.width = ImageIconItemWidth;
item.style.height = ImageIconItemHeight;
item.style.marginRight = ImageIconItemMargin;
item.style.alignItems = Align.Center;
item.style.justifyContent = Justify.Center;
item.style.borderTopLeftRadius = 4;
item.style.borderTopRightRadius = 4;
item.style.borderBottomLeftRadius = 4;
item.style.borderBottomRightRadius = 4;
item.AddToClassList("utk-icon-slot");
var iconImage = new VisualElement();
iconImage.name = "icon-image";
iconImage.style.width = 32;
iconImage.style.height = 32;
iconImage.style.marginBottom = 4;
iconImage.AddToClassList("utk-icon-slot__image");
item.Add(iconImage);
var nameLabel = new Label();
nameLabel.name = "name-label";
nameLabel.style.fontSize = 8;
nameLabel.style.whiteSpace = WhiteSpace.NoWrap;
nameLabel.style.overflow = Overflow.Hidden;
nameLabel.style.textOverflow = TextOverflow.Ellipsis;
nameLabel.style.maxWidth = ImageIconItemWidth - 4;
nameLabel.style.unityTextAlign = TextAnchor.MiddleCenter;
nameLabel.AddToClassList("utk-icon-slot__name");
item.Add(nameLabel);
return item;
}
private void BindImageIconRow(VisualElement row, int index)
{
if (_imageIconListView?.itemsSource is not List<List<string>> rowData) return;
if (index < 0 || index >= rowData.Count) return;
var iconNames = rowData[index];
var slots = row.Query<VisualElement>("image-icon-slot").ToList();
for (int i = 0; i < slots.Count; i++)
{
var slot = slots[i];
if (i < iconNames.Count)
{
var iconName = iconNames[i];
var iconPath = UTKImageIcons.GetPath(iconName);
slot.style.display = DisplayStyle.Flex;
var iconImage = slot.Q<VisualElement>("icon-image");
if (iconImage != null)
{
var texture = UTKImageIcons.LoadTextureByName(iconName);
if (texture != null)
{
iconImage.style.backgroundImage = new StyleBackground(texture);
}
else
{
iconImage.style.backgroundImage = StyleKeyword.None;
}
}
var nameLabel = slot.Q<Label>("name-label");
if (nameLabel != null)
nameLabel.text = iconName;
slot.tooltip = $"{iconName}\n{iconPath}";
slot.userData = iconName;
slot.UnregisterCallback<ClickEvent>(OnImageIconSlotClicked);
slot.RegisterCallback<ClickEvent>(OnImageIconSlotClicked);
}
else
{
slot.style.display = DisplayStyle.None;
}
}
}
private void OnImageIconSlotClicked(ClickEvent evt)
{
if (evt.currentTarget is VisualElement slot && slot.userData is string iconName)
{
UpdateImageIconCodeBlock(iconName);
var csharpCode = $"UTKImageIcons.{iconName}";
GUIUtility.systemCopyBuffer = csharpCode;
UTKToast.Show($"복사됨: {csharpCode}");
}
}
private void UpdateImageIconCodeBlock(string iconName)
{
if (_imageIconCodeBlock == null) return;
var iconPath = UTKImageIcons.GetPath(iconName);
if (string.IsNullOrEmpty(iconPath))
{
_imageIconCodeBlock.Code = $"// 아이콘을 찾을 수 없습니다: {iconName}";
return;
}
//PascalCase을 camelCase로 변환 btn_cancel_64 -> BtnCancel64
var iconDisplayNameCapitalized = "";
var words = iconName.Split('_');
for (int i = 0; i < words.Length; i++)
{
words[i] = char.ToUpper(words[i][0]) + words[i].Substring(1);
}
iconDisplayNameCapitalized = string.Join("", words);
var code = $"// C# 코드\n" +
$"// Sprite 로드\n" +
$"Sprite sprite = UTKImageIcons.{iconDisplayNameCapitalized};\n" +
$"var image = new Image {{ sprite = sprite }};\n" +
$"\n" +
$"// 또는 이름으로 로드\n" +
$"Sprite sprite2 = UTKImageIcons.LoadSpriteByName(\"{iconName}\");\n" +
$"\n" +
$"// Texture2D 로드\n" +
$"Texture2D texture = UTKImageIcons.LoadTextureByName(\"{iconName}\");\n" +
$"var image2 = new Image();\n" +
$"image2.style.backgroundImage = new StyleBackground(texture);\n" +
$"\n" +
$"// Image Icon만 사용\n" +
$"var imgOnly = new UTKLabel(UTKImageIcons.{iconDisplayNameCapitalized}, isImageIcon: true);\n" +
$"<utk:UTKLabel text=\"\" image-icon=\"{iconName}\" />\n" +
$"<utk:UTKLabel image-icon=\"{iconName}\" icon-size=\"22\" />\n" +
$"\n" +
$"var circleBtn1 = new UTKButton(\"\", UTKImageIcons.{iconDisplayNameCapitalized}, ButtonVariant.Text, 12) {{ IconOnly = true }};\n" +
$"<utk:UTKButton icon=\"{iconName}\" icon-only=\"true\" icon-size=\"12\" variant=\"Text\" />\n" +
$"\n" +
$"/* 경로: {iconPath} */\n" +
$"\n" +
$"/* UXML에서 사용 */\n" +
$"<utk:UTKLabel imageIcon=\"{iconPath}\" iconSize=\"22\" />";
_imageIconCodeBlock.Code = code;
}
private void InitializeUTKImageSample(VisualElement root)
{
// 외부 이미지 로드 버튼
var btnLoadExternal = root.Q<UTKButton>("btn-load-external");
var imgExternal = root.Q<UTKImage>("img-external");
var imgExternalStatus = root.Q<Label>("img-external-status");
if (btnLoadExternal != null && imgExternal != null)
{
btnLoadExternal.RegisterCallback<ClickEvent>(_ =>
{
if (imgExternalStatus != null)
imgExternalStatus.text = "로드 중...";
// 샘플 외부 이미지 URL (placeholder 이미지)
const string sampleUrl = "https://picsum.photos/200";
imgExternal.OnImageLoaded += (texture) =>
{
if (imgExternalStatus != null)
imgExternalStatus.text = $"로드 완료 ({texture.width}x{texture.height})";
};
imgExternal.OnImageFailed += (error) =>
{
if (imgExternalStatus != null)
imgExternalStatus.text = $"로드 실패: {error}";
};
imgExternal.Src = sampleUrl;
});
}
}
#endregion
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d238e34921c4c594d9301c629912bac0

View File

@@ -0,0 +1,357 @@
#nullable enable
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.UIToolkit;
/// <summary>
/// UTKStyleGuideSample의 Input 카테고리 Initialize 메서드들
/// </summary>
public partial class UTKStyleGuideSample
{
#region Input Initializers
private void InitializeNumberStepperSample(VisualElement root)
{
var disabledRow = root.Q<VisualElement>("stepper-disabled-row");
if (disabledRow != null)
{
var stepper = new UTKNumberStepper(0, 100, 30, 1);
stepper.style.width = 150;
stepper.SetEnabled(false);
disabledRow.Add(stepper);
}
SetCodeSamples(root,
csharpCode: @"// 기본 사용법
var stepper = new UTKNumberStepper(minValue: 0, maxValue: 100, value: 50, step: 1);
stepper.OnValueChanged += (newValue) => Debug.Log($""Value: {newValue}"");
// Step 설정
var stepper5 = new UTKNumberStepper(0, 100, 25, 5); // Step 5씩 증감
// Wrap Around (최소/최대값에서 순환)
var wrapStepper = new UTKNumberStepper(0, 100, 0, 10);
wrapStepper.WrapAround = true; // 0 -> -10 시 100으로 순환
// 비활성화
var disabledStepper = new UTKNumberStepper(0, 100, 30, 1);
disabledStepper.SetEnabled(false);
// 속성 변경
stepper.Value = 75;
stepper.MinValue = 10;
stepper.MaxValue = 90;
stepper.Step = 2;",
uxmlCode: @"<!-- 네임스페이스 선언 -->
<ui:UXML xmlns:utk=""UVC.UIToolkit"">
<!-- Step 1 -->
<utk:UTKNumberStepper min-value=""0"" max-value=""100"" value=""50"" step=""1"" />
<!-- Step 5 -->
<utk:UTKNumberStepper min-value=""0"" max-value=""100"" value=""25"" step=""5"" />
<!-- Wrap Around -->
<utk:UTKNumberStepper min-value=""0"" max-value=""100"" value=""0"" step=""10"" wrap-around=""true"" />
<!-- 비활성화 -->
<utk:UTKNumberStepper min-value=""0"" max-value=""100"" value=""30"" step=""1"" is-enabled=""false"" />
<!-- 커스텀 스타일 -->
<utk:UTKNumberStepper class=""custom-stepper"" style=""width: 150px;"" />
</ui:UXML>");
}
private void InitializeVector2FieldSample(VisualElement root)
{
var field = root.Q<UTKVector2Field>("vec2-position");
if (field != null)
{
field.Value = new Vector2(100, 200);
}
SetCodeSamples(root,
csharpCode: @"// 기본 사용법
var positionField = new UTKVector2Field(""Position"");
positionField.Value = new Vector2(100, 200);
positionField.OnValueChanged += (newValue) => Debug.Log($""Position: {newValue}"");
// 라벨 없이
var field = new UTKVector2Field();
field.Label = """";
// 읽기 전용
var readOnlyField = new UTKVector2Field(""ReadOnly"");
readOnlyField.SetEnabled(false);",
uxmlCode: @"<!-- 네임스페이스 선언 -->
<ui:UXML xmlns:utk=""UVC.UIToolkit"">
<!-- 기본 사용 -->
<utk:UTKVector2Field label=""Position"" />
<!-- 라벨 없이 -->
<utk:UTKVector2Field />
<!-- 비활성화 -->
<utk:UTKVector2Field label=""ReadOnly"" is-enabled=""false"" />
</ui:UXML>");
}
private void InitializeVector3FieldSample(VisualElement root)
{
var field = root.Q<UTKVector3Field>("vec3-position");
if (field != null)
{
field.Value = new Vector3(10, 20, 30);
}
SetCodeSamples(root,
csharpCode: @"// 기본 사용법
var positionField = new UTKVector3Field(""Position"");
positionField.Value = new Vector3(10, 20, 30);
positionField.OnValueChanged += (newValue) => Debug.Log($""Position: {newValue}"");
// 회전 벡터
var rotationField = new UTKVector3Field(""Rotation"");
rotationField.Value = new Vector3(0, 90, 0);
// 비활성화
var disabledField = new UTKVector3Field(""Disabled"");
disabledField.SetEnabled(false);",
uxmlCode: @"<!-- 네임스페이스 선언 -->
<ui:UXML xmlns:utk=""UVC.UIToolkit"">
<!-- 기본 사용 -->
<utk:UTKVector3Field label=""Position"" />
<!-- 라벨 없이 -->
<utk:UTKVector3Field />
<!-- 비활성화 -->
<utk:UTKVector3Field label=""Disabled"" is-enabled=""false"" />
</ui:UXML>");
}
private void InitializeVector4FieldSample(VisualElement root)
{
var field = root.Q<UTKVector4Field>("vec4-color");
if (field != null)
{
field.Value = new Vector4(1, 0.5f, 0.25f, 1);
}
SetCodeSamples(root,
csharpCode: @"// 기본 사용법
var colorField = new UTKVector4Field(""Color"");
colorField.Value = new Vector4(1, 0.5f, 0.25f, 1); // RGBA
colorField.OnValueChanged += (newValue) => Debug.Log($""Color: {newValue}"");
// 쿼터니언 값
var quaternionField = new UTKVector4Field(""Quaternion"");
var quat = Quaternion.identity;
quaternionField.Value = new Vector4(quat.x, quat.y, quat.z, quat.w);
// 비활성화
var disabledField = new UTKVector4Field(""Disabled"");
disabledField.SetEnabled(false);",
uxmlCode: @"<!-- 네임스페이스 선언 -->
<ui:UXML xmlns:utk=""UVC.UIToolkit"">
<!-- 기본 사용 -->
<utk:UTKVector4Field label=""Color"" />
<!-- 라벨 없이 -->
<utk:UTKVector4Field />
<!-- 비활성화 -->
<utk:UTKVector4Field label=""Disabled"" is-enabled=""false"" />
</ui:UXML>");
}
private void InitializeRectFieldSample(VisualElement root)
{
var field = root.Q<UTKRectField>("rect-area");
if (field != null)
{
field.Value = new Rect(10, 20, 100, 50);
}
SetCodeSamples(root,
csharpCode: @"// 기본 사용법
var areaField = new UTKRectField(""Area"");
areaField.Value = new Rect(10, 20, 100, 50); // x, y, width, height
areaField.OnValueChanged += (newValue) => Debug.Log($""Rect: {newValue}"");
// 화면 영역 설정
var screenArea = new UTKRectField(""Screen Area"");
screenArea.Value = new Rect(0, 0, Screen.width, Screen.height);
// 비활성화
var disabledField = new UTKRectField(""Disabled"");
disabledField.SetEnabled(false);",
uxmlCode: @"<!-- 네임스페이스 선언 -->
<ui:UXML xmlns:utk=""UVC.UIToolkit"">
<!-- 기본 사용 -->
<utk:UTKRectField label=""Area"" />
<!-- 라벨 없이 -->
<utk:UTKRectField />
<!-- 비활성화 -->
<utk:UTKRectField label=""Disabled"" is-enabled=""false"" />
</ui:UXML>");
}
private void InitializeBoundsFieldSample(VisualElement root)
{
var field = root.Q<UTKBoundsField>("bounds-collision");
if (field != null)
{
field.Value = new Bounds(new Vector3(0, 1, 0), new Vector3(2, 2, 2));
}
SetCodeSamples(root,
csharpCode: @"// 기본 사용법
var boundsField = new UTKBoundsField(""Bounds"");
var center = new Vector3(0, 1, 0);
var size = new Vector3(2, 2, 2);
boundsField.Value = new Bounds(center, size);
boundsField.OnValueChanged += (newValue) => Debug.Log($""Bounds: {newValue}"");
// 콜라이더 범위 설정
var collisionField = new UTKBoundsField(""Collision Bounds"");
collisionField.Value = new Bounds(Vector3.zero, Vector3.one * 5);
// 비활성화
var disabledField = new UTKBoundsField(""Disabled"");
disabledField.SetEnabled(false);",
uxmlCode: @"<!-- 네임스페이스 선언 -->
<ui:UXML xmlns:utk=""UVC.UIToolkit"">
<!-- 기본 사용 -->
<utk:UTKBoundsField label=""Bounds"" />
<!-- 라벨 없이 -->
<utk:UTKBoundsField />
<!-- 비활성화 -->
<utk:UTKBoundsField label=""Disabled"" is-enabled=""false"" />
</ui:UXML>");
}
#endregion
#region Dropdown Initializers
private void InitializeDropdownSample(VisualElement root)
{
var normalRow = root.Q<VisualElement>("dropdown-normal-row");
if (normalRow != null)
{
var dropdown = new UTKDropdown("Select Option");
dropdown.SetOptions(new List<string> { "Option 1", "Option 2", "Option 3", "Option 4" });
dropdown.SelectedIndex = 0;
normalRow.Add(dropdown);
}
var disabledRow = root.Q<VisualElement>("dropdown-disabled-row");
if (disabledRow != null)
{
var dropdown = new UTKDropdown("Disabled");
dropdown.SetOptions(new List<string> { "Option 1", "Option 2" });
dropdown.SelectedIndex = 0;
dropdown.IsEnabled = false;
disabledRow.Add(dropdown);
}
SetCodeSamples(root,
csharpCode: @"// 기본 사용법
var dropdown = new UTKDropdown(""Select Option"");
dropdown.SetOptions(new List<string> { ""Option 1"", ""Option 2"", ""Option 3"", ""Option 4"" });
dropdown.SelectedIndex = 0;
// 선택 이벤트
dropdown.OnSelectionChanged += (index) =>
{
Debug.Log($""선택된 인덱스: {index}"");
};
// 선택된 값 가져오기
var selectedIndex = dropdown.SelectedIndex;
var selectedValue = dropdown.SelectedValue;
// 옵션 동적 변경
dropdown.SetOptions(new List<string> { ""New 1"", ""New 2"", ""New 3"" });
// 프로그램으로 선택
dropdown.SelectedIndex = 2;
// Disabled
var disabledDropdown = new UTKDropdown(""Disabled"");
disabledDropdown.SetOptions(new List<string> { ""Option 1"", ""Option 2"" });
disabledDropdown.SelectedIndex = 0;
disabledDropdown.IsEnabled = false;",
uxmlCode: @"<!-- UTKDropdown은 동적 생성 권장 -->
<!-- C# 코드에서 SetOptions로 옵션 설정 -->
<!-- 기본 드롭다운 -->
<utk:UTKDropdown name=""dropdown-1"" text=""Select Option"" />
<!-- Disabled -->
<utk:UTKDropdown name=""dropdown-2"" text=""Disabled"" is-enabled=""false"" />");
}
private enum SampleEnum { Option1, Option2, Option3 }
private void InitializeEnumDropDownSample(VisualElement root)
{
var enumRow = root.Q<VisualElement>("enum-dropdown-row");
if (enumRow != null)
{
var field = new UTKEnumDropDown("Choice", SampleEnum.Option1);
enumRow.Add(field);
}
SetCodeSamples(root,
csharpCode: @"// Enum 정의
public enum SampleEnum { Option1, Option2, Option3 }
// 기본 사용법
var enumField = new UTKEnumDropDown(""Choice"", SampleEnum.Option1);
// 값 변경 이벤트
enumField.OnValueChanged += (newValue) =>
{
Debug.Log($""선택된 값: {newValue}"");
};
// 현재 선택된 값 가져오기
var currentValue = enumField.Value;
// 프로그램으로 값 변경
enumField.Value = SampleEnum.Option2;
// Disabled
enumField.IsEnabled = false;",
uxmlCode: @"<!-- UTKEnumDropDown은 동적 생성 권장 -->
<!-- C# 코드에서 enum 타입과 초기값 지정 -->
<!-- 기본 Enum 드롭다운 -->
<utk:UTKEnumDropDown name=""enum-dropdown-1"" label=""Choice"" />
<!-- Disabled -->
<utk:UTKEnumDropDown name=""enum-dropdown-2"" label=""Choice"" is-enabled=""false"" />");
}
#endregion
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 96cc8dc4259f8e5408a0cb5d26902cc7

View File

@@ -0,0 +1,372 @@
#nullable enable
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.UIToolkit;
/// <summary>
/// UTKStyleGuideSample의 List 카테고리 Initialize 메서드들
/// </summary>
public partial class UTKStyleGuideSample
{
#region Label Initializers
private void InitializeLabelSample(VisualElement root)
{
// Material Icon + Text
var materialIconRow = root.Q<VisualElement>("material-icon-row");
if (materialIconRow != null)
{
materialIconRow.Add(new UTKLabel("Settings", UTKMaterialIcons.Settings));
materialIconRow.Add(new UTKLabel("Home", UTKMaterialIcons.Home));
materialIconRow.Add(new UTKLabel("Search", UTKMaterialIcons.Search));
materialIconRow.Add(new UTKLabel("Edit", UTKMaterialIcons.Edit));
}
// Icon Right
var iconRightRow = root.Q<VisualElement>("icon-right-row");
if (iconRightRow != null)
{
iconRightRow.Add(new UTKLabel("Next", UTKMaterialIcons.ArrowForward, UTKLabel.IconPosition.Right));
iconRightRow.Add(new UTKLabel("Download", UTKMaterialIcons.Download, UTKLabel.IconPosition.Right));
iconRightRow.Add(new UTKLabel("External", UTKMaterialIcons.OpenInNew, UTKLabel.IconPosition.Right));
}
// Image Icon + Text
var imageIconRow = root.Q<VisualElement>("image-icon-row");
if (imageIconRow != null)
{
imageIconRow.Add(new UTKLabel("Close", UTKImageIcons.BtnClose16, isImageIcon: true));
imageIconRow.Add(new UTKLabel("Settings", UTKImageIcons.IconSetting22, isImageIcon: true));
}
// Material Icon Only
var materialIconOnlyRow = root.Q<VisualElement>("material-icon-only-row");
if (materialIconOnlyRow != null)
{
materialIconOnlyRow.Add(new UTKLabel(UTKMaterialIcons.Home, 24));
materialIconOnlyRow.Add(new UTKLabel(UTKMaterialIcons.Settings, 24));
materialIconOnlyRow.Add(new UTKLabel(UTKMaterialIcons.Search, 24));
materialIconOnlyRow.Add(new UTKLabel(UTKMaterialIcons.Edit, 24));
materialIconOnlyRow.Add(new UTKLabel(UTKMaterialIcons.Delete, 24));
}
SetCodeSamples(root,
csharpCode: @"// 기본 라벨
var label = new UTKLabel();
label.Text = ""안녕하세요"";
label.Size = UTKLabel.LabelSize.Body1;
label.Variant = UTKLabel.LabelVariant.Primary;
// 제목 스타일
var title = new UTKLabel();
title.Text = ""제목"";
title.Size = UTKLabel.LabelSize.Heading1;
title.IsBold = true;
// Material Icon과 텍스트 함께 사용
var iconLabel = new UTKLabel(""설정"", UTKMaterialIcons.Settings);
// Material Icon만 사용
var iconOnly = new UTKLabel(UTKMaterialIcons.Home);",
uxmlCode: @"<!-- 기본 라벨 -->
<utk:UTKLabel text=""일반 텍스트"" />
<!-- 제목 -->
<utk:UTKLabel text=""제목"" size=""H1"" is-bold=""true"" />
<!-- 보조 텍스트 -->
<utk:UTKLabel text=""설명"" size=""Caption"" variant=""Secondary"" />
<!-- Material Icon과 텍스트 -->
<utk:UTKLabel text=""설정"" material-icon=""settings"" />
<!-- 아이콘 오른쪽 배치 -->
<utk:UTKLabel text=""다음"" material-icon=""arrow_forward"" icon-placement=""Right"" />");
}
#endregion
#region List Initializers
private void InitializeListViewSample(VisualElement root)
{
var listView = root.Q<UTKListView>("listview-sample");
if (listView != null)
{
var items = new List<string>();
for (int i = 1; i <= 20; i++)
items.Add($"Item {i}");
listView.makeItem = () => new Label();
listView.bindItem = (element, index) => ((Label)element).text = items[index];
listView.itemsSource = items;
listView.fixedItemHeight = 24;
}
SetCodeSamples(root,
csharpCode: @"// 기본 사용법
var listView = new UTKListView();
// 데이터 소스 설정
var items = new List<string>();
for (int i = 1; i <= 20; i++)
items.Add($""Item {i}"");
// makeItem: 각 아이템을 표시할 UI 요소 생성
listView.makeItem = () => new Label();
// bindItem: 데이터를 UI 요소에 바인딩
listView.bindItem = (element, index) => ((Label)element).text = items[index];
// 데이터 소스 설정
listView.itemsSource = items;
// 고정 높이 설정 (가상화를 위해 권장)
listView.fixedItemHeight = 24;
// 선택 이벤트
listView.selectionChanged += (items) =>
{
foreach (var item in items)
Debug.Log($""Selected: {item}"");
};",
uxmlCode: @"<!-- 네임스페이스 선언 -->
<ui:UXML xmlns:utk=""UVC.UIToolkit"">
<!-- 기본 사용 -->
<utk:UTKListView name=""listview-sample"" />
<!-- 스타일 적용 -->
<utk:UTKListView class=""custom-listview"" style=""height: 300px;"" />
</ui:UXML>");
}
private void InitializeTreeViewSample(VisualElement root)
{
var treeView = root.Q<UTKTreeView>("treeview-sample");
if (treeView != null)
{
var treeItems = new List<TreeViewItemData<string>>
{
new(1, "Parent 1", new List<TreeViewItemData<string>>
{
new(2, "Child 1-1"),
new(3, "Child 1-2"),
}),
new(4, "Parent 2", new List<TreeViewItemData<string>>
{
new(5, "Child 2-1"),
new(6, "Child 2-2", new List<TreeViewItemData<string>>
{
new(7, "Grandchild 2-2-1"),
new(8, "Grandchild 2-2-2"),
}),
}),
new(9, "Parent 3"),
};
treeView.SetRootItems(treeItems);
treeView.Rebuild();
}
SetCodeSamples(root,
csharpCode: @"// 기본 사용법
var treeView = new UTKTreeView();
// 계층적 데이터 생성
var treeItems = new List<TreeViewItemData<string>>
{
new(1, ""Parent 1"", new List<TreeViewItemData<string>>
{
new(2, ""Child 1-1""),
new(3, ""Child 1-2""),
}),
new(4, ""Parent 2"", new List<TreeViewItemData<string>>
{
new(5, ""Child 2-1""),
new(6, ""Child 2-2"", new List<TreeViewItemData<string>>
{
new(7, ""Grandchild 2-2-1""),
new(8, ""Grandchild 2-2-2""),
}),
}),
new(9, ""Parent 3""),
};
// 트리 데이터 설정
treeView.SetRootItems(treeItems);
treeView.Rebuild();
// 선택 이벤트
treeView.selectionChanged += (items) =>
{
foreach (var item in items)
Debug.Log($""Selected: {item}"");
};",
uxmlCode: @"<!-- 네임스페이스 선언 -->
<ui:UXML xmlns:utk=""UVC.UIToolkit"">
<!-- 기본 사용 -->
<utk:UTKTreeView name=""treeview-sample"" />
<!-- 스타일 적용 -->
<utk:UTKTreeView class=""custom-treeview"" style=""height: 300px;"" />
</ui:UXML>");
}
private class SampleListItem
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Status { get; set; } = "";
public int Progress { get; set; }
}
private void InitializeMultiColumnListViewSample(VisualElement root)
{
var listView = root.Q<UTKMultiColumnListView>("multicolumn-listview-sample");
if (listView != null)
{
listView.columns.Add(new Column { name = "id", title = "ID", width = 50 });
listView.columns.Add(new Column { name = "name", title = "Name", width = 150, stretchable = true });
listView.columns.Add(new Column { name = "status", title = "Status", width = 100 });
listView.columns.Add(new Column { name = "progress", title = "Progress", width = 80 });
var items = new List<SampleListItem>
{
new() { Id = 1, Name = "Task Alpha", Status = "Active", Progress = 75 },
new() { Id = 2, Name = "Task Beta", Status = "Pending", Progress = 30 },
new() { Id = 3, Name = "Task Gamma", Status = "Completed", Progress = 100 },
new() { Id = 4, Name = "Task Delta", Status = "Active", Progress = 50 },
new() { Id = 5, Name = "Task Epsilon", Status = "Cancelled", Progress = 0 },
};
listView.itemsSource = items;
listView.fixedItemHeight = 24;
listView.columns["id"].makeCell = () => new Label();
listView.columns["id"].bindCell = (e, i) => ((Label)e).text = items[i].Id.ToString();
listView.columns["name"].makeCell = () => new Label();
listView.columns["name"].bindCell = (e, i) => ((Label)e).text = items[i].Name;
listView.columns["status"].makeCell = () => new Label();
listView.columns["status"].bindCell = (e, i) => ((Label)e).text = items[i].Status;
listView.columns["progress"].makeCell = () => new Label();
listView.columns["progress"].bindCell = (e, i) => ((Label)e).text = $"{items[i].Progress}%";
}
}
private class SampleTreeItem
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Type { get; set; } = "";
public string Size { get; set; } = "";
}
private void InitializeMultiColumnTreeViewSample(VisualElement root)
{
var treeView = root.Q<UTKMultiColumnTreeView>("multicolumn-treeview-sample");
if (treeView != null)
{
treeView.columns.Add(new Column { name = "name", title = "Name", width = 200, stretchable = true });
treeView.columns.Add(new Column { name = "type", title = "Type", width = 100 });
treeView.columns.Add(new Column { name = "size", title = "Size", width = 80 });
var rootItems = new List<TreeViewItemData<SampleTreeItem>>
{
new(1, new SampleTreeItem { Id = 1, Name = "Documents", Type = "Folder", Size = "2.5 GB" },
new List<TreeViewItemData<SampleTreeItem>>
{
new(11, new SampleTreeItem { Id = 11, Name = "Reports", Type = "Folder", Size = "500 MB" },
new List<TreeViewItemData<SampleTreeItem>>
{
new(111, new SampleTreeItem { Id = 111, Name = "Q1_Report.pdf", Type = "PDF", Size = "2.3 MB" }),
new(112, new SampleTreeItem { Id = 112, Name = "Q2_Report.pdf", Type = "PDF", Size = "1.8 MB" }),
}),
new(12, new SampleTreeItem { Id = 12, Name = "Images", Type = "Folder", Size = "1.2 GB" }),
}),
new(2, new SampleTreeItem { Id = 2, Name = "Projects", Type = "Folder", Size = "5.0 GB" },
new List<TreeViewItemData<SampleTreeItem>>
{
new(21, new SampleTreeItem { Id = 21, Name = "ProjectA", Type = "Folder", Size = "2.0 GB" }),
new(22, new SampleTreeItem { Id = 22, Name = "ProjectB", Type = "Folder", Size = "3.0 GB" }),
}),
new(3, new SampleTreeItem { Id = 3, Name = "Config.json", Type = "JSON", Size = "4 KB" }),
};
treeView.SetRootItems(rootItems);
treeView.fixedItemHeight = 22;
treeView.columns["name"].makeCell = () => new Label();
treeView.columns["name"].bindCell = (e, i) =>
{
var item = treeView.GetItemDataForIndex<SampleTreeItem>(i);
((Label)e).text = item.Name;
};
treeView.columns["type"].makeCell = () => new Label();
treeView.columns["type"].bindCell = (e, i) =>
{
var item = treeView.GetItemDataForIndex<SampleTreeItem>(i);
((Label)e).text = item.Type;
};
treeView.columns["size"].makeCell = () => new Label();
treeView.columns["size"].bindCell = (e, i) =>
{
var item = treeView.GetItemDataForIndex<SampleTreeItem>(i);
((Label)e).text = item.Size;
};
treeView.ExpandAll();
}
}
private void InitializeScrollViewSample(VisualElement root)
{
// Horizontal scroll
var horizontalContainer = root.Q<VisualElement>("horizontal-scroll-container");
if (horizontalContainer != null)
{
var horizontalScroll = new UTKScrollView();
horizontalScroll.mode = ScrollViewMode.Horizontal;
horizontalScroll.style.height = 150;
horizontalScroll.style.width = 200;
var horizontalContent = new VisualElement();
horizontalContent.style.flexDirection = FlexDirection.Row;
for (int i = 1; i <= 15; i++)
{
var item = new Label($"H-Item {i}");
item.style.minWidth = 80;
item.style.marginRight = 8;
horizontalContent.Add(item);
}
horizontalScroll.Add(horizontalContent);
horizontalContainer.Add(horizontalScroll);
}
// Both scroll
var bothContainer = root.Q<VisualElement>("both-scroll-container");
if (bothContainer != null)
{
var bothScroll = new UTKScrollView();
bothScroll.mode = ScrollViewMode.VerticalAndHorizontal;
bothScroll.style.height = 150;
bothScroll.style.width = 200;
for (int i = 1; i <= 10; i++)
{
var item = new Label($"This is a very long scrollable item number {i} that requires horizontal scrolling");
item.style.whiteSpace = WhiteSpace.NoWrap;
bothScroll.Add(item);
}
bothContainer.Add(bothScroll);
}
}
#endregion
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 80d5e7a49b6ff724c9626bac6ba6759e

View File

@@ -0,0 +1,637 @@
#nullable enable
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.UIToolkit;
/// <summary>
/// UTKStyleGuideSample의 Modal, Tab, Picker 카테고리 Initialize 메서드들
/// </summary>
public partial class UTKStyleGuideSample
{
#region Tab Initializer
private void InitializeTabViewSample(VisualElement root)
{
var tabContainer = root.Q<VisualElement>("tabview-container");
if (tabContainer != null)
{
var tabView = new UTKTabView();
tabView.style.width = 400;
tabView.style.height = 200;
tabView.AddUTKTab("Tab 1", new Label("Content for Tab 1"));
tabView.AddUTKTab("Tab 2", new Label("Content for Tab 2"));
tabView.AddUTKTab("Tab 3", new Label("Content for Tab 3"));
tabContainer.Add(tabView);
}
SetCodeSamples(root,
csharpCode: @"// 기본 사용법
var tabView = new UTKTabView();
tabView.style.width = 400;
tabView.style.height = 200;
// 탭 추가
tabView.AddUTKTab(""Tab 1"", new Label(""Content for Tab 1""));
tabView.AddUTKTab(""Tab 2"", new Label(""Content for Tab 2""));
tabView.AddUTKTab(""Tab 3"", new Label(""Content for Tab 3""));
// 복잡한 콘텐츠 추가
var contentContainer = new VisualElement();
contentContainer.Add(new Label(""복잡한 콘텐츠""));
contentContainer.Add(new UTKButton(""버튼""));
tabView.AddUTKTab(""Tab 4"", contentContainer);
// 탭 선택 이벤트
tabView.OnTabChanged += (index) =>
{
Debug.Log($""선택된 탭 인덱스: {index}"");
};
// 프로그램으로 탭 선택
tabView.SelectTab(1); // 두 번째 탭 선택
// 현재 선택된 탭 인덱스
var currentTab = tabView.SelectedTabIndex;",
uxmlCode: @"<!-- UTKTabView는 동적 생성 권장 -->
<!-- C# 코드에서 AddUTKTab으로 탭 추가 -->
<!-- 기본 TabView -->
<utk:UTKTabView name=""tab-view-1"" style=""width: 400px; height: 200px;"" />");
}
#endregion
#region Modal Initializers
private void InitializeAlertSample(VisualElement root)
{
if (_root == null) return;
UTKAlert.SetRoot(_root);
var btnInfo = root.Q<UTKButton>("btn-info");
btnInfo?.RegisterCallback<ClickEvent>(_ => ShowInfoAlertAsync().Forget());
var btnSuccess = root.Q<UTKButton>("btn-success");
btnSuccess?.RegisterCallback<ClickEvent>(_ => ShowSuccessAlertAsync().Forget());
var btnWarning = root.Q<UTKButton>("btn-warning");
btnWarning?.RegisterCallback<ClickEvent>(_ => ShowWarningAlertAsync().Forget());
var btnError = root.Q<UTKButton>("btn-error");
btnError?.RegisterCallback<ClickEvent>(_ => ShowErrorAlertAsync().Forget());
var btnConfirm = root.Q<UTKButton>("btn-confirm");
btnConfirm?.RegisterCallback<ClickEvent>(_ => ShowConfirmAlertAsync().Forget());
var btnConfirmCustom = root.Q<UTKButton>("btn-confirm-custom");
btnConfirmCustom?.RegisterCallback<ClickEvent>(_ => ShowConfirmCustomLabelsAsync().Forget());
var btnCallback = root.Q<UTKButton>("btn-callback");
btnCallback?.RegisterCallback<ClickEvent>(_ =>
{
UTKAlert.ShowInfo(_root, "Callback Style", "This uses callback instead of async.",
onClose: () => Debug.Log("Alert closed via callback"));
});
var btnConfirmCallback = root.Q<UTKButton>("btn-confirm-callback");
btnConfirmCallback?.RegisterCallback<ClickEvent>(_ =>
{
UTKAlert.ShowConfirm(_root, "Confirm", "Do you want to proceed?",
onConfirm: () => Debug.Log("Confirmed via callback!"),
onCancel: () => Debug.Log("Cancelled via callback!"));
});
SetCodeSamples(root,
csharpCode: @"// Root 설정 (한 번만)
UTKAlert.SetRoot(rootVisualElement);
// ========================================
// 1. Async/Await 방식 (권장)
// ========================================
// Info Alert
await UTKAlert.ShowInfoAsync(""정보"", ""이것은 정보 메시지입니다."");
// Success Alert
await UTKAlert.ShowSuccessAsync(""성공"", ""작업이 성공적으로 완료되었습니다!"");
// Warning Alert
await UTKAlert.ShowWarningAsync(""경고"", ""주의가 필요합니다."");
// Error Alert
await UTKAlert.ShowErrorAsync(""오류"", ""오류가 발생했습니다!"");
// Confirm Dialog
bool result = await UTKAlert.ShowConfirmAsync(""확인"", ""정말 진행하시겠습니까?"");
if (result)
{
Debug.Log(""사용자가 확인을 눌렀습니다."");
}
else
{
Debug.Log(""사용자가 취소를 눌렀습니다."");
}
// Confirm with Custom Labels
bool deleteResult = await UTKAlert.ShowConfirmAsync(
""항목 삭제"",
""이 항목을 정말 삭제하시겠습니까?"",
confirmLabel: ""삭제"",
cancelLabel: ""유지""
);
// closeOnBlockerClick 옵션 (배경 클릭 시 닫기)
await UTKAlert.ShowInfoAsync(""정보"", ""배경을 클릭해도 닫힙니다."", closeOnBlockerClick: true);
// ========================================
// 2. Callback 방식
// ========================================
// Info with Callback
UTKAlert.ShowInfo(rootVisualElement, ""정보"", ""콜백 방식입니다."",
onClose: () => Debug.Log(""Alert가 닫혔습니다.""));
// Confirm with Callback
UTKAlert.ShowConfirm(rootVisualElement, ""확인"", ""진행하시겠습니까?"",
onConfirm: () => Debug.Log(""확인 클릭!""),
onCancel: () => Debug.Log(""취소 클릭!""));");
}
private async UniTaskVoid ShowInfoAlertAsync()
{
await UTKAlert.ShowInfoAsync("Information", "This is an info message.");
Debug.Log("Info alert closed");
}
private async UniTaskVoid ShowSuccessAlertAsync()
{
await UTKAlert.ShowSuccessAsync("Success", "Operation completed successfully!", closeOnBlockerClick: true);
Debug.Log("Success alert closed");
}
private async UniTaskVoid ShowWarningAlertAsync()
{
await UTKAlert.ShowWarningAsync("Warning", "This is a warning message.");
Debug.Log("Warning alert closed");
}
private async UniTaskVoid ShowErrorAlertAsync()
{
await UTKAlert.ShowErrorAsync("Error", "An error has occurred!");
Debug.Log("Error alert closed");
}
private async UniTaskVoid ShowConfirmAlertAsync()
{
bool result = await UTKAlert.ShowConfirmAsync("Confirm", "Are you sure?");
Debug.Log(result ? "Confirmed!" : "Cancelled!");
}
private async UniTaskVoid ShowConfirmCustomLabelsAsync()
{
bool result = await UTKAlert.ShowConfirmAsync("Delete Item", "Are you sure you want to delete this item?",
confirmLabel: "Delete", cancelLabel: "Keep");
Debug.Log(result ? "Item deleted!" : "Item kept!");
}
private void InitializeToastSample(VisualElement root)
{
var btnInfo = root.Q<UTKButton>("btn-toast-info");
btnInfo?.RegisterCallback<ClickEvent>(_ => UTKToast.Show("This is an info toast!"));
var btnSuccess = root.Q<UTKButton>("btn-toast-success");
btnSuccess?.RegisterCallback<ClickEvent>(_ => UTKToast.ShowSuccess("Operation successful!"));
var btnWarning = root.Q<UTKButton>("btn-toast-warning");
btnWarning?.RegisterCallback<ClickEvent>(_ => UTKToast.ShowWarning("Warning: Check your input!"));
var btnError = root.Q<UTKButton>("btn-toast-error");
btnError?.RegisterCallback<ClickEvent>(_ => UTKToast.ShowError("An error occurred!"));
SetCodeSamples(root,
csharpCode: @"// Root 설정 (한 번만)
UTKToast.SetRoot(rootVisualElement);
// Info Toast (기본)
UTKToast.Show(""이것은 정보 토스트입니다!"");
// Success Toast
UTKToast.ShowSuccess(""작업이 성공적으로 완료되었습니다!"");
// Warning Toast
UTKToast.ShowWarning(""경고: 입력값을 확인하세요!"");
// Error Toast
UTKToast.ShowError(""오류가 발생했습니다!"");
// 지속 시간 설정 (밀리초)
UTKToast.Show(""5초 동안 표시"", 5000);
// 사용 예시
public async UniTask SaveDataAsync()
{
try
{
await SaveToServerAsync();
UTKToast.ShowSuccess(""데이터가 저장되었습니다."");
}
catch (Exception ex)
{
UTKToast.ShowError($""저장 실패: {ex.Message}"");
}
}");
}
private void InitializeTooltipSample(VisualElement root)
{
var btnShort = root.Q<UTKButton>("btn-short-tooltip");
if (btnShort != null)
{
UTKTooltipManager.Instance.AttachTooltip(btnShort, "This is a short tooltip.");
}
var btnLong = root.Q<UTKButton>("btn-long-tooltip");
if (btnLong != null)
{
UTKTooltipManager.Instance.AttachTooltip(btnLong, "This is a longer tooltip message that demonstrates how the tooltip handles multiple lines of text content.");
}
}
#endregion
#region Picker Initializers
private void InitializeColorPickerSample(VisualElement root)
{
if (_root == null) return;
_colorPreviewBox = root.Q<VisualElement>("color-preview-box");
_colorHexLabel = root.Q<Label>("color-hex-label");
if (_colorPreviewBox != null)
{
_colorPreviewBox.style.backgroundColor = _selectedColor;
}
var btnAlpha = root.Q<UTKButton>("btn-color-alpha");
btnAlpha?.RegisterCallback<ClickEvent>(_ => OpenColorPicker(true));
var btnNoAlpha = root.Q<UTKButton>("btn-color-no-alpha");
btnNoAlpha?.RegisterCallback<ClickEvent>(_ => OpenColorPicker(false));
var btnAsync = root.Q<UTKButton>("btn-color-async");
btnAsync?.RegisterCallback<ClickEvent>(_ => OpenColorPickerAsync().Forget());
SetCodeSamples(root,
csharpCode: @"// ========================================
// 1. Callback 방식
// ========================================
// Alpha 포함 (기본)
var picker = UTKColorPicker.Show(rootVisualElement, Color.white, ""색상 선택"", useAlpha: true);
// 색상 변경 이벤트 (실시간)
picker.OnColorChanged += (color) =>
{
Debug.Log($""색상 변경: {ColorUtility.ToHtmlStringRGBA(color)}"");
// 미리보기 업데이트 등
};
// 최종 선택 이벤트
picker.OnColorSelected += (color) =>
{
Debug.Log($""색상 선택됨: {ColorUtility.ToHtmlStringRGBA(color)}"");
// 최종 색상 적용
};
// 취소 이벤트
picker.OnCancelled += () =>
{
Debug.Log(""색상 선택이 취소되었습니다."");
};
// Alpha 없이 (RGB만)
var pickerNoAlpha = UTKColorPicker.Show(
rootVisualElement,
Color.red,
""색상 선택 (Alpha 없음)"",
useAlpha: false
);
// ========================================
// 2. Async/Await 방식 (권장)
// ========================================
// Alpha 포함
Color result = await UTKColorPicker.ShowAsync(
rootVisualElement,
Color.white,
""색상 선택 (Async)"",
useAlpha: true
);
Debug.Log($""선택된 색상: #{ColorUtility.ToHtmlStringRGBA(result)}"");
// Alpha 없이
Color rgbColor = await UTKColorPicker.ShowAsync(
rootVisualElement,
Color.red,
""RGB 색상 선택"",
useAlpha: false
);
Debug.Log($""선택된 RGB: #{ColorUtility.ToHtmlStringRGB(rgbColor)}"");
// 사용 예시
public async UniTask ChangeBackgroundColorAsync()
{
Color newColor = await UTKColorPicker.ShowAsync(
_root,
_currentBackgroundColor,
""배경 색상 선택"",
useAlpha: true
);
_currentBackgroundColor = newColor;
ApplyBackgroundColor(newColor);
}");
}
private void OpenColorPicker(bool useAlpha)
{
if (_root == null) return;
var picker = UTKColorPicker.Show(_root, _selectedColor, "Select Color", useAlpha);
picker.OnColorChanged += (color) =>
{
if (_colorPreviewBox != null)
_colorPreviewBox.style.backgroundColor = color;
if (_colorHexLabel != null)
_colorHexLabel.text = useAlpha
? $"#{ColorUtility.ToHtmlStringRGBA(color)}"
: $"#{ColorUtility.ToHtmlStringRGB(color)}";
};
picker.OnColorSelected += (color) =>
{
_selectedColor = color;
Debug.Log($"Color Selected: #{(useAlpha ? ColorUtility.ToHtmlStringRGBA(color) : ColorUtility.ToHtmlStringRGB(color))}");
};
}
private async UniTaskVoid OpenColorPickerAsync()
{
if (_root == null) return;
Color result = await UTKColorPicker.ShowAsync(_root, _selectedColor, "Select Color (Async)", useAlpha: true);
_selectedColor = result;
if (_colorPreviewBox != null)
_colorPreviewBox.style.backgroundColor = result;
if (_colorHexLabel != null)
_colorHexLabel.text = $"#{ColorUtility.ToHtmlStringRGBA(result)}";
Debug.Log($"[Async] Color Result: #{ColorUtility.ToHtmlStringRGBA(result)}");
}
private void InitializeDatePickerSample(VisualElement root)
{
if (_root == null) return;
UTKDatePicker.SetDayNames(new[] { "일", "월", "화", "수", "목", "금", "토" });
_dateLabel = root.Q<Label>("date-label");
_rangeDateLabel = root.Q<Label>("range-date-label");
if (_dateLabel != null)
_dateLabel.text = $"Selected: {_selectedDate:yyyy-MM-dd}";
if (_rangeDateLabel != null)
_rangeDateLabel.text = $"Range: {_rangeStartDate:yyyy-MM-dd} ~ {_rangeEndDate:yyyy-MM-dd}";
var btnDateOnly = root.Q<UTKButton>("btn-date-only");
btnDateOnly?.RegisterCallback<ClickEvent>(_ => OpenDatePicker(UTKDatePicker.PickerMode.DateOnly));
var btnDateTime = root.Q<UTKButton>("btn-date-time");
btnDateTime?.RegisterCallback<ClickEvent>(_ => OpenDatePicker(UTKDatePicker.PickerMode.DateAndTime));
var btnDateAsync = root.Q<UTKButton>("btn-date-async");
btnDateAsync?.RegisterCallback<ClickEvent>(_ => OpenDatePickerAsync().Forget());
var btnRange = root.Q<UTKButton>("btn-range");
btnRange?.RegisterCallback<ClickEvent>(_ => OpenDateRangePicker());
var btnRangeAsync = root.Q<UTKButton>("btn-range-async");
btnRangeAsync?.RegisterCallback<ClickEvent>(_ => OpenDateRangePickerAsync().Forget());
SetCodeSamples(root,
csharpCode: @"// 요일 이름 설정 (선택사항, 한 번만)
UTKDatePicker.SetDayNames(new[] { ""일"", ""월"", ""화"", ""수"", ""목"", ""금"", ""토"" });
// ========================================
// 1. 단일 날짜 선택 - Callback 방식
// ========================================
// Date Only
var datePicker = UTKDatePicker.Show(
rootVisualElement,
DateTime.Today,
UTKDatePicker.PickerMode.DateOnly,
""날짜 선택""
);
datePicker.OnDateSelected += (date) =>
{
Debug.Log($""선택된 날짜: {date:yyyy-MM-dd}"");
};
datePicker.OnCancelled += () =>
{
Debug.Log(""날짜 선택이 취소되었습니다."");
};
// Date & Time
var dateTimePicker = UTKDatePicker.Show(
rootVisualElement,
DateTime.Now,
UTKDatePicker.PickerMode.DateAndTime,
""날짜 및 시간 선택""
);
dateTimePicker.OnDateSelected += (date) =>
{
Debug.Log($""선택된 날짜/시간: {date:yyyy-MM-dd HH:mm}"");
};
// ========================================
// 2. 단일 날짜 선택 - Async/Await 방식 (권장)
// ========================================
// Date Only
DateTime? dateResult = await UTKDatePicker.ShowAsync(
rootVisualElement,
DateTime.Today,
UTKDatePicker.PickerMode.DateOnly,
""날짜 선택 (Async)""
);
if (dateResult.HasValue)
{
Debug.Log($""선택된 날짜: {dateResult.Value:yyyy-MM-dd}"");
}
else
{
Debug.Log(""날짜 선택이 취소되었습니다."");
}
// Date & Time
DateTime? dateTimeResult = await UTKDatePicker.ShowAsync(
rootVisualElement,
DateTime.Now,
UTKDatePicker.PickerMode.DateAndTime,
""날짜 및 시간 선택""
);
if (dateTimeResult.HasValue)
{
Debug.Log($""선택된 날짜/시간: {dateTimeResult.Value:yyyy-MM-dd HH:mm}"");
}
// ========================================
// 3. 날짜 범위 선택 - Callback 방식
// ========================================
var rangePicker = UTKDatePicker.ShowRange(
rootVisualElement,
DateTime.Today,
DateTime.Today.AddDays(7),
includeTime: false,
""기간 선택""
);
rangePicker.OnDateRangeSelected += (start, end) =>
{
Debug.Log($""선택된 기간: {start:yyyy-MM-dd} ~ {end:yyyy-MM-dd}"");
};
rangePicker.OnCancelled += () =>
{
Debug.Log(""기간 선택이 취소되었습니다."");
};
// ========================================
// 4. 날짜 범위 선택 - Async/Await 방식 (권장)
// ========================================
var rangeResult = await UTKDatePicker.ShowRangeAsync(
rootVisualElement,
DateTime.Today,
DateTime.Today.AddDays(7),
includeTime: false,
""기간 선택 (Async)""
);
if (rangeResult.HasValue)
{
Debug.Log($""선택된 기간: {rangeResult.Value.Start:yyyy-MM-dd} ~ {rangeResult.Value.End:yyyy-MM-dd}"");
}
else
{
Debug.Log(""기간 선택이 취소되었습니다."");
}
// 시간 포함 범위 선택
var rangeTimeResult = await UTKDatePicker.ShowRangeAsync(
rootVisualElement,
DateTime.Now,
DateTime.Now.AddDays(7),
includeTime: true,
""기간 및 시간 선택""
);
if (rangeTimeResult.HasValue)
{
Debug.Log($""시작: {rangeTimeResult.Value.Start:yyyy-MM-dd HH:mm}"");
Debug.Log($""종료: {rangeTimeResult.Value.End:yyyy-MM-dd HH:mm}"");
}");
}
private void OpenDatePicker(UTKDatePicker.PickerMode mode)
{
if (_root == null) return;
string title = mode == UTKDatePicker.PickerMode.DateOnly ? "Select Date" : "Select Date & Time";
var picker = UTKDatePicker.Show(_root, _selectedDate, mode, title);
picker.OnDateSelected += (date) =>
{
_selectedDate = date;
if (_dateLabel != null)
{
_dateLabel.text = mode == UTKDatePicker.PickerMode.DateOnly
? $"Selected: {date:yyyy-MM-dd}"
: $"Selected: {date:yyyy-MM-dd HH:mm}";
}
Debug.Log($"Date Selected: {date:yyyy-MM-dd HH:mm}");
};
}
private async UniTaskVoid OpenDatePickerAsync()
{
if (_root == null) return;
DateTime? result = await UTKDatePicker.ShowAsync(_root, _selectedDate, UTKDatePicker.PickerMode.DateOnly, "Select Date (Async)");
if (result.HasValue)
{
_selectedDate = result.Value;
if (_dateLabel != null)
_dateLabel.text = $"Selected: {result.Value:yyyy-MM-dd}";
Debug.Log($"[Async] Date Result: {result.Value:yyyy-MM-dd}");
}
else
{
Debug.Log("[Async] Date selection cancelled");
}
}
private void OpenDateRangePicker()
{
if (_root == null) return;
var picker = UTKDatePicker.ShowRange(_root, _rangeStartDate, _rangeEndDate, false, "Select Date Range");
picker.OnDateRangeSelected += (start, end) =>
{
_rangeStartDate = start;
_rangeEndDate = end;
if (_rangeDateLabel != null)
_rangeDateLabel.text = $"Range: {start:yyyy-MM-dd} ~ {end:yyyy-MM-dd}";
Debug.Log($"Date Range Selected: {start:yyyy-MM-dd} ~ {end:yyyy-MM-dd}");
};
}
private async UniTaskVoid OpenDateRangePickerAsync()
{
if (_root == null) return;
var result = await UTKDatePicker.ShowRangeAsync(_root, _rangeStartDate, _rangeEndDate, false, "Select Date Range (Async)");
if (result.HasValue)
{
_rangeStartDate = result.Value.Start;
_rangeEndDate = result.Value.End;
if (_rangeDateLabel != null)
_rangeDateLabel.text = $"Range: {result.Value.Start:yyyy-MM-dd} ~ {result.Value.End:yyyy-MM-dd}";
Debug.Log($"[Async] Range Result: {result.Value.Start:yyyy-MM-dd} ~ {result.Value.End:yyyy-MM-dd}");
}
else
{
Debug.Log("[Async] Date range selection cancelled");
}
}
#endregion
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e39e393718f744746bb6e7142a229a7f

View File

@@ -0,0 +1,312 @@
#nullable enable
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.UIToolkit;
/// <summary>
/// UTKStyleGuideSample의 Window 카테고리 Initialize 메서드들
/// </summary>
public partial class UTKStyleGuideSample
{
#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
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9672bcb94bb58294aaf96cc827f5a665

File diff suppressed because it is too large Load Diff