Files
EnglewoodLAB/Assets/Sample/UIToolkit/UTKPropertyListWindowSample.cs
2026-03-10 11:35:30 +09:00

748 lines
38 KiB
C#

#nullable enable
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.Locale;
using UVC.UIToolkit;
namespace UVC.Sample.UIToolkit
{
/// <summary>
/// UTKPropertyListWindow 샘플 코드
/// 기존 PropertyWindowSample과 동일한 데이터를 UTKPropertyListWindow로 표시
/// </summary>
public class UTKPropertyListWindowSample : MonoBehaviour
{
[SerializeField] private UIDocument _uiDocument;
[SerializeField]
[Tooltip("시작 시 적용할 테마")]
private UTKTheme initialTheme = UTKTheme.Dark;
private UTKToggle? _themeToggle;
private UTKPropertyListWindow? _propertyWindow;
private UTKPropertyTabListWindow? _propertyTabWindow;
private void Start()
{
bool success = LocalizationManager.Instance.LoadDefaultLocalizationData("KO");
Debug.Log($"LocalizationManager: LoadDefaultLocalizationData success: {success}");
// UIDocument 참조 확인
var doc = GetComponent<UIDocument>();
if (doc == null)
{
Debug.LogError("UIDocument가 할당되지 않았습니다.");
return;
}
_uiDocument = doc;
var toggle = _uiDocument.rootVisualElement.Q<UTKToggle>("toggle");
if (toggle == null)
{
Debug.LogError("UXML에서 UTKToggle을 찾을 수 없습니다.");
return;
}
_themeToggle = toggle;
// PropertyListWindow 샘플
var window = _uiDocument.rootVisualElement.Q<UTKPropertyListWindow>("window");
if (window != null)
{
_propertyWindow = window;
CreateSamplePropertyWindow();
}
// PropertyTabListWindow 샘플
var tabWindow = _uiDocument.rootVisualElement.Q<UTKPropertyTabListWindow>("tabWindow");
if (tabWindow != null)
{
_propertyTabWindow = tabWindow;
CreateSamplePropertyTabWindow();
}
UTKThemeManager.Instance.RegisterRoot(_uiDocument.rootVisualElement);
UTKThemeManager.Instance.SetTheme(initialTheme);
_themeToggle.OnValueChanged += (isOn) =>
{
UTKThemeManager.Instance.SetTheme(!isOn ? UTKTheme.Dark : UTKTheme.Light);
};
}
private void CreateSamplePropertyWindow()
{
if (_propertyWindow == null) return;
_propertyWindow.ShowCloseButton = true;
_propertyWindow.OnCloseClicked += () =>
{
Debug.Log("Property Window Close clicked");
_propertyWindow?.Hide();
};
_propertyWindow.OnPropertyValueChanged += args =>
{
Debug.Log($"Property Changed: {args.PropertyId} {args.PropertyName} ({args.PropertyType}) = {args.NewValue}");
// gap_type 변경 시 해당 분포 속성만 표시
if (args.PropertyId == "gap_type" && args.NewValue is string gapType)
{
UpdateGapVisibility(gapType);
}
};
_propertyWindow.OnPropertyClicked += args =>
{
Debug.Log($"Property Clicked: {args.Id} {args.DisplayName} ({args.PropertyType})");
};
_propertyWindow.OnPropertyButtonClicked += (id, actionName) =>
{
Debug.Log($"Button Clicked: {id} - Action: {actionName}");
if(id == "string_with_btn" && actionName == "string_action")
{
_propertyWindow.SetPropertyValue("string_with_btn", "Button clicked!");
}
};
// 샘플 데이터 생성
var entries = CreateSampleEntries();
_propertyWindow.LoadMixedProperties(entries);
}
/// <summary>
/// UTKPropertyTabListWindow 샘플 데이터 설정
/// 탭별로 서로 다른 데이터 타입(Flat/Grouped/Mixed)을 보여줍니다.
/// </summary>
private void CreateSamplePropertyTabWindow()
{
if (_propertyTabWindow == null) return;
_propertyTabWindow.ShowCloseButton = true;
_propertyTabWindow.OnCloseClicked += () =>
{
Debug.Log("Tab Property Window Close clicked");
_propertyTabWindow?.Hide();
};
_propertyTabWindow.OnTabChanged += (index, data) =>
{
Debug.Log($"Tab Changed: index={index}, name={data?.Name ?? "All"}");
};
_propertyTabWindow.OnPropertyValueChanged += args =>
{
Debug.Log($"[Tab] Property Changed: {args.PropertyId} {args.PropertyName} ({args.PropertyType}) = {args.NewValue}");
};
// === 탭 1: 기본 속성 (Grouped) ===
var basicTab = new TabPropertyData("기본");
var basicGroups = new List<IUTKPropertyGroup>();
var infoGroup = new UTKPropertyGroup("tab_info", "기본 정보");
infoGroup.AddItem(new UTKStringPropertyItem("tab_name", "이름", "오브젝트 A"));
infoGroup.AddItem(new UTKBoolPropertyItem("tab_active", "활성화", true));
infoGroup.AddItem(new UTKEnumPropertyItem("tab_layer", "레이어", SampleLayer.Default));
infoGroup.AddItem(new UTKDropdownPropertyItem("tab_tag", "태그",
new List<string> { "Untagged", "Player", "Enemy" }, "Player"));
basicGroups.Add(infoGroup);
var transformGroup = new UTKPropertyGroup("tab_transform", "Transform");
transformGroup.AddItem(new UTKVector3PropertyItem("tab_pos", "Position", new Vector3(0, 1, 0)));
transformGroup.AddItem(new UTKVector3PropertyItem("tab_rot", "Rotation", Vector3.zero));
transformGroup.AddItem(new UTKVector3PropertyItem("tab_scale", "Scale", Vector3.one));
basicGroups.Add(transformGroup);
basicTab.SetGroupedData(basicGroups);
// === 탭 2: 외관 (Grouped) ===
var appearanceTab = new TabPropertyData("외관");
var appearanceGroups = new List<IUTKPropertyGroup>();
var colorGroup = new UTKPropertyGroup("tab_colors", "색상");
colorGroup.AddItem(new UTKColorPropertyItem("tab_main_color", "메인 색상", Color.blue));
colorGroup.AddItem(new UTKColorPropertyItem("tab_emission", "발광 색상", Color.yellow, true));
colorGroup.AddItem(new UTKFloatPropertyItem("tab_alpha", "투명도", 1f, 0f, 1f, useSlider: true));
appearanceGroups.Add(colorGroup);
var materialGroup = new UTKPropertyGroup("tab_material", "머티리얼");
materialGroup.AddItem(new UTKDropdownPropertyItem("tab_shader", "셰이더",
new List<string> { "Standard", "Unlit", "URP/Lit", "URP/Simple Lit" }, "URP/Lit"));
materialGroup.AddItem(new UTKFloatPropertyItem("tab_metallic", "메탈릭", 0.5f, 0f, 1f, useSlider: true));
materialGroup.AddItem(new UTKFloatPropertyItem("tab_smoothness", "부드러움", 0.5f, 0f, 1f, useSlider: true));
appearanceGroups.Add(materialGroup);
appearanceTab.SetGroupedData(appearanceGroups);
// === 탭 3: 고급 설정 (Flat) ===
var advancedTab = new TabPropertyData("고급");
var advancedItems = new List<IUTKPropertyItem>
{
new UTKBoolPropertyItem("tab_debug", "디버그 모드", false),
new UTKIntPropertyItem("tab_priority", "우선순위", 0, -10, 10, useStepper: true),
new UTKFloatPropertyItem("tab_lod_bias", "LOD Bias", 1.0f, 0.1f, 5.0f, useSlider: true, useStepper: true),
new UTKMultiSelectDropdownPropertyItem("tab_flags", "플래그",
new List<string> { "Static", "Batching", "Navigation", "Occluder", "Occludee" },
new List<string> { "Static", "Batching" }),
new UTKRadioPropertyItem("tab_quality", "품질",
new List<string> { "Low", "Medium", "High", "Ultra" }, 2),
};
advancedTab.SetFlatData(advancedItems);
// === 탭 4: 일정 (Mixed) ===
var scheduleTab = new TabPropertyData("일정");
var scheduleEntries = new List<IUTKPropertyEntry>();
scheduleEntries.Add(new UTKDatePropertyItem("tab_created", "생성일", DateTime.Today.AddDays(-30)));
scheduleEntries.Add(new UTKDateTimePropertyItem("tab_modified", "수정일", DateTime.Now));
var periodGroup = new UTKPropertyGroup("tab_period", "유효 기간");
periodGroup.AddItem(new UTKDateRangePropertyItem("tab_valid", "유효 기간",
DateTime.Today, DateTime.Today.AddMonths(1)));
periodGroup.AddItem(new UTKDateTimeRangePropertyItem("tab_session", "세션 기간",
DateTime.Now, DateTime.Now.AddHours(2)));
scheduleEntries.Add(periodGroup);
scheduleTab.SetMixedData(scheduleEntries);
// 탭 데이터 설정
_propertyTabWindow.SetTabData(new List<TabPropertyData>
{
basicTab,
appearanceTab,
advancedTab,
scheduleTab
});
}
private List<IUTKPropertyEntry> CreateSampleEntries()
{
var entries = new List<IUTKPropertyEntry>();
// ===== Group에 속하지 않은 개별 아이템들 =====
// String (편집 가능)
entries.Add(new UTKStringPropertyItem("string", "String", "Editable text"));
// String with Action Button
var stringWithButton = new UTKStringPropertyItem("string_with_btn", "String Button", "Click the button");
stringWithButton.ActionButton = new UTKButtonItem("btn_string_action", "string_action", "", UTKMaterialIcons.Search,
UTKButton.ButtonVariant.OutlineNormal, UTKButton.ButtonSize.Small);
stringWithButton.ActionButton.IconOnly = true;
stringWithButton.ActionButton.IconSize = 14;
entries.Add(stringWithButton);
var stringWithButton2 = new UTKStringPropertyItem("string_with_btn2", "String Button2", "Click the button");
stringWithButton2.ActionButton = new UTKButtonItem("btn_string_action", "string_action", "Search", UTKMaterialIcons.Search,
UTKButton.ButtonVariant.OutlineNormal, UTKButton.ButtonSize.Small);
stringWithButton2.ActionButton.IconSize = 14;
entries.Add(stringWithButton2);
// String (ShowLabel = false, 전체 너비)
var stringNoLabel = new UTKStringPropertyItem("string_no_label", "No Label String", "Full width input");
stringNoLabel.ShowLabel = false;
entries.Add(stringNoLabel);
// String (읽기 전용)
var roString = new UTKStringPropertyItem("string_ro", "String (RO)", "Read-only text", isReadOnly: true);
entries.Add(roString);
// Bool (편집 가능)
entries.Add(new UTKBoolPropertyItem("bool", "Bool", true));
// Bool (읽기 전용)
var roBool = new UTKBoolPropertyItem("bool_ro", "Bool (RO)", true, true);
entries.Add(roBool);
// Int (편집 가능)
entries.Add(new UTKIntPropertyItem("int", "Int", 42, 0, 100));
// Int (ShowLabel = false)
var intNoLabel = new UTKIntPropertyItem("int_no_label", "No Label Int", 75, 0, 100);
intNoLabel.ShowLabel = false;
entries.Add(intNoLabel);
// Int (읽기 전용)
entries.Add(new UTKIntPropertyItem("int_ro", "Int (RO)", 99, 0, 100, isReadOnly: true));
// Int (편집 가능)
entries.Add(new UTKIntPropertyItem("int1", "Int", 42, 0, 100, true));
// Int (읽기 전용)
entries.Add(new UTKIntPropertyItem("int1_ro", "Int (RO)", 99, 0, 100, true, isReadOnly: true));
// Int stepper (편집 가능)
entries.Add(new UTKIntPropertyItem("int2", "Int2", 42, 0, 100, false, true));
// Int stepper (읽기 전용)
entries.Add(new UTKIntPropertyItem("int2_ro", "Int2 (RO)", 99, 0, 100, false, true, isReadOnly: true));
// Int stepper (편집 가능)
entries.Add(new UTKIntPropertyItem("int3", "Int3", 42, 0, 100, true, true));
// Int stepper (읽기 전용)
entries.Add(new UTKIntPropertyItem("int3_ro", "Int3 (RO)", 99, 0, 100, true, true, isReadOnly: true));
// Float (useSlider=true, useStepper=true)
entries.Add(new UTKFloatPropertyItem("float1", "Float (Slider+Stepper)", 3.14f, 0f, 10f, useSlider: true, useStepper: true));
// Float (useSlider=true, useStepper=false)
entries.Add(new UTKFloatPropertyItem("float2", "Float (Slider)", 5.0f, 0f, 10f, useSlider: true, useStepper: false));
// Float (useSlider=false, useStepper=true)
var floatStepper = new UTKFloatPropertyItem("float3", "Float (Stepper)", 2.5f, 0f, 10f, useSlider: false, useStepper: true)
{
Step = 0.5f // 0.5씩 증감
};
entries.Add(floatStepper);
// Float (useSlider=false, useStepper=false)
entries.Add(new UTKFloatPropertyItem("float4", "Float (Field)", 7.2f, 0f, 10f, useSlider: false, useStepper: false));
// Float (ReadOnly=true)
entries.Add(new UTKFloatPropertyItem("float_ro", "Float (ReadOnly)", 2.71f, 0f, 10f, useSlider: true, useStepper: false, isReadOnly: true));
// Vector2 (편집 가능)
entries.Add(new UTKVector2PropertyItem("vec2", "Vector2", new Vector2(1, 2)));
// Vector2 (읽기 전용)
var roVec2 = new UTKVector2PropertyItem("vec2_ro", "Vector2 (RO)", new Vector2(3, 4));
roVec2.IsReadOnly = true;
entries.Add(roVec2);
// Vector3 (편집 가능)
entries.Add(new UTKVector3PropertyItem("vec3", "Vector3", new Vector3(1, 2, 3)));
// Vector3 (읽기 전용)
var roVec3 = new UTKVector3PropertyItem("vec3_ro", "Vector3 (RO)", new Vector3(4, 5, 6));
roVec3.IsReadOnly = true;
entries.Add(roVec3);
// Color (편집 가능)
entries.Add(new UTKColorPropertyItem("color", "Color", Color.red));
// Color (읽기 전용)
var roColor = new UTKColorPropertyItem("color_ro", "Color (RO)", Color.green, true);
roColor.IsReadOnly = true;
entries.Add(roColor);
// ColorState (편집 가능)
entries.Add(new UTKColorStatePropertyItem("colorstate", "ColorState",
new UTKColorState("Normal", Color.blue)));
// ColorState (읽기 전용)
var roColorState = new UTKColorStatePropertyItem("colorstate_ro", "ColorState (RO)",
new UTKColorState("Locked", Color.gray));
roColorState.IsReadOnly = true;
entries.Add(roColorState);
// Date (편집 가능)
entries.Add(new UTKDatePropertyItem("date", "Date", DateTime.Today));
// Date (읽기 전용)
entries.Add(new UTKDatePropertyItem("date_ro", "Date (RO)", DateTime.Today.AddDays(7), true));
// DateTime (편집 가능)
entries.Add(new UTKDateTimePropertyItem("datetime", "DateTime", DateTime.Now));
// DateTime (읽기 전용)
entries.Add(new UTKDateTimePropertyItem("datetime_ro", "DateTime (RO)", DateTime.Now.AddHours(1), true));
// DateRange (편집 가능)
entries.Add(new UTKDateRangePropertyItem("daterange", "DateRange",
DateTime.Today, DateTime.Today.AddDays(7)));
// DateRange (읽기 전용)
var roDateRange = new UTKDateRangePropertyItem("daterange_ro", "DateRange (RO)",
DateTime.Today.AddDays(10), DateTime.Today.AddDays(20));
roDateRange.IsReadOnly = true;
entries.Add(roDateRange);
// DateTimeRange (편집 가능)
entries.Add(new UTKDateTimeRangePropertyItem("datetimerange", "DateTimeRange",
DateTime.Now, DateTime.Now.AddHours(2)));
// DateTimeRange (읽기 전용)
var roDateTimeRange = new UTKDateTimeRangePropertyItem("datetimerange_ro", "DateTimeRange (RO)",
DateTime.Now.AddHours(3), DateTime.Now.AddHours(5));
roDateTimeRange.IsReadOnly = true;
entries.Add(roDateTimeRange);
// Enum (편집 가능)
entries.Add(new UTKEnumPropertyItem("enum", "Enum", SampleLayer.Default));
// Enum (읽기 전용)
var roEnum = new UTKEnumPropertyItem("enum_ro", "Enum (RO)", SampleLayer.Water);
roEnum.IsReadOnly = true;
entries.Add(roEnum);
// Dropdown (편집 가능)
entries.Add(new UTKDropdownPropertyItem("dropdown", "Dropdown",
new List<string> { "Option A", "Option B", "Option C" }, "Option A"));
// Dropdown (읽기 전용)
var roDropdown = new UTKDropdownPropertyItem("dropdown_ro", "Dropdown (RO)",
new List<string> { "Option X", "Option Y", "Option Z" }, "Option Y");
roDropdown.IsReadOnly = true;
entries.Add(roDropdown);
// MultiSelectDropdown (편집 가능)
entries.Add(new UTKMultiSelectDropdownPropertyItem("multiselect", "MultiSelect",
new List<string> { "Tag1", "Tag2", "Tag3", "Tag4" },
new List<string> { "Tag1", "Tag3" }));
// MultiSelectDropdown (읽기 전용)
var roMultiSelect = new UTKMultiSelectDropdownPropertyItem("multiselect_ro", "MultiSelect (RO)",
new List<string> { "Feature A", "Feature B", "Feature C", "Feature D" },
new List<string> { "Feature B", "Feature C" });
roMultiSelect.IsReadOnly = true;
entries.Add(roMultiSelect);
// Radio (편집 가능)
entries.Add(new UTKRadioPropertyItem("radio", "Radio",
new List<string> { "Choice 1", "Choice 2", "Choice 3" }, 0));
// Radio (읽기 전용)
var roRadio = new UTKRadioPropertyItem("radio_ro", "Radio (RO)",
new List<string> { "Choice A", "Choice B", "Choice C" }, 1);
roRadio.IsReadOnly = true;
entries.Add(roRadio);
// IntRange (편집 가능)
entries.Add(new UTKIntRangePropertyItem("intrange", "IntRange", 10, 90));
// IntRange (읽기 전용)
entries.Add(new UTKIntRangePropertyItem("intrange_ro", "IntRange (RO)", 20, 80, isReadOnly: true));
// IntRange (편집 가능)
entries.Add(new UTKIntRangePropertyItem("intrange2", "IntRange2", 10, 90, useStepper: true));
// IntRange (읽기 전용)
entries.Add(new UTKIntRangePropertyItem("intrange2_ro", "IntRange2 (RO)", 20, 80, useStepper: true, isReadOnly: true));
// FloatRange (편집 가능)
entries.Add(new UTKFloatRangePropertyItem("floatrange", "FloatRange", 1.5f, 8.5f));
// FloatRange (읽기 전용)
var roFloatRange = new UTKFloatRangePropertyItem("floatrange_ro", "FloatRange (RO)", 2.5f, 7.5f);
roFloatRange.IsReadOnly = true;
entries.Add(roFloatRange);
// FloatRange Stepper (편집 가능)
entries.Add(new UTKFloatRangePropertyItem("floatrange2", "FloatRange Stepper", 1.5f, 8.5f, stepperStep: 0.5f, stepperMinValue: 0f, stepperMaxValue: 100f, useStepper: true));
// FloatRange Stepper (읽기 전용)
entries.Add(new UTKFloatRangePropertyItem("floatrange2_ro", "FloatRange Stepper (RO)", 2.5f, 7.5f, stepperStep: 0.5f, stepperMinValue: 0f, stepperMaxValue: 100f, useStepper: true, isReadOnly: true));
// FloatDropdown (FloatField + Dropdown)
entries.Add(new UTKFloatDropdownPropertyItem("floatdropdown1", "FloatDropdown",
1.5f, new List<string> { "mm", "cm", "m", "km" }, "cm"));
// FloatDropdown (Stepper + Dropdown)
entries.Add(new UTKFloatDropdownPropertyItem("floatdropdown2", "FloatDropdown Stepper",
10.0f, new List<string> { "mm", "cm", "m", "km" }, "m",
floatMinValue: 0f, floatMaxValue: 1000f, stepperStep: 0.5f, useStepper: true));
// FloatDropdown (읽기 전용)
entries.Add(new UTKFloatDropdownPropertyItem("floatdropdown_ro", "FloatDropdown (RO)",
5.0f, new List<string> { "mm", "cm", "m", "km" }, "km", isReadOnly: true));
// ===== Group에 속한 아이템들 =====
var timeList = new List<string> { "초(sec)", "분(min)", "시간(hour)" };
var gapGroup = new UTKPropertyGroup("gap", "생산 간격 정책");
gapGroup.AddItem(new UTKDropdownPropertyItem("gap_type", "간격 타입",
new List<string> { "상수", "정규 분포", "균등 분포", "지수 분포", "삼각 분포" }, "상수", showLabel: false));
//상수
gapGroup.AddItem(new UTKFloatDropdownPropertyItem("gap_value", "상수", 1.0f, timeList, "초(sec)"));
//정규 분포
gapGroup.AddItem(new UTKFloatDropdownPropertyItem("gap_normal_mean", "정규 분포 평균치", 1.0f, timeList, "초(sec)"){ IsVisible = false });
gapGroup.AddItem(new UTKFloatDropdownPropertyItem("gap_normal_stddev", "정규 분포 표준 편차", 1.0f, timeList, "초(sec)"){ IsVisible = false });
//균등 분포
gapGroup.AddItem(new UTKFloatDropdownPropertyItem("gap_uniform_min", "균등 분포 최소값", 1.0f, timeList, "초(sec)"){ IsVisible = false });
gapGroup.AddItem(new UTKFloatDropdownPropertyItem("gap_uniform_max", "균등 분포 최대값", 1.0f, timeList, "초(sec)"){ IsVisible = false });
//지수 분포
gapGroup.AddItem(new UTKFloatDropdownPropertyItem("gap_exponential", "지수 분포 평균치", 1.0f, timeList, "초(sec)"){ IsVisible = false });
//삼각 분포
gapGroup.AddItem(new UTKFloatDropdownPropertyItem("gap_triangular_min", "삼각 분포 최소값", 1.0f, timeList, "초(sec)"){ IsVisible = false });
gapGroup.AddItem(new UTKFloatDropdownPropertyItem("gap_triangular_mode", "삼각 분포 최빈값", 1.0f, timeList, "초(sec)"){ IsVisible = false });
gapGroup.AddItem(new UTKFloatDropdownPropertyItem("gap_triangular_max", "삼각 분포 최대값", 1.0f, timeList, "초(sec)"){ IsVisible = false });
entries.Add(gapGroup);
// 기본 속성 그룹 (편집 가능)
var basicGroup = new UTKPropertyGroup("basic", "Basic Properties (Editable)");
basicGroup.AddItem(new UTKStringPropertyItem("name", "Name", "Sample Object"));
// String with Edit Button
var pathItem = new UTKStringPropertyItem("path", "File Path", "C:/Users/Sample/file.txt");
pathItem.ActionButton = new UTKButtonItem("btn_browse", "browse_file", "", UTKMaterialIcons.FolderOpen,
UTKButton.ButtonVariant.OutlineNormal, UTKButton.ButtonSize.Small);
pathItem.ActionButton.IconOnly = true;
pathItem.ActionButton.IconSize = 14;
basicGroup.AddItem(pathItem);
basicGroup.AddItem(new UTKStringPropertyItem("description", "Description", "This is a sample object") { IsMultiline = true });
basicGroup.AddItem(new UTKBoolPropertyItem("active", "Is Active", true));
basicGroup.AddItem(new UTKIntPropertyItem("count", "Count", 10, 0, 100, true));
basicGroup.AddItem(new UTKFloatPropertyItem("speed", "Speed", 1.5f, 0f, 10f, true));
entries.Add(basicGroup);
// 기본 속성 그룹 (읽기 전용)
var basicGroupRO = new UTKPropertyGroup("basic_ro", "Basic Properties (ReadOnly)");
var roName = new UTKStringPropertyItem("name_ro", "Name", "Locked Object");
roName.IsReadOnly = true;
basicGroupRO.AddItem(roName);
var roDesc = new UTKStringPropertyItem("desc_ro", "Description", "Cannot be modified") { IsMultiline = true };
roDesc.IsReadOnly = true;
basicGroupRO.AddItem(roDesc);
var roActive = new UTKBoolPropertyItem("active_ro", "Is Active", false);
roActive.IsReadOnly = true;
basicGroupRO.AddItem(roActive);
var roCount = new UTKIntPropertyItem("count_ro", "Count", 50, 0, 100, true);
roCount.IsReadOnly = true;
basicGroupRO.AddItem(roCount);
var roSpeed = new UTKFloatPropertyItem("speed_ro", "Speed", 5.5f, 0f, 10f, true);
roSpeed.IsReadOnly = true;
basicGroupRO.AddItem(roSpeed);
entries.Add(basicGroupRO);
// Transform 그룹 (편집 가능)
var transformGroup = new UTKPropertyGroup("transform", "Transform (Editable)");
transformGroup.AddItem(new UTKVector3PropertyItem("position", "Position", new Vector3(0, 1, 0)));
transformGroup.AddItem(new UTKVector3PropertyItem("rotation", "Rotation", Vector3.zero));
transformGroup.AddItem(new UTKVector3PropertyItem("scale", "Scale", Vector3.one));
transformGroup.AddItem(new UTKVector2PropertyItem("uv", "UV Offset", new Vector2(0.5f, 0.5f)));
entries.Add(transformGroup);
// Transform 그룹 (읽기 전용)
var transformGroupRO = new UTKPropertyGroup("transform_ro", "Transform (ReadOnly)");
var roPos = new UTKVector3PropertyItem("position_ro", "Position", new Vector3(10, 20, 30));
roPos.IsReadOnly = true;
transformGroupRO.AddItem(roPos);
var roRot = new UTKVector3PropertyItem("rotation_ro", "Rotation", new Vector3(90, 0, 0));
roRot.IsReadOnly = true;
transformGroupRO.AddItem(roRot);
var roScale = new UTKVector3PropertyItem("scale_ro", "Scale", new Vector3(2, 2, 2));
roScale.IsReadOnly = true;
transformGroupRO.AddItem(roScale);
var roUV = new UTKVector2PropertyItem("uv_ro", "UV Offset", new Vector2(0.25f, 0.75f));
roUV.IsReadOnly = true;
transformGroupRO.AddItem(roUV);
entries.Add(transformGroupRO);
// Appearance 그룹 (편집 가능)
var appearanceGroup = new UTKPropertyGroup("appearance", "Appearance (Editable)");
appearanceGroup.AddItem(new UTKColorPropertyItem("mainColor", "Main Color", Color.blue));
appearanceGroup.AddItem(new UTKColorPropertyItem("emissionColor", "Emission Color", Color.yellow, true));
appearanceGroup.AddItem(new UTKColorStatePropertyItem("status", "Status", new UTKColorState("Active", Color.green)));
appearanceGroup.AddItem(new UTKFloatPropertyItem("alpha", "Alpha", 1f, 0f, 1f, true));
entries.Add(appearanceGroup);
// Appearance 그룹 (읽기 전용)
var appearanceGroupRO = new UTKPropertyGroup("appearance_ro", "Appearance (ReadOnly)");
var roMainColor = new UTKColorPropertyItem("mainColor_ro", "Main Color", Color.red);
roMainColor.IsReadOnly = true;
appearanceGroupRO.AddItem(roMainColor);
var roEmission = new UTKColorPropertyItem("emissionColor_ro", "Emission Color", Color.cyan, true);
roEmission.IsReadOnly = true;
appearanceGroupRO.AddItem(roEmission);
var roStatus = new UTKColorStatePropertyItem("status_ro", "Status", new UTKColorState("Disabled", Color.gray));
roStatus.IsReadOnly = true;
appearanceGroupRO.AddItem(roStatus);
var roAlpha = new UTKFloatPropertyItem("alpha_ro", "Alpha", 0.5f, 0f, 1f, true);
roAlpha.IsReadOnly = true;
appearanceGroupRO.AddItem(roAlpha);
entries.Add(appearanceGroupRO);
// Date/Time 그룹 (편집 가능)
var dateGroup = new UTKPropertyGroup("datetime", "Date & Time (Editable)");
dateGroup.AddItem(new UTKDatePropertyItem("createdDate", "Created Date", DateTime.Today.AddDays(-30)));
dateGroup.AddItem(new UTKDateTimePropertyItem("lastModified", "Last Modified", DateTime.Now));
dateGroup.AddItem(new UTKDateRangePropertyItem("validPeriod", "Valid Period", DateTime.Today, DateTime.Today.AddMonths(1)));
dateGroup.AddItem(new UTKDateTimeRangePropertyItem("sessionPeriod", "Session Period", DateTime.Now, DateTime.Now.AddHours(2)));
entries.Add(dateGroup);
// Date/Time 그룹 (읽기 전용)
var dateGroupRO = new UTKPropertyGroup("datetime_ro", "Date & Time (ReadOnly)");
var roCreated = new UTKDatePropertyItem("createdDate_ro", "Created Date", DateTime.Today.AddDays(-60));
roCreated.IsReadOnly = true;
dateGroupRO.AddItem(roCreated);
var roModified = new UTKDateTimePropertyItem("lastModified_ro", "Last Modified", DateTime.Now.AddDays(-1));
roModified.IsReadOnly = true;
dateGroupRO.AddItem(roModified);
var roValid = new UTKDateRangePropertyItem("validPeriod_ro", "Valid Period", DateTime.Today.AddMonths(-1), DateTime.Today);
roValid.IsReadOnly = true;
dateGroupRO.AddItem(roValid);
var roSession = new UTKDateTimeRangePropertyItem("sessionPeriod_ro", "Session Period", DateTime.Now.AddHours(-2), DateTime.Now);
roSession.IsReadOnly = true;
dateGroupRO.AddItem(roSession);
entries.Add(dateGroupRO);
// Selection 그룹 (편집 가능)
var selectionGroup = new UTKPropertyGroup("selection", "Selection (Editable)");
selectionGroup.AddItem(new UTKEnumPropertyItem("layer", "Layer", SampleLayer.Default));
selectionGroup.AddItem(new UTKDropdownPropertyItem("tag", "Tag",
new List<string> { "Untagged", "Player", "Enemy", "Item", "Environment" }, "Player"));
selectionGroup.AddItem(new UTKMultiSelectDropdownPropertyItem("categories", "Categories",
new List<string> { "Physics", "Rendering", "Audio", "UI", "Network" },
new List<string> { "Physics", "Rendering" }));
selectionGroup.AddItem(new UTKRadioPropertyItem("quality", "Quality",
new List<string> { "Low", "Medium", "High", "Ultra" }, 2));
entries.Add(selectionGroup);
// Selection 그룹 (읽기 전용)
var selectionGroupRO = new UTKPropertyGroup("selection_ro", "Selection (ReadOnly)");
var roLayer = new UTKEnumPropertyItem("layer_ro", "Layer", SampleLayer.UI);
roLayer.IsReadOnly = true;
selectionGroupRO.AddItem(roLayer);
var roTag = new UTKDropdownPropertyItem("tag_ro", "Tag",
new List<string> { "Untagged", "Player", "Enemy", "Item", "Environment" }, "Enemy");
roTag.IsReadOnly = true;
selectionGroupRO.AddItem(roTag);
var roCategories = new UTKMultiSelectDropdownPropertyItem("categories_ro", "Categories",
new List<string> { "Physics", "Rendering", "Audio", "UI", "Network" },
new List<string> { "Audio", "UI", "Network" });
roCategories.IsReadOnly = true;
selectionGroupRO.AddItem(roCategories);
var roQuality = new UTKRadioPropertyItem("quality_ro", "Quality",
new List<string> { "Low", "Medium", "High", "Ultra" }, 3);
roQuality.IsReadOnly = true;
selectionGroupRO.AddItem(roQuality);
entries.Add(selectionGroupRO);
// Range 그룹 (편집 가능)
var rangeGroup = new UTKPropertyGroup("range", "Range Properties (Editable)");
rangeGroup.AddItem(new UTKIntRangePropertyItem("levelRange", "Level Range", 1, 50));
rangeGroup.AddItem(new UTKFloatRangePropertyItem("damageRange", "Damage Range", 10.5f, 25.0f));
entries.Add(rangeGroup);
// Range 그룹 (읽기 전용)
var rangeGroupRO = new UTKPropertyGroup("range_ro", "Range Properties (ReadOnly)");
var roLevelRange = new UTKIntRangePropertyItem("levelRange_ro", "Level Range", 25, 75);
roLevelRange.IsReadOnly = true;
rangeGroupRO.AddItem(roLevelRange);
var roDamageRange = new UTKFloatRangePropertyItem("damageRange_ro", "Damage Range", 50.0f, 100.0f);
roDamageRange.IsReadOnly = true;
rangeGroupRO.AddItem(roDamageRange);
entries.Add(rangeGroupRO);
// Button 그룹 (라벨 표시 - ShowLabel = true, 기본값)
var buttonGroup = new UTKPropertyGroup("buttons", "Buttons (With Label)");
// Primary 버튼
buttonGroup.AddItem(new UTKButtonItem("btn_save", "save", "Save", UTKMaterialIcons.Save,
UTKButton.ButtonVariant.Primary, UTKButton.ButtonSize.Medium));
// Normal 버튼
buttonGroup.AddItem(new UTKButtonItem("btn_load", "load", "Load", UTKMaterialIcons.Download,
UTKButton.ButtonVariant.Normal, UTKButton.ButtonSize.Medium));
// Danger 버튼
buttonGroup.AddItem(new UTKButtonItem("btn_delete", "delete", "Delete", UTKMaterialIcons.Delete,
UTKButton.ButtonVariant.Danger, UTKButton.ButtonSize.Medium));
// Icon Only 버튼
var iconOnlyBtn = new UTKButtonItem("btn_settings", "settings", "", UTKMaterialIcons.Settings,
UTKButton.ButtonVariant.OutlinePrimary, UTKButton.ButtonSize.Medium);
iconOnlyBtn.IconOnly = true;
iconOnlyBtn.IconSize = 16;
buttonGroup.AddItem(iconOnlyBtn);
// Text 버튼
buttonGroup.AddItem(new UTKButtonItem("btn_help", "help", "Help", UTKMaterialIcons.Help,
UTKButton.ButtonVariant.Text, UTKButton.ButtonSize.Medium));
entries.Add(buttonGroup);
// Button 그룹 (라벨 없음 - ShowLabel = false, 전체 너비 사용)
var buttonGroupNoLabel = new UTKPropertyGroup("buttons_no_label", "Buttons (No Label)");
// Primary 버튼 (전체 너비)
var btnSaveNoLabel = new UTKButtonItem("btn_save_no_label", "save_no_label", "Save Changes", UTKMaterialIcons.Save,
UTKButton.ButtonVariant.Primary, UTKButton.ButtonSize.Medium);
btnSaveNoLabel.ShowLabel = false;
buttonGroupNoLabel.AddItem(btnSaveNoLabel);
// Normal 버튼 (전체 너비)
var btnLoadNoLabel = new UTKButtonItem("btn_load_no_label", "load_no_label", "Load Data", UTKMaterialIcons.Download,
UTKButton.ButtonVariant.Normal, UTKButton.ButtonSize.Medium);
btnLoadNoLabel.ShowLabel = false;
buttonGroupNoLabel.AddItem(btnLoadNoLabel);
// Danger 버튼 (전체 너비)
var btnDeleteNoLabel = new UTKButtonItem("btn_delete_no_label", "delete_no_label", "Delete All", UTKMaterialIcons.Delete,
UTKButton.ButtonVariant.Danger, UTKButton.ButtonSize.Medium);
btnDeleteNoLabel.ShowLabel = false;
buttonGroupNoLabel.AddItem(btnDeleteNoLabel);
entries.Add(buttonGroupNoLabel);
// Individual Button Items (라벨 표시)
entries.Add(new UTKButtonItem("btn_apply", "apply", "Apply Changes", UTKMaterialIcons.Check,
UTKButton.ButtonVariant.Primary, UTKButton.ButtonSize.Medium));
entries.Add(new UTKButtonItem("btn_reset", "reset", "Reset to Default", UTKMaterialIcons.Refresh,
UTKButton.ButtonVariant.OutlineNormal, UTKButton.ButtonSize.Medium));
// Individual Button Items (라벨 없음 - 전체 너비)
var btnConfirmNoLabel = new UTKButtonItem("btn_confirm_no_label", "confirm_no_label", "Confirm Action", UTKMaterialIcons.CheckCircle,
UTKButton.ButtonVariant.Primary, UTKButton.ButtonSize.Medium);
btnConfirmNoLabel.ShowLabel = false;
entries.Add(btnConfirmNoLabel);
var btnCancelNoLabel = new UTKButtonItem("btn_cancel_no_label", "cancel_no_label", "Cancel Operation", UTKMaterialIcons.Cancel,
UTKButton.ButtonVariant.OutlineNormal, UTKButton.ButtonSize.Medium);
btnCancelNoLabel.ShowLabel = false;
entries.Add(btnCancelNoLabel);
return entries;
}
/// <summary>
/// gap_type 값에 따라 해당 분포 속성의 가시성을 전환합니다.
/// </summary>
private void UpdateGapVisibility(string gapType)
{
Debug.Log($"Updating gap visibility for type: {gapType}");
_propertyWindow.SetPropertyVisibilityBatch(new (string, bool)[]
{
// 상수
("gap_value", gapType == "상수"),
// 정규 분포
("gap_normal_mean", gapType == "정규 분포"),
("gap_normal_stddev", gapType == "정규 분포"),
// 균등 분포
("gap_uniform_min", gapType == "균등 분포"),
("gap_uniform_max", gapType == "균등 분포"),
// 지수 분포
("gap_exponential", gapType == "지수 분포"),
// 삼각 분포
("gap_triangular_min", gapType == "삼각 분포"),
("gap_triangular_mode", gapType == "삼각 분포"),
("gap_triangular_max", gapType == "삼각 분포"),
});
}
private void OnDestroy()
{
_propertyWindow?.Dispose();
_propertyWindow = null;
_propertyTabWindow?.Dispose();
_propertyTabWindow = null;
}
// 샘플 열거형
public enum SampleLayer
{
Default,
TransparentFX,
IgnoreRaycast,
Water,
UI
}
}
}