스타일 가이드 수정 중
This commit is contained in:
249
Assets/Sample/UIToolkit/UTKStyleGuideSample.Button.cs
Normal file
249
Assets/Sample/UIToolkit/UTKStyleGuideSample.Button.cs
Normal 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
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5eb3d381be2ce2c4db20a29ca901880c
|
||||
511
Assets/Sample/UIToolkit/UTKStyleGuideSample.Icon.cs
Normal file
511
Assets/Sample/UIToolkit/UTKStyleGuideSample.Icon.cs
Normal 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
|
||||
}
|
||||
2
Assets/Sample/UIToolkit/UTKStyleGuideSample.Icon.cs.meta
Normal file
2
Assets/Sample/UIToolkit/UTKStyleGuideSample.Icon.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d238e34921c4c594d9301c629912bac0
|
||||
357
Assets/Sample/UIToolkit/UTKStyleGuideSample.Input.cs
Normal file
357
Assets/Sample/UIToolkit/UTKStyleGuideSample.Input.cs
Normal 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
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96cc8dc4259f8e5408a0cb5d26902cc7
|
||||
372
Assets/Sample/UIToolkit/UTKStyleGuideSample.List.cs
Normal file
372
Assets/Sample/UIToolkit/UTKStyleGuideSample.List.cs
Normal 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
|
||||
}
|
||||
2
Assets/Sample/UIToolkit/UTKStyleGuideSample.List.cs.meta
Normal file
2
Assets/Sample/UIToolkit/UTKStyleGuideSample.List.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80d5e7a49b6ff724c9626bac6ba6759e
|
||||
637
Assets/Sample/UIToolkit/UTKStyleGuideSample.Modal.cs
Normal file
637
Assets/Sample/UIToolkit/UTKStyleGuideSample.Modal.cs
Normal 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
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e39e393718f744746bb6e7142a229a7f
|
||||
312
Assets/Sample/UIToolkit/UTKStyleGuideSample.Window.cs
Normal file
312
Assets/Sample/UIToolkit/UTKStyleGuideSample.Window.cs
Normal 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
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9672bcb94bb58294aaf96cc827f5a665
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user