137 lines
6.8 KiB
C#
137 lines
6.8 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace UVC.UI.Toolbar.View
|
|
{
|
|
/// <summary>
|
|
/// 툴바 내의 라디오 버튼 그룹(UnityEngine.UI.ToggleGroup)을 생성하고 관리하는 헬퍼 클래스입니다.
|
|
/// ToolbarView로부터 ToggleGroup 관련 로직을 위임받아 처리함으로써 ToolbarView의 복잡도를 낮추고 역할을 분리합니다.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// 주요 역할:
|
|
/// - ToggleGroup 동적 생성: 라디오 버튼 모델의 GroupName을 기반으로 해당하는 ToggleGroup을 찾거나 새로 생성합니다.
|
|
/// - 리소스 관리: 생성된 ToggleGroup GameObject들을 내부적으로 관리하며, 툴바가 정리될 때 함께 파괴하여 메모리 누수를 방지합니다.
|
|
/// - 레이아웃 독립성: 생성된 ToggleGroup GameObject가 툴바의 UI 레이아웃에 영향을 주지 않도록 LayoutElement 컴포넌트를 추가하고 `ignoreLayout`을 true로 설정합니다.
|
|
/// </remarks>
|
|
/// <example>
|
|
/// <code>
|
|
/// // 이 클래스는 ToolbarView 내부에서 다음과 같이 사용됩니다.
|
|
///
|
|
/// // 1. ToolbarView의 Awake 메서드에서 ToggleGroupManager 인스턴스 생성
|
|
/// // public class ToolbarView : MonoBehaviour
|
|
/// // {
|
|
/// // public Transform toolbarContainer;
|
|
/// // private ToggleGroupManager _toggleGroupManager;
|
|
/// //
|
|
/// // void Awake()
|
|
/// // {
|
|
/// // _toggleGroupManager = new ToggleGroupManager(toolbarContainer);
|
|
/// // }
|
|
/// // // ...
|
|
/// // }
|
|
///
|
|
/// // 2. 라디오 버튼(RadioButton)의 UI 프로세서에서 `GetOrCreateToggleGroup` 호출
|
|
/// // public class ToolbarRadioButtonViewProcessor : IButtonViewProcessor
|
|
/// // {
|
|
/// // public void SetupButtonInteractions(ToolbarButtonBase buttonModel, GameObject buttonUIObject, ToolbarView viewContext)
|
|
/// // {
|
|
/// // ToolbarRadioButton radioModel = buttonModel as ToolbarRadioButton;
|
|
/// // Toggle uiToggle = buttonUIObject.GetComponent<Toggle>();
|
|
/// // if (uiToggle != null)
|
|
/// // {
|
|
/// // // viewContext의 GetOrCreateToggleGroup을 호출하면 내부적으로 ToggleGroupManager의 메서드가 실행됩니다.
|
|
/// // uiToggle.group = viewContext.GetOrCreateToggleGroup(radioModel.GroupName);
|
|
/// // }
|
|
/// // }
|
|
/// // }
|
|
///
|
|
/// // 3. 툴바를 정리(Clear)할 때 Manager의 Clear 메서드 호출
|
|
/// // public class ToolbarView : MonoBehaviour
|
|
/// // {
|
|
/// // protected virtual void ClearToolbar()
|
|
/// // {
|
|
/// // // ... 다른 UI 요소 정리 ...
|
|
/// // _toggleGroupManager.Clear(); // 생성된 모든 토글 그룹 GameObject들을 파괴
|
|
/// // }
|
|
/// // }
|
|
/// </code>
|
|
/// </example>
|
|
public class ToggleGroupManager
|
|
{
|
|
private readonly Transform _container;
|
|
private readonly Dictionary<string, ToggleGroup> _toggleGroups = new Dictionary<string, ToggleGroup>();
|
|
|
|
/// <summary>
|
|
/// ToggleGroupManager의 새 인스턴스를 초기화합니다.
|
|
/// </summary>
|
|
/// <param name="container">생성될 ToggleGroup GameObject들이 자식으로 추가될 부모 Transform입니다. 보통 툴바의 컨테이너를 지정합니다.</param>
|
|
public ToggleGroupManager(Transform container)
|
|
{
|
|
_container = container;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 지정된 그룹 이름에 해당하는 UnityEngine.UI.ToggleGroup을 가져오거나, 없으면 새로 생성합니다.
|
|
/// </summary>
|
|
/// <param name="groupName">찾거나 생성할 토글 그룹의 이름입니다.</param>
|
|
/// <returns>요청된 이름에 해당하는 ToggleGroup 컴포넌트입니다.</returns>
|
|
public ToggleGroup GetOrCreateToggleGroup(string groupName)
|
|
{
|
|
if (string.IsNullOrEmpty(groupName))
|
|
{
|
|
Debug.LogError("ToggleGroupManager: GetOrCreateToggleGroup - groupName이 null이거나 비어있습니다.");
|
|
// 그룹 이름이 없는 비정상적인 경우를 위해 임시 그룹을 생성하여 반환합니다.
|
|
GameObject tempGroupObj = new GameObject($"ToggleGroup_UnnamedDynamic");
|
|
tempGroupObj.transform.SetParent(_container, false);
|
|
return tempGroupObj.AddComponent<ToggleGroup>();
|
|
}
|
|
|
|
// 캐시된 딕셔너리에서 그룹 이름으로 ToggleGroup을 찾아봅니다.
|
|
if (!_toggleGroups.TryGetValue(groupName, out ToggleGroup group))
|
|
{
|
|
// 해당하는 ToggleGroup이 없으면 새로 생성합니다.
|
|
GameObject groupObj = new GameObject($"ToggleGroup_{groupName}");
|
|
groupObj.transform.SetParent(_container);
|
|
|
|
// RectTransform을 추가하고 크기를 0으로 설정하여 레이아웃에 영향을 주지 않도록 합니다.
|
|
RectTransform groupRect = groupObj.AddComponent<RectTransform>();
|
|
groupRect.sizeDelta = Vector2.zero;
|
|
groupRect.anchoredPosition = Vector2.zero;
|
|
groupRect.anchorMin = Vector2.zero;
|
|
groupRect.anchorMax = Vector2.one;
|
|
|
|
// ToggleGroup 컴포넌트를 추가합니다.
|
|
group = groupObj.AddComponent<ToggleGroup>();
|
|
group.allowSwitchOff = true; // 모든 버튼이 선택 해제된 상태를 허용합니다. false로 설정하면 Unity가 첫 번째 Toggle을 자동으로 선택합니다.
|
|
|
|
// LayoutElement를 추가하고 ignoreLayout을 true로 설정하여 부모의 LayoutGroup 계산에서 이 GameObject를 무시하도록 합니다.
|
|
LayoutElement element = groupObj.AddComponent<LayoutElement>();
|
|
element.ignoreLayout = true;
|
|
|
|
// 새로 생성된 그룹을 딕셔너리에 추가하여 다음 요청 시 재사용할 수 있도록 합니다.
|
|
_toggleGroups.Add(groupName, group);
|
|
}
|
|
return group;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이 매니저를 통해 생성된 모든 ToggleGroup GameObject들을 파괴하고 내부 캐시를 비웁니다.
|
|
/// 툴바가 다시 렌더링되거나 파괴될 때 호출하여 메모리 누수를 방지합니다.
|
|
/// </summary>
|
|
public void Clear()
|
|
{
|
|
if (_toggleGroups == null) return;
|
|
foreach (var groupObj in _toggleGroups.Values)
|
|
{
|
|
if (groupObj != null && groupObj.gameObject != null)
|
|
{
|
|
// 생성했던 GameObject를 파괴합니다.
|
|
Object.Destroy(groupObj.gameObject);
|
|
}
|
|
}
|
|
_toggleGroups.Clear();
|
|
}
|
|
}
|
|
}
|