#nullable enable using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UVC.Core; using UVC.Factory; using UVC.Factory.Component; using UVC.UI.Commands; using UVC.UI.List.ComponentList; using UVC.UI.Menu; namespace UVC.UI.Window { /// /// '컴포넌트 목록' UI 창을 관리하는 클래스입니다. /// 이 창은 팩토리 내의 모든 객체(컴포넌트)를 리스트 형태로 보여주는 역할을 합니다. /// 사용자는 이 창을 통해 객체를 검색하고, 필터링하며, 선택할 수 있습니다. /// /// /// - SingletonScene: 이 클래스가 씬 내에서 단 하나의 인스턴스만 존재하도록 보장합니다. (싱글톤 패턴) /// 이를 통해 다른 스크립트에서 'ComponentListWindow.Instance'로 쉽게 접근할 수 있습니다. /// - IPointerEnterHandler, IPointerExitHandler: 마우스 포인터가 이 UI 창 영역에 들어오거나 나갈 때의 이벤트를 감지합니다. /// 이 인터페이스들을 사용하여 UI 위에 마우스가 있을 때 3D 뷰의 카메라 움직임을 잠시 멈출 수 있습니다. /// public class ComponentListWindow : SingletonScene, IPointerEnterHandler, IPointerExitHandler { // [SerializeField]는 Unity 에디터의 Inspector 창에서 이 변수를 직접 연결할 수 있게 해줍니다. // 이 창이 실제로 제어할 리스트 UI 컴포넌트를 가리킵니다. [Tooltip("실제 데이터 리스트를 표시하는 ComponentList UI 컴포넌트입니다.")] [SerializeField] protected ComponentList? componentList = null; /// /// 이 컴포넌트가 처음 초기화될 때 호출됩니다. (SingletonScene의 일부) /// 'componentList' 변수에 필요한 컴포넌트를 찾아 할당하는 역할을 합니다. /// protected override void Init() { if (componentList == null) { componentList = GetComponentInChildren(); } if (componentList == null) { Debug.LogError("InfiniteScroll component is not assigned or found in Children."); return; } Hide(); } /// /// 리스트에 표시할 데이터를 설정하고 UI를 구성합니다. /// FactoryObjectManager로부터 모든 객체 정보를 가져와 리스트에 넘겨줍니다. /// public void SetupData() { // 팩토리 내 모든 객체 정보를 카테고리별로 정렬하여 가져옵니다. var infos = FactoryObjectManager.Instance.GetFactoryObjectInfosByCategory(); // 가져온 데이터를 ComponentList 컴포넌트에 전달하여 실제 UI 리스트를 생성하도록 합니다. componentList?.SetupData(infos); } /// /// '필터' 버튼을 클릭했을 때 호출되는 메서드입니다. /// 사용자가 쉽게 검색할 수 있도록 도와주는 필터 키워드 메뉴를 보여줍니다. /// public void ShowFilter() { Debug.Log("필터 버튼 클릭됨."); // 컨텍스트 메뉴에 표시할 항목들을 정의합니다. var menuItems = new List { // "카테고리" 메뉴: 클릭 시 검색창에 "@Category "를 자동으로 입력해줍니다. // 생성자: (itemId, displayName, command, commandParameter) new ContextMenuItemData("Menu1", "카테고리", new ActionCommand(()=>{ componentList?.SetSearchText("@Category "); })), new ContextMenuItemData(isSeparator: true), // 구분선 추가 new ContextMenuItemData("Menu2", "구역", new ActionCommand(()=>{ componentList?.SetSearchText("@Area "); })), new ContextMenuItemData(isSeparator: true), // 구분선 추가 new ContextMenuItemData("Menu3", "층", new ActionCommand(()=>{ componentList?.SetSearchText("@Floor "); })), }; // ContextMenuManager를 통해 마우스 위치에 메뉴를 표시합니다. ContextMenuManager.Instance.ShowMenu(menuItems, Input.mousePosition); } /// /// 새로고침 버튼 클릭 시 호출됩니다. /// 리스트의 모든 데이터를 지우고 SetupData를 다시 호출하여 목록을 갱신합니다. /// public void Refresh() { SetupData(); } /// /// 닫기 버튼 클릭 시 호출됩니다. /// 컴포넌트 목록 UI를 비활성화하고, 카메라 컨트롤을 다시 활성화합니다. /// public void Hide() { gameObject.SetActive(false); FactoryCameraController.Instance.Enable = true; // 카메라 컨트롤러 활성화 } /// /// 외부에서 이 창을 다시 화면에 표시하고 싶을 때 호출하는 메서드입니다. /// public void Show() { gameObject.SetActive(true); } /// /// 마우스 포인터가 이 UI 요소의 영역 안으로 들어왔을 때 호출됩니다. /// UI와 상호작용하는 동안 3D 뷰의 카메라가 움직이지 않도록 컨트롤러를 비활성화합니다. /// public virtual void OnPointerEnter(PointerEventData eventData) { FactoryCameraController.Instance.Enable = false; // 카메라 컨트롤러 비활성화 } /// /// 마우스 포인터가 이 UI 요소의 영역 밖으로 나갔을 때 호출됩니다. /// 카메라 컨트롤을 다시 활성화하여 3D 뷰를 조작할 수 있도록 합니다. /// public virtual void OnPointerExit(PointerEventData eventData) { FactoryCameraController.Instance.Enable = true; // 카메라 컨트롤러 활성화 } } }