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; } } } }