#nullable enable using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; using UVC.UIToolkit; namespace UVC.Sample.UIToolkit { /// /// UTKPropertyListWindow 샘플 코드 /// 기존 PropertyWindowSample과 동일한 데이터를 UTKPropertyListWindow로 표시 /// 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() { // UIDocument 참조 확인 var doc = GetComponent(); if (doc == null) { Debug.LogError("UIDocument가 할당되지 않았습니다."); return; } _uiDocument = doc; UTKThemeManager.Instance.RegisterRoot(_uiDocument.rootVisualElement); UTKThemeManager.Instance.SetTheme(initialTheme); var root = _uiDocument.rootVisualElement; // PropertyListWindow 샘플 var window = root.Q("window"); if (window != null) { _propertyWindow = window; _propertyWindow.style.position = Position.Absolute; _propertyWindow.style.top = 50; _propertyWindow.style.left = 0; _propertyWindow.style.bottom = 0; _propertyWindow.style.width = 300; CreateSamplePropertyWindow(); } // PropertyTabListWindow 샘플 var tabWindow = root.Q("tabWindow"); if (tabWindow != null) { _propertyTabWindow = tabWindow; _propertyTabWindow.style.position = Position.Absolute; _propertyTabWindow.style.top = 50; _propertyTabWindow.style.right = 0; _propertyTabWindow.style.bottom = 0; _propertyTabWindow.style.width = 300; CreateSamplePropertyTabWindow(); } UTKThemeManager.Instance.OnThemeChanged += theme => { UTKThemeManager.Instance.ApplyThemeToElement(_uiDocument.rootVisualElement); }; } 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); } /// /// UTKPropertyTabListWindow 샘플 데이터 설정 /// 탭별로 서로 다른 데이터 타입(Flat/Grouped/Mixed)을 보여줍니다. /// 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("기본", UTKMaterialIcons.Settings); var basicGroups = new List(); 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 { "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("외관", UTKMaterialIcons.Palette); var appearanceGroups = new List(); 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 { "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("고급", UTKMaterialIcons.Tune); var advancedItems = new List { 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 { "Static", "Batching", "Navigation", "Occluder", "Occludee" }, new List { "Static", "Batching" }), new UTKRadioPropertyItem("tab_quality", "품질", new List { "Low", "Medium", "High", "Ultra" }, 2), }; advancedTab.SetFlatData(advancedItems); // === 탭 4: 일정 (Mixed) === var scheduleTab = new TabPropertyData("일정", UTKMaterialIcons.CalendarMonth); var scheduleEntries = new List(); 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 { basicTab, appearanceTab, advancedTab, scheduleTab }); } private List CreateSampleEntries() { var entries = new List(); // ===== 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 { "Option A", "Option B", "Option C" }, "Option A")); // Dropdown (읽기 전용) var roDropdown = new UTKDropdownPropertyItem("dropdown_ro", "Dropdown (RO)", new List { "Option X", "Option Y", "Option Z" }, "Option Y"); roDropdown.IsReadOnly = true; entries.Add(roDropdown); // MultiSelectDropdown (편집 가능) entries.Add(new UTKMultiSelectDropdownPropertyItem("multiselect", "MultiSelect", new List { "Tag1", "Tag2", "Tag3", "Tag4" }, new List { "Tag1", "Tag3" })); // MultiSelectDropdown (읽기 전용) var roMultiSelect = new UTKMultiSelectDropdownPropertyItem("multiselect_ro", "MultiSelect (RO)", new List { "Feature A", "Feature B", "Feature C", "Feature D" }, new List { "Feature B", "Feature C" }); roMultiSelect.IsReadOnly = true; entries.Add(roMultiSelect); // Radio (편집 가능) entries.Add(new UTKRadioPropertyItem("radio", "Radio", new List { "Choice 1", "Choice 2", "Choice 3" }, 0)); // Radio (읽기 전용) var roRadio = new UTKRadioPropertyItem("radio_ro", "Radio (RO)", new List { "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 { "mm", "cm", "m", "km" }, "cm")); // FloatDropdown (Stepper + Dropdown) entries.Add(new UTKFloatDropdownPropertyItem("floatdropdown2", "FloatDropdown Stepper", 10.0f, new List { "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 { "mm", "cm", "m", "km" }, "km", isReadOnly: true)); // ===== Group에 속한 아이템들 ===== var timeList = new List { "초(sec)", "분(min)", "시간(hour)" }; var gapGroup = new UTKPropertyGroup("gap", "생산 간격 정책"); gapGroup.AddItem(new UTKDropdownPropertyItem("gap_type", "간격 타입", new List { "상수", "정규 분포", "균등 분포", "지수 분포", "삼각 분포" }, "상수", 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 { "Untagged", "Player", "Enemy", "Item", "Environment" }, "Player")); selectionGroup.AddItem(new UTKMultiSelectDropdownPropertyItem("categories", "Categories", new List { "Physics", "Rendering", "Audio", "UI", "Network" }, new List { "Physics", "Rendering" })); selectionGroup.AddItem(new UTKRadioPropertyItem("quality", "Quality", new List { "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 { "Untagged", "Player", "Enemy", "Item", "Environment" }, "Enemy"); roTag.IsReadOnly = true; selectionGroupRO.AddItem(roTag); var roCategories = new UTKMultiSelectDropdownPropertyItem("categories_ro", "Categories", new List { "Physics", "Rendering", "Audio", "UI", "Network" }, new List { "Audio", "UI", "Network" }); roCategories.IsReadOnly = true; selectionGroupRO.AddItem(roCategories); var roQuality = new UTKRadioPropertyItem("quality_ro", "Quality", new List { "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; } /// /// gap_type 값에 따라 해당 분포 속성의 가시성을 전환합니다. /// 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 } } }