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