Files
XRLib/Assets/Scripts/UVC/UI/Window/ComponentListWindow.cs
2025-12-08 21:06:05 +09:00

151 lines
5.9 KiB
C#

#nullable enable
using System;
using System.Collections.Generic;
using UnityEngine;
using UVC.UI.List.ComponentList;
namespace UVC.UI.Window
{
/// <summary>
/// '컴포넌트 목록' UI 창을 관리하는 클래스입니다.
/// 이 창은 팩토리 내의 모든 객체(컴포넌트)를 리스트 형태로 보여주는 역할을 합니다.
/// 사용자는 이 창을 통해 객체를 검색하고, 필터링하며, 선택할 수 있습니다.
/// </summary>
/// <remarks>
/// - SingletonScene<T>: 이 클래스가 씬 내에서 단 하나의 인스턴스만 존재하도록 보장합니다. (싱글톤 패턴)
/// 이를 통해 다른 스크립트에서 'ComponentListWindow.Instance'로 쉽게 접근할 수 있습니다.
/// - IPointerEnterHandler, IPointerExitHandler: 마우스 포인터가 이 UI 창 영역에 들어오거나 나갈 때의 이벤트를 감지합니다.
/// 이 인터페이스들을 사용하여 UI 위에 마우스가 있을 때 3D 뷰의 카메라 움직임을 잠시 멈출 수 있습니다.
/// </remarks>
public class ComponentListWindow : MonoBehaviour
{
// [SerializeField]는 Unity 에디터의 Inspector 창에서 이 변수를 직접 연결할 수 있게 해줍니다.
// 이 창이 실제로 제어할 리스트 UI 컴포넌트를 가리킵니다.
[Tooltip("실제 데이터 리스트를 표시하는 ComponentList UI 컴포넌트입니다.")]
[SerializeField]
protected ComponentList? componentList = null;
/// <summary>
/// 아이템 클릭 이벤트.
/// </summary>
public Action<ComponentListItemData>? OnClickItem;
/// <summary>
/// 아이템 마우스 오른쪽 클릭 이벤트.
/// </summary>
public Action<ComponentListItemData>? OnRightClickItem;
/// <summary>
/// 내부 <see cref="ComponentList"/>에 대한 접근자.
/// 이벤트 구독 등 외부에서 리스트에 직접 접근할 때 사용합니다.
/// </summary>
public ComponentList? ComponentList => componentList;
/// <summary>
/// 카테고리 확장/축소 이벤트.
/// </summary>
public Action<ComponentListItemData>? OnCategoryExpand;
/// <summary>
/// 설정 버튼 클릭 이벤트.
/// </summary>
public Action<ComponentListItemData>? OnSettingButtonClick;
/// <summary>
/// 보이기 버튼 클릭 이벤트.
/// </summary>
public Action<ComponentListItemData, bool>? OnVisibleChanged;
/// <summary>
/// 숨기기 버튼 클릭 이벤트.
/// </summary>
public Action<ComponentListItemData>? OnHideButtonClick;
/// <summary>
/// 검색/이동 버튼 클릭 이벤트.
/// </summary>
public Action<ComponentListItemData>? OnFindButtonClick;
/// <summary>
/// refresh 버튼 클릭 이벤트.
/// </summary>
public Action? OnRefreshButtonClick;
/// <summary>
/// 이 컴포넌트가 처음 초기화될 때 호출됩니다. (SingletonScene의 일부)
/// 'componentList' 변수에 필요한 컴포넌트를 찾아 할당하는 역할을 합니다.
/// </summary>
protected virtual void Start()
{
if (componentList == null)
{
componentList = GetComponentInChildren<ComponentList>();
}
if (componentList == null)
{
Debug.LogError("ComponentList component is not assigned or found in Children.");
return;
}
componentList.OnClickItem += (itemData) => OnClickItem?.Invoke(itemData);
componentList.OnRightClickItem += (itemData) => OnRightClickItem?.Invoke(itemData);
componentList.OnCategoryExpand += (itemData) => OnCategoryExpand?.Invoke(itemData);
componentList.OnSettingButtonClick += (itemData) => OnSettingButtonClick?.Invoke(itemData);
componentList.OnShowButtonClick += (itemData) => OnVisibleChanged?.Invoke(itemData, true);
componentList.OnHideButtonClick += (itemData) => OnVisibleChanged?.Invoke(itemData, false);
componentList.OnSearchButtonClick += (itemData) => OnFindButtonClick?.Invoke(itemData);
}
/// <summary>
/// 카테고리별로 그룹화된 데이터로 리스트를 설정합니다.
/// </summary>
/// <param name="objectsData">카테고리 이름을 키로, 해당 카테고리의 아이템 목록을 값으로 하는 딕셔너리</param>
public void SetupData(SortedDictionary<string, List<ComponentListItemData>> objectsData)
{
if (componentList != null)
{
componentList.SetupData(objectsData);
}
}
public void Refresh()
{
OnRefreshButtonClick?.Invoke();
}
/// <summary>
/// 닫기 버튼 클릭 시 호출됩니다.
/// 컴포넌트 목록 UI를 비활성화하고, 카메라 컨트롤을 다시 활성화합니다.
/// </summary>
public void Hide()
{
gameObject.SetActive(false);
}
/// <summary>
/// 외부에서 이 창을 다시 화면에 표시하고 싶을 때 호출하는 메서드입니다.
/// </summary>
public void Show()
{
gameObject.SetActive(true);
}
protected virtual void OnDestroy()
{
// 이벤트 핸들러 정리
OnClickItem = null;
OnRightClickItem = null;
OnCategoryExpand = null;
OnSettingButtonClick = null;
OnVisibleChanged = null;
OnHideButtonClick = null;
OnFindButtonClick = null;
// 참조 정리
componentList = null;
}
}
}