Files
XRLib/Assets/Scripts/UVC/UI/Window/PropertyWindow/UI/RadioGroupPropertyUI.cs
2025-09-25 16:31:52 +09:00

157 lines
5.6 KiB
C#

using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UVC.Extention;
using UVC.UI.Tooltip;
namespace UVC.UI.Window.PropertyWindow.UI
{
/// <summary>
/// RadioGroupProperty를 위한 UI를 제어하는 스크립트입니다.
/// 동적으로 생성된 Toggle들을 사용하여 항목을 선택합니다.
/// </summary>
[RequireComponent(typeof(LayoutElement))]
public class RadioGroupPropertyUI : MonoBehaviour, IPropertyUI
{
[Header("UI Components")]
[SerializeField]
private TextMeshProUGUI _nameLabel; // 속성 이름을 표시할 Text
[SerializeField]
private TextMeshProUGUI _descriptionLabel;
[SerializeField]
private RectTransform _toggleContainer; // Toggle들이 생성될 부모 컨테이너
[SerializeField]
private GameObject _togglePrefab; // 개별 라디오 버튼(Toggle) 프리팹
private RadioGroupProperty _propertyItem;
private PropertyWindow _controller;
private ToggleGroup _toggleGroup;
private readonly List<Toggle> _toggles = new List<Toggle>();
/// <summary>
/// PropertyView에 의해 호출되어 UI를 초기화하고 데이터를 설정합니다.
/// </summary>
public void Setup(IPropertyItem item, PropertyWindow controller)
{
if (!(item is RadioGroupProperty radioItem))
{
Debug.LogError($"RadioGroupPropertyUI에 잘못된 타입의 PropertyItem이 전달되었습니다. {item.GetType()}");
return;
}
if (_togglePrefab == null)
{
Debug.LogError("RadioGroupPropertyUI에 Toggle 프리팹이 연결되지 않았습니다.");
return;
}
_propertyItem = radioItem;
_controller = controller;
// --- 데이터 바인딩 ---
_nameLabel.text = _propertyItem.Name;
// 툴팁 설정 (TooltipHandler 컴포넌트가 있다면 연동)
TooltipHandler tooltipHandler = _nameLabel.GetComponent<TooltipHandler>();
if (tooltipHandler != null && !_propertyItem.Tooltip.IsNullOrEmpty())
{
tooltipHandler.Tooltip = _propertyItem.Tooltip;
}
if (_propertyItem.Description.IsNullOrEmpty())
{
_descriptionLabel.gameObject.SetActive(false);
}
else
{
_descriptionLabel.gameObject.SetActive(true);
_descriptionLabel.text = _propertyItem.Description;
}
// 기존 토글 정리
foreach (Transform child in _toggleContainer)
{
Destroy(child.gameObject);
}
_toggles.Clear();
// ToggleGroup 컴포넌트 가져오기 (없으면 추가)
_toggleGroup = _toggleContainer.GetComponent<ToggleGroup>();
if (_toggleGroup == null)
{
_toggleGroup = _toggleContainer.gameObject.AddComponent<ToggleGroup>();
}
_toggleGroup.allowSwitchOff = false; // 항상 하나는 선택되도록 설정
// ItemsSource를 기반으로 토글 동적 생성
for (int i = 0; i < _propertyItem.ItemsSource.Count; i++)
{
string optionValue = _propertyItem.ItemsSource[i];
GameObject toggleInstance = Instantiate(_togglePrefab, _toggleContainer);
toggleInstance.name = $"RadioToggle_{optionValue}";
Toggle toggle = toggleInstance.GetComponent<Toggle>();
TextMeshProUGUI label = toggleInstance.GetComponentInChildren<TextMeshProUGUI>();
if (toggle != null)
{
_toggles.Add(toggle);
toggle.group = _toggleGroup;
toggle.interactable = !_propertyItem.IsReadOnly;
// 현재 값과 일치하는 토글을 활성화
toggle.isOn = (optionValue == _propertyItem.Value);
// 리스너 등록
toggle.onValueChanged.RemoveAllListeners();
toggle.onValueChanged.AddListener((isOn) =>
{
// 토글이 켜졌을 때만 값 업데이트
if (isOn)
{
OnToggleValueChanged(optionValue);
}
});
}
if (label != null)
{
label.text = optionValue;
}
}
}
/// <summary>
/// 토글 값이 변경되었을 때 호출됩니다.
/// </summary>
/// <param name="selectedValue">선택된 토글에 해당하는 값</param>
private void OnToggleValueChanged(string selectedValue)
{
if(selectedValue == _propertyItem.Value)
{
return; // 값이 변경되지 않았으면 무시
}
// 컨트롤러를 통해 모델의 값을 업데이트합니다.
_controller.UpdatePropertyValue(_propertyItem.Id, _propertyItem.PropertyType, selectedValue);
}
/// <summary>
/// 이 UI 오브젝트가 파괴될 때 Unity에 의해 호출됩니다.
/// </summary>
private void OnDestroy()
{
foreach (var toggle in _toggles)
{
if (toggle != null)
{
toggle.onValueChanged.RemoveAllListeners();
}
}
}
}
}