using UnityEngine;
namespace UVC.UI.Window.PropertyWindow
{
///
/// 속성창의 UI를 담당하는 View 클래스입니다.
/// Controller로부터 데이터를 받아와 동적으로 UI 요소들을 생성하고 관리합니다.
/// 이 클래스는 MonoBehaviour를 상속받아 Unity 씬에 배치될 수 있습니다.
///
public class PropertyView : MonoBehaviour
{
///
/// UI 요소들이 생성될 부모 컨테이너입니다.
/// Unity 에디터에서 Vertical Layout Group 컴포넌트가 추가된 Panel 등을 연결합니다.
///
[Tooltip("속성 UI들이 생성될 부모 Transform (예: Vertical Layout Group이 있는 Panel)")]
[SerializeField] private Transform _container;
// 각 속성 타입에 맞는 UI 프리팹들입니다.
// 실제 프로젝트에서는 이 프리팹들을 만들고 여기에 연결해야 합니다.
[Header("Property UI Prefabs")]
[SerializeField] private GameObject _stringPropertyPrefab;
[SerializeField] private GameObject _numberPropertyPrefab;
[SerializeField] private GameObject _boolPropertyPrefab;
[SerializeField] private GameObject _vector2PropertyPrefab;
[SerializeField] private GameObject _vector3PropertyPrefab;
[SerializeField] private GameObject _colorPropertyPrefab;
[SerializeField] private GameObject _datePropertyPrefab;
[SerializeField] private GameObject _dateTimePropertyPrefab;
[SerializeField] private GameObject _enumPropertyPrefab;
[SerializeField] private GameObject _listPropertyPrefab;
[SerializeField] private GameObject _radioGroupPropertyPrefab;
[SerializeField] private GameObject _numberRangePropertyPrefab;
[SerializeField] private GameObject _dateRangePropertyPrefab;
[SerializeField] private GameObject _dateTimeRangePropertyPrefab;
///
/// View가 상호작용할 Controller 인스턴스입니다.
///
private PropertyWindow _controller;
///
/// Controller를 View에 설정하고 UI를 초기화합니다.
///
/// 사용할 PropertyWindow
public void Initialize(PropertyWindow controller)
{
_controller = controller;
// Controller가 null이 아니면, 이벤트 핸들러를 등록하고 UI를 그립니다.
if (_controller != null)
{
_controller.PropertyValueChanged += OnPropertyValueChanged;
DrawProperties();
}
}
///
/// Controller에 있는 속성 목록을 기반으로 UI를 생성합니다.
///
private void DrawProperties()
{
// UI를 다시 그리기 전에 기존에 생성된 모든 자식 오브젝트를 삭제합니다.
foreach (Transform child in _container)
{
Destroy(child.gameObject);
}
if (_controller == null) return;
// 각 속성 항목에 대해 적절한 UI를 생성합니다.
foreach (var propertyItem in _controller.Properties)
{
// 속성 타입에 맞는 UI 프리팹을 찾습니다.
GameObject prefab = GetPrefabForProperty(propertyItem.PropertyType);
if (prefab != null)
{
// 프리팹을 인스턴스화하여 컨테이너의 자식으로 추가합니다.
GameObject uiInstance = Instantiate(prefab, _container);
// 생성된 UI 인스턴스에서 IPropertyUI 컴포넌트를 찾아 Setup을 호출합니다.
var propertyUI = uiInstance.GetComponent();
if (propertyUI != null)
{
propertyUI.Setup(propertyItem, _controller);
}
else
{
Debug.LogError($"[PropertyView] 프리팹 '{prefab.name}'에 IPropertyUI를 구현한 스크립트가 없습니다.");
}
}
else
{
Debug.LogWarning($"[PropertyView] '{propertyItem.PropertyType}' 타입에 대한 UI 프리팹이 지정되지 않았습니다.");
}
}
}
///
/// 속성 타입에 맞는 UI 프리팹을 반환합니다.
/// 실제 구현에서는 더 많은 case가 필요합니다.
///
private GameObject GetPrefabForProperty(PropertyType type)
{
switch (type)
{
case PropertyType.String:
return _stringPropertyPrefab;
case PropertyType.Int:
return _numberPropertyPrefab;
case PropertyType.Float:
return _numberPropertyPrefab;
case PropertyType.Bool:
return _boolPropertyPrefab;
case PropertyType.Vector2:
return _vector2PropertyPrefab;
case PropertyType.Vector3:
return _vector3PropertyPrefab;
case PropertyType.Color:
return _colorPropertyPrefab;
case PropertyType.Date:
return _datePropertyPrefab;
case PropertyType.DateTime:
return _dateTimePropertyPrefab;
case PropertyType.Enum:
return _enumPropertyPrefab;
case PropertyType.DropdownList:
return _listPropertyPrefab;
case PropertyType.RadioGroup:
return _radioGroupPropertyPrefab;
case PropertyType.IntRange:
return _numberRangePropertyPrefab;
case PropertyType.FloatRange:
return _numberRangePropertyPrefab;
case PropertyType.DateRange:
return _dateRangePropertyPrefab;
case PropertyType.DateTimeRange:
return _dateTimeRangePropertyPrefab;
default:
Debug.LogWarning($"'{type}' 타입에 대한 프리팹이 정의되지 않았습니다.");
return null;
}
}
///
/// Controller에서 PropertyValueChanged 이벤트가 발생했을 때 호출되는 핸들러입니다.
///
private void OnPropertyValueChanged(object sender, PropertyValueChangedEventArgs e)
{
//Debug.Log($"[PropertyView] 속성 변경 감지: ID='{e.PropertyId}', 이전 값='{e.OldValue}', 새 값='{e.NewValue}'");
// 여기서 특정 속성 값의 변경에 따라 다른 UI를 업데이트하는 로직을 추가할 수 있습니다.
// 예: 특정 bool 속성이 false가 되면 다른 속성 UI를 비활성화 처리
// DrawProperties(); // 전체를 다시 그리는 가장 간단하지만 비효율적일 수 있는 방법
}
private void OnDestroy()
{
// 오브젝트가 파괴될 때 이벤트 핸들러를 안전하게 해제합니다. (메모리 누수 방지)
if (_controller != null)
{
_controller.PropertyValueChanged -= OnPropertyValueChanged;
}
}
}
}