#nullable enable using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; using UVC.UIToolkit; namespace UVC.Sample.UIToolkit { /// /// UTKPropertyWindow 샘플 코드 /// 기존 PropertyWindowSample과 동일한 데이터를 UTKPropertyWindow로 표시 /// public class UTKPropertyWindowSample : MonoBehaviour { [SerializeField] private UIDocument _uiDocument; [SerializeField] [Tooltip("시작 시 적용할 테마")] private UTKTheme initialTheme = UTKTheme.Dark; private UTKToggle _themeToggle; private UTKPropertyWindow _propertyWindow; private void Start() { // UIDocument 참조 확인 var doc = GetComponent(); if (doc == null) { Debug.LogError("UIDocument가 할당되지 않았습니다."); return; } _uiDocument = doc; var toggle = _uiDocument.rootVisualElement.Q("toggle"); if (toggle == null) { Debug.LogError("UXML에서 UTKToggle을 찾을 수 없습니다."); return; } _themeToggle = toggle; var window = _uiDocument.rootVisualElement.Q("window"); if (window == null) { Debug.LogError("UXML에서 UTKPropertyWindow를 찾을 수 없습니다."); return; } _propertyWindow = window; UTKThemeManager.Instance.RegisterRoot(_uiDocument.rootVisualElement); UTKThemeManager.Instance.SetTheme(initialTheme); _themeToggle.OnValueChanged += (isOn) => { UTKThemeManager.Instance.SetTheme(!isOn ? UTKTheme.Dark : UTKTheme.Light); }; var root = _uiDocument.rootVisualElement; CreateSamplePropertyWindow(root); } private void CreateSamplePropertyWindow(VisualElement root) { // 세로 높이를 부모에 맞게 꽉 채우기 _propertyWindow.style.position = Position.Absolute; _propertyWindow.style.top = 0; _propertyWindow.style.bottom = 0; _propertyWindow.style.right = 0; _propertyWindow.style.width = 300; _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}"); }; // 샘플 데이터 생성 var entries = CreateSampleEntries(); _propertyWindow.LoadMixedProperties(entries); root.Add(_propertyWindow); } private List CreateSampleEntries() { var entries = new List(); // ===== Group에 속하지 않은 개별 아이템들 ===== // String (편집 가능) entries.Add(new UTKStringPropertyItem("string", "String", "Editable text")); // 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); roBool.IsReadOnly = true; entries.Add(roBool); // Int (편집 가능) entries.Add(new UTKIntPropertyItem("int", "Int", 42, 0, 100, true)); // Int (읽기 전용) var roInt = new UTKIntPropertyItem("int_ro", "Int (RO)", 99, 0, 100, true); roInt.IsReadOnly = true; entries.Add(roInt); // Float (편집 가능) entries.Add(new UTKFloatPropertyItem("float", "Float", 3.14f, 0f, 10f, true)); // Float (읽기 전용) var roFloat = new UTKFloatPropertyItem("float_ro", "Float (RO)", 2.71f, 0f, 10f, true); roFloat.IsReadOnly = true; entries.Add(roFloat); // 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 (읽기 전용) var roDate = new UTKDatePropertyItem("date_ro", "Date (RO)", DateTime.Today.AddDays(7)); roDate.IsReadOnly = true; entries.Add(roDate); // DateTime (편집 가능) entries.Add(new UTKDateTimePropertyItem("datetime", "DateTime", DateTime.Now)); // DateTime (읽기 전용) var roDateTime = new UTKDateTimePropertyItem("datetime_ro", "DateTime (RO)", DateTime.Now.AddHours(1)); roDateTime.IsReadOnly = true; entries.Add(roDateTime); // 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); // 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 (읽기 전용) var roIntRange = new UTKIntRangePropertyItem("intrange_ro", "IntRange (RO)", 20, 80); roIntRange.IsReadOnly = true; entries.Add(roIntRange); // 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); // ===== Group에 속한 아이템들 ===== // 기본 속성 그룹 (편집 가능) var basicGroup = new UTKPropertyGroup("basic", "Basic Properties (Editable)"); basicGroup.AddItem(new UTKStringPropertyItem("name", "Name", "Sample Object")); 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 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 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); return entries; } private void OnDestroy() { _propertyWindow?.Dispose(); _propertyWindow = null; } // 샘플 열거형 public enum SampleLayer { Default, TransparentFX, IgnoreRaycast, Water, UI } } }