#nullable enable using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; namespace UVC.UIToolkit { /// /// PropertyItem 데이터에 해당하는 View를 생성하는 팩토리 클래스입니다. /// /// 주요 기능: /// /// PropertyType에 따라 적절한 View 인스턴스 생성 /// Data 클래스와 View 자동 바인딩 /// 커스텀 View 등록 지원 /// /// /// 사용법: /// /// var data = new UTKFloatPropertyItem("speed", "속도", 1.5f); /// var view = UTKPropertyItemViewFactory.CreateView(data); /// parent.Add(view); /// /// public static class UTKPropertyItemViewFactory { #region Fields private static readonly Dictionary> _customViewFactories = new(); #endregion #region Public Methods /// /// PropertyItem 데이터에 해당하는 View를 생성하고 바인딩합니다. /// /// PropertyItem 데이터 /// 바인딩된 View (VisualElement) public static VisualElement CreateView(IUTKPropertyItem data) { var view = CreateViewInstance(data); view.Bind(data); if (view is VisualElement element) { return element; } Debug.LogError($"[UTKPropertyItemViewFactory] View is not a VisualElement: {view.GetType().Name}"); return new VisualElement(); } /// /// PropertyItem 데이터에 해당하는 View를 생성합니다 (바인딩 없음). /// /// PropertyItem 데이터 (View 설정에 필요한 정보 제공) /// View 인스턴스 public static IUTKPropertyItemView CreateViewInstance(IUTKPropertyItem data) { // 커스텀 팩토리 우선 if (_customViewFactories.TryGetValue(data.PropertyType, out var customFactory)) { return customFactory(); } // 기본 View 생성 - View의 Bind 메서드에서 데이터 속성 동기화 처리 return data.PropertyType switch { UTKPropertyType.String => CreateStringView(data), UTKPropertyType.Int => CreateIntView(data), UTKPropertyType.Float => CreateFloatView(data), UTKPropertyType.Bool => new UTKBoolPropertyItemView(), UTKPropertyType.Vector2 => new UTKVector2PropertyItemView(), UTKPropertyType.Vector3 => new UTKVector3PropertyItemView(), UTKPropertyType.Color => new UTKColorPropertyItemView(), UTKPropertyType.Date => new UTKDatePropertyItemView(), UTKPropertyType.DateTime => new UTKDateTimePropertyItemView(), UTKPropertyType.Enum => CreateEnumView(data), UTKPropertyType.DropdownList => CreateDropdownView(data), UTKPropertyType.MultiSelectDropdownList => CreateMultiSelectDropdownView(data), UTKPropertyType.RadioGroup => CreateRadioView(data), UTKPropertyType.IntRange => new UTKIntRangePropertyItemView(), UTKPropertyType.FloatRange => new UTKFloatRangePropertyItemView(), UTKPropertyType.DateRange => new UTKDateRangePropertyItemView(), UTKPropertyType.DateTimeRange => new UTKDateTimeRangePropertyItemView(), UTKPropertyType.ColorState => new UTKColorStatePropertyItemView(), UTKPropertyType.FloatDropdown => CreateFloatDropdownView(data), UTKPropertyType.Button => CreateButtonView(data), _ => throw new ArgumentException($"Unknown property type: {data.PropertyType}") }; } /// /// PropertyType에 해당하는 빈 View 인스턴스를 생성합니다. /// /// 속성 타입 /// View 인스턴스 public static IUTKPropertyItemView CreateViewInstance(UTKPropertyType propertyType) { // 커스텀 팩토리 우선 if (_customViewFactories.TryGetValue(propertyType, out var customFactory)) { return customFactory(); } return propertyType switch { UTKPropertyType.String => new UTKStringPropertyItemView(), UTKPropertyType.Int => new UTKIntPropertyItemView(), UTKPropertyType.Float => new UTKFloatPropertyItemView(), UTKPropertyType.Bool => new UTKBoolPropertyItemView(), UTKPropertyType.Vector2 => new UTKVector2PropertyItemView(), UTKPropertyType.Vector3 => new UTKVector3PropertyItemView(), UTKPropertyType.Color => new UTKColorPropertyItemView(), UTKPropertyType.Date => new UTKDatePropertyItemView(), UTKPropertyType.DateTime => new UTKDateTimePropertyItemView(), UTKPropertyType.Enum => new UTKEnumPropertyItemView(), UTKPropertyType.DropdownList => new UTKDropdownPropertyItemView(), UTKPropertyType.MultiSelectDropdownList => new UTKMultiSelectDropdownPropertyItemView(), UTKPropertyType.RadioGroup => new UTKRadioPropertyItemView(), UTKPropertyType.IntRange => new UTKIntRangePropertyItemView(), UTKPropertyType.FloatRange => new UTKFloatRangePropertyItemView(), UTKPropertyType.DateRange => new UTKDateRangePropertyItemView(), UTKPropertyType.DateTimeRange => new UTKDateTimeRangePropertyItemView(), UTKPropertyType.ColorState => new UTKColorStatePropertyItemView(), UTKPropertyType.FloatDropdown => new UTKFloatDropdownPropertyItemView(), UTKPropertyType.Button => new UTKButtonItemView(), _ => throw new ArgumentException($"Unknown property type: {propertyType}") }; } /// /// PropertyItem 데이터에 해당하는 View의 Type을 반환합니다. /// View 재사용 시 기존 View와 타입 호환 여부 확인에 사용합니다. /// /// PropertyItem 데이터 /// View Type public static Type GetViewType(IUTKPropertyItem data) { return data.PropertyType switch { UTKPropertyType.String => typeof(UTKStringPropertyItemView), UTKPropertyType.Int => typeof(UTKIntPropertyItemView), UTKPropertyType.Float => typeof(UTKFloatPropertyItemView), UTKPropertyType.Bool => typeof(UTKBoolPropertyItemView), UTKPropertyType.Vector2 => typeof(UTKVector2PropertyItemView), UTKPropertyType.Vector3 => typeof(UTKVector3PropertyItemView), UTKPropertyType.Color => typeof(UTKColorPropertyItemView), UTKPropertyType.Date => typeof(UTKDatePropertyItemView), UTKPropertyType.DateTime => typeof(UTKDateTimePropertyItemView), UTKPropertyType.Enum => typeof(UTKEnumPropertyItemView), UTKPropertyType.DropdownList => typeof(UTKDropdownPropertyItemView), UTKPropertyType.MultiSelectDropdownList => typeof(UTKMultiSelectDropdownPropertyItemView), UTKPropertyType.RadioGroup => typeof(UTKRadioPropertyItemView), UTKPropertyType.IntRange => typeof(UTKIntRangePropertyItemView), UTKPropertyType.FloatRange => typeof(UTKFloatRangePropertyItemView), UTKPropertyType.DateRange => typeof(UTKDateRangePropertyItemView), UTKPropertyType.DateTimeRange => typeof(UTKDateTimeRangePropertyItemView), UTKPropertyType.ColorState => typeof(UTKColorStatePropertyItemView), UTKPropertyType.FloatDropdown => typeof(UTKFloatDropdownPropertyItemView), UTKPropertyType.Button => typeof(UTKButtonItemView), _ => typeof(VisualElement) }; } /// /// 커스텀 View 팩토리를 등록합니다. /// /// 속성 타입 /// View 생성 팩토리 함수 public static void RegisterCustomView(UTKPropertyType propertyType, Func factory) { _customViewFactories[propertyType] = factory; } /// /// 커스텀 View 팩토리를 제거합니다. /// /// 속성 타입 public static void UnregisterCustomView(UTKPropertyType propertyType) { _customViewFactories.Remove(propertyType); } /// /// 모든 커스텀 View 팩토리를 제거합니다. /// public static void ClearCustomViews() { _customViewFactories.Clear(); } #endregion #region Private Methods private static IUTKPropertyItemView CreateStringView(IUTKPropertyItem data) { // UTKStringPropertyItem의 Multiline 속성에 따라 View 생성 if (data is UTKStringPropertyItem stringItem) { return new UTKStringPropertyItemView(stringItem.Id, stringItem.Value ?? "", stringItem.IsMultiline, stringItem.MaxLength, stringItem.IsReadOnly); } return new UTKStringPropertyItemView(); } private static IUTKPropertyItemView CreateIntView(IUTKPropertyItem data) { // UTKIntPropertyItem의 UseSlider 속성에 따라 View 생성 if (data is UTKIntPropertyItem intItem && intItem.UseSlider) { return new UTKIntPropertyItemView("", intItem.Value, intItem.MinValue, intItem.MaxValue, true); } return new UTKIntPropertyItemView(); } private static IUTKPropertyItemView CreateFloatView(IUTKPropertyItem data) { // UTKFloatPropertyItem의 UseSlider 속성에 따라 View 생성 if (data is UTKFloatPropertyItem floatItem && floatItem.UseSlider) { return new UTKFloatPropertyItemView("", floatItem.Value, floatItem.MinValue, floatItem.MaxValue, true); } return new UTKFloatPropertyItemView(); } private static IUTKPropertyItemView CreateEnumView(IUTKPropertyItem data) { // UTKEnumPropertyItem의 Value로 EnumDropDown 초기화 if (data is UTKEnumPropertyItem enumItem && enumItem.Value != null) { return new UTKEnumPropertyItemView("", enumItem.Value); } return new UTKEnumPropertyItemView(); } private static IUTKPropertyItemView CreateDropdownView(IUTKPropertyItem data) { // UTKDropdownPropertyItem의 Choices로 Dropdown 초기화 if (data is UTKDropdownPropertyItem dropdownItem) { return new UTKDropdownPropertyItemView("", dropdownItem.Choices); } return new UTKDropdownPropertyItemView(); } private static IUTKPropertyItemView CreateRadioView(IUTKPropertyItem data) { // UTKRadioPropertyItem의 Choices로 RadioGroup 초기화 if (data is UTKRadioPropertyItem radioItem) { return new UTKRadioPropertyItemView("", radioItem.Choices); } return new UTKRadioPropertyItemView(); } private static IUTKPropertyItemView CreateMultiSelectDropdownView(IUTKPropertyItem data) { // UTKMultiSelectDropdownPropertyItem의 Choices로 MultiSelectDropdown 초기화 if (data is UTKMultiSelectDropdownPropertyItem multiSelectItem) { return new UTKMultiSelectDropdownPropertyItemView("", multiSelectItem.Choices); } return new UTKMultiSelectDropdownPropertyItemView(); } private static IUTKPropertyItemView CreateFloatDropdownView(IUTKPropertyItem data) { // UTKFloatDropdownPropertyItem의 Choices로 View 초기화 if (data is UTKFloatDropdownPropertyItem floatDropdownItem) { return new UTKFloatDropdownPropertyItemView(floatDropdownItem); } return new UTKFloatDropdownPropertyItemView(); } private static IUTKPropertyItemView CreateButtonView(IUTKPropertyItem data) { // UTKButtonItem으로 ButtonView 초기화 if (data is UTKButtonItem buttonItem) { return new UTKButtonItemView(buttonItem); } return new UTKButtonItemView(); } #endregion } }