Files
XRLib/Assets/Scripts/UVC/UI/Window/PropertyWindow/PropertyItem.cs
UVCLimHun 6b78b68229 merge
merge and property
2025-12-24 17:36:01 +09:00

348 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
namespace UVC.UI.Window.PropertyWindow
{
/// <summary>
/// 속성의 값 타입을 정의하는 열거형입니다.
/// View에서 이 타입을 보고 적절한 UI 컨트롤을 생성합니다.
/// </summary>
public enum PropertyType
{
String,
Int,
Float,
Bool,
Vector2,
Vector3,
Color,
Date,
DateTime,
Enum,
DropdownList,
RadioGroup,
IntRange,
FloatRange,
DateRange,
DateTimeRange,
}
/// <summary>
/// 속성 값이 변경되었을 때 전달될 이벤트 데이터 클래스입니다.
/// </summary>
public class PropertyValueChangedEventArgs : EventArgs
{
/// <summary>
/// 변경된 속성의 고유 ID
/// </summary>
public string PropertyId { get; }
/// <summary>
/// 이 인스턴스가 나타내는 속성의 유형을 가져옵니다.
/// </summary>
public PropertyType PropertyType { get; }
/// <summary>
/// 변경 전의 값
/// </summary>
public object OldValue { get; }
/// <summary>
/// 변경 후의 새로운 값
/// </summary>
public object NewValue { get; }
public PropertyValueChangedEventArgs(string propertyId, PropertyType propertyType, object oldValue, object newValue)
{
PropertyId = propertyId;
PropertyType = propertyType;
OldValue = oldValue;
NewValue = newValue;
}
}
/// <summary>
/// 모든 속성 항목이 구현해야 하는 기본 인터페이스입니다.
/// IPropertyEntry를 상속하여 그룹과 혼용하여 사용할 수 있습니다.
/// </summary>
public interface IPropertyItem : IPropertyEntry
{
/// <summary>
/// 속성의 고유 식별자 (필수)
/// </summary>
string Id { get; }
/// <summary>
/// UI에 표시될 속성 이름 (필수)
/// </summary>
string Name { get; }
/// <summary>
/// 속성에 대한 간단한 설명 (선택)
/// </summary>
string Description { get; set; }
/// <summary>
/// 마우스를 올렸을 때 표시될 툴팁 (선택)
/// </summary>
string Tooltip { get; set; }
/// <summary>
/// 읽기 전용 여부. true이면 UI에서 값 수정이 비활성화됩니다.
/// </summary>
bool IsReadOnly { get; set; }
/// <summary>
/// 속성의 현재 값 (object 타입)
/// </summary>
object GetValue();
/// <summary>
/// 속성의 값을 설정합니다.
/// </summary>
/// <param name="value">새로운 값</param>
void SetValue(object value);
/// <summary>
/// 속성의 데이터 타입
/// </summary>
PropertyType PropertyType { get; }
/// <summary>
/// 아이템이 속한 그룹의 ID입니다.
/// null이면 그룹에 속하지 않은 독립 아이템입니다.
/// </summary>
string GroupId { get; set; }
}
/// <summary>
/// IPropertyItem 인터페이스를 구현하는 제네릭 기반의 추상 클래스입니다.
/// 공통적인 기능을 미리 구현하여 코드 중복을 줄입니다.
/// </summary>
/// <typeparam name="T">속성 값의 실제 타입</typeparam>
public abstract class PropertyItem<T> : IPropertyItem
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Tooltip { get; set; }
public bool IsReadOnly { get; set; } = false;
public abstract PropertyType PropertyType { get; }
/// <summary>
/// 렌더링 순서를 결정하는 값입니다. (IPropertyEntry 구현)
/// </summary>
public int Order { get; set; } = 0;
/// <summary>
/// 아이템이 속한 그룹의 ID입니다. null이면 그룹에 속하지 않습니다.
/// </summary>
public string GroupId { get; set; }
/// <summary>
/// 실제 데이터가 저장되는 필드
/// </summary>
protected T _value;
private Action<T>? _setter;
/// <summary>
/// 속성의 현재 값 (제네릭 타입)
/// </summary>
public T Value
{
get => _value;
set => _value = value;
}
protected PropertyItem(string id, string name, T initialValue)
{
Id = id;
Name = name;
_value = initialValue;
}
public PropertyItem<T> Bind(Action<T>? setter)
{
_setter = setter; // 읽기전용이면 null 가능
return this;
}
// IPropertyItem 인터페이스 구현
public object GetValue() => _value;
public void SetValue(object value)
{
// 타입 안정성을 위해 캐스팅 시도
if (value is T typedValue)
{
_value = typedValue;
if (_setter != null)
{
_setter(typedValue);
}
}
else
{
Debug.LogError($"[PropertyItem] ID '{Id}'에 잘못된 타입의 값({value.GetType().Name})이 할당되었습니다. 필요한 타입: {typeof(T).Name}");
}
}
}
#region Concrete Property Classes
// --- 기본 타입 속성 ---
public class StringProperty : PropertyItem<string>
{
public override PropertyType PropertyType => PropertyType.String;
public StringProperty(string id, string name, string initialValue) : base(id, name, initialValue) { }
}
public class IntProperty : PropertyItem<int>
{
public override PropertyType PropertyType => PropertyType.Int;
public bool IsSlider { get; set; } = false; // 슬라이더로 표시할지 여부
public int MinValue { get; set; } = 0; // 슬라이더 최소값
public int MaxValue { get; set; } = 100; // 슬라이더 최대값
public IntProperty(string id, string name, int initialValue, bool isSlider = false, int minValue = 0, int maxValue = 100) : base(id, name, initialValue)
{
this.IsSlider = isSlider;
this.MinValue = minValue;
this.MaxValue = maxValue;
}
}
public class FloatProperty : PropertyItem<float>
{
public override PropertyType PropertyType => PropertyType.Float;
public bool IsSlider { get; set; } = false; // 슬라이더로 표시할지 여부
public float MinValue { get; set; } = 0; // 슬라이더 최소값
public float MaxValue { get; set; } = 1; // 슬라이더 최대값
public FloatProperty(string id, string name, float initialValue, bool isSlider = false, float minValue = 0, float maxValue = 1) : base(id, name, initialValue)
{
this.IsSlider = isSlider;
this.MinValue = minValue;
this.MaxValue = maxValue;
}
}
public class BoolProperty : PropertyItem<bool>
{
public override PropertyType PropertyType => PropertyType.Bool;
public BoolProperty(string id, string name, bool initialValue) : base(id, name, initialValue) { }
}
public class ColorProperty : PropertyItem<Color>
{
public override PropertyType PropertyType => PropertyType.Color;
public ColorProperty(string id, string name, Color initialValue) : base(id, name, initialValue) { }
}
public class DateProperty : PropertyItem<DateTime>
{
public override PropertyType PropertyType => PropertyType.Date;
public DateProperty(string id, string name, DateTime initialValue) : base(id, name, initialValue) { }
}
public class DateTimeProperty : PropertyItem<DateTime>
{
public override PropertyType PropertyType => PropertyType.DateTime;
public DateTimeProperty(string id, string name, DateTime initialValue) : base(id, name, initialValue) { }
}
// --- 복합 타입 속성 ---
public class Vector2Property : PropertyItem<Vector2>
{
public override PropertyType PropertyType => PropertyType.Vector2;
/// <summary>
/// 자식 필드의 이름 목록 (예: "X", "Y")
/// </summary>
public List<string> ChildNames { get; set; } = new List<string> { "X", "Y" };
public Vector2Property(string id, string name, Vector2 initialValue) : base(id, name, initialValue) { }
}
public class Vector3Property : PropertyItem<Vector3>
{
public override PropertyType PropertyType => PropertyType.Vector3;
/// <summary>
/// 자식 필드의 이름 목록 (예: "X", "Y", "Z")
/// </summary>
public List<string> ChildNames { get; set; } = new List<string> { "X", "Y", "Z" };
public Vector3Property(string id, string name, Vector3 initialValue) : base(id, name, initialValue) { }
}
// --- 범위 타입 속성 ---
public class IntRangeProperty : PropertyItem<Tuple<int, int>>
{
public override PropertyType PropertyType => PropertyType.IntRange;
public IntRangeProperty(string id, string name, Tuple<int, int> initialValue) : base(id, name, initialValue) { }
}
public class FloatRangeProperty : PropertyItem<Tuple<float, float>>
{
public override PropertyType PropertyType => PropertyType.FloatRange;
public FloatRangeProperty(string id, string name, Tuple<float, float> initialValue) : base(id, name, initialValue) { }
}
public class DateRangeProperty : PropertyItem<Tuple<DateTime, DateTime>>
{
public override PropertyType PropertyType => PropertyType.DateRange;
public DateRangeProperty(string id, string name, Tuple<DateTime, DateTime> initialValue) : base(id, name, initialValue) { }
}
public class DateTimeRangeProperty : PropertyItem<Tuple<DateTime, DateTime>>
{
public override PropertyType PropertyType => PropertyType.DateTimeRange;
public DateTimeRangeProperty(string id, string name, Tuple<DateTime, DateTime> initialValue) : base(id, name, initialValue) { }
}
// --- 열거형 및 목록 타입 속성 ---
public class EnumProperty : PropertyItem<Enum>
{
public override PropertyType PropertyType => PropertyType.Enum;
/// <summary>
/// UI에서 드롭다운 목록을 채우기 위한 열거형의 타입 정보
/// </summary>
public Type EnumType { get; }
public EnumProperty(string id, string name, Enum initialValue) : base(id, name, initialValue)
{
EnumType = initialValue.GetType();
}
}
public class ListProperty : PropertyItem<string> // 값은 선택된 항목의 값을 저장
{
public override PropertyType PropertyType => PropertyType.DropdownList;
/// <summary>
/// 드롭다운에 표시될 항목 목록
/// </summary>
public List<string> ItemsSource { get; }
public ListProperty(string id, string name, List<string> items, string initialValue) : base(id, name, initialValue)
{
ItemsSource = items ?? new List<string>();
}
}
public class RadioGroupProperty : PropertyItem<string> // 값은 선택된 항목의 값을 저장
{
public override PropertyType PropertyType => PropertyType.RadioGroup;
/// <summary>
/// 드롭다운에 표시될 항목 목록
/// </summary>
public List<string> ItemsSource { get; }
public RadioGroupProperty(string id, string name, List<string> items, string initialValue) : base(id, name, initialValue)
{
ItemsSource = items ?? new List<string>();
}
}
#endregion
}