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