Files
SHI_Sample_UI/Assets/Scripts/DTNavigation/SidebarNavigationController.cs
2026-03-09 01:05:56 +09:00

124 lines
6.2 KiB
C#

#nullable enable
using DTNavigation.CameraSystem;
using DTNavigation.Config;
using DTNavigation.Model;
using DTNavigation.Presenter;
using DTNavigation.View;
using UnityEngine;
using UnityEngine.UIElements;
namespace DTNavigation
{
/// <summary>
/// 네비게이션 진입점 MonoBehaviour.
/// 사이드바·탑바 Presenter를 초기화하고,
/// CameraController/CameraNavManager와 연결합니다.
/// </summary>
[RequireComponent(typeof(UIDocument))]
public sealed class SidebarNavigationController : MonoBehaviour
{
// ── Inspector 연결 ─────────────────────────────────────────
[Header("카메라 연결 (선택 사항)")]
[Tooltip("마우스 컨트롤러가 붙은 카메라 오브젝트를 연결합니다.\n연결하지 않으면 UI 블로킹이 비활성화됩니다.")]
[SerializeField] private CameraController? _cameraController;
[Tooltip("탭 선택 → 카메라 이동을 담당하는 매니저를 연결합니다.\n연결하지 않으면 카메라 이동이 비활성화됩니다.")]
[SerializeField] private CameraNavManager? _cameraNavManager;
// ── 런타임 참조 ────────────────────────────────────────────
private SidebarPresenter? _sidebarPresenter;
private TabBarPresenter? _tabBarPresenter;
private NavSelectionModel? _selectionModel;
// ──────────────────────────────────────────────────────────
private void Start()
{
var document = GetComponent<UIDocument>();
var root = document.rootVisualElement;
// ── USS 로드 및 적용 ───────────────────────────────────
var sidebarSS = Resources.Load<StyleSheet>(NavigationConfig.SidebarUssPath)
?? throw new System.InvalidOperationException(
$"StyleSheet을 찾을 수 없습니다: Resources/{NavigationConfig.SidebarUssPath}.uss");
root.styleSheets.Add(sidebarSS);
var tabBarSS = Resources.Load<StyleSheet>(NavigationConfig.TabBarUssPath)
?? throw new System.InvalidOperationException(
$"StyleSheet을 찾을 수 없습니다: Resources/{NavigationConfig.TabBarUssPath}.uss");
root.styleSheets.Add(tabBarSS);
// ── 통합 레이아웃 UXML 로드 ───────────────────────────
var treeAsset = Resources.Load<VisualTreeAsset>(NavigationConfig.UxmlPath)
?? throw new System.InvalidOperationException(
$"VisualTreeAsset을 찾을 수 없습니다: Resources/{NavigationConfig.UxmlPath}.uxml");
treeAsset.CloneTree(root);
// ── 공유 선택 모델 ─────────────────────────────────────
_selectionModel = new NavSelectionModel();
_selectionModel.OnSelectionChanged += OnNavItemSelected;
// ── 사이드바 초기화 ────────────────────────────────────
var sidebarView = new SidebarView(root);
_sidebarPresenter = new SidebarPresenter(sidebarView, SidebarConfig.DefaultNavItems, _selectionModel);
_sidebarPresenter.Initialize();
// ── 탑바 초기화 ────────────────────────────────────────
var tabBarView = new TabBarView(root);
_tabBarPresenter = new TabBarPresenter(tabBarView, _selectionModel);
_tabBarPresenter.Initialize();
// ── 카메라 내비게이션 연결 ─────────────────────────────
_cameraNavManager?.Initialize(_selectionModel);
// ── UI 블로킹 등록 (사이드바·탑바만, 콘텐츠 영역 제외) ─
if (_cameraController != null)
RegisterUIBlocking(root);
}
private void OnDestroy()
{
if (_selectionModel != null)
{
_selectionModel.OnSelectionChanged -= OnNavItemSelected;
_selectionModel = null;
}
_sidebarPresenter?.Dispose();
_sidebarPresenter = null;
_tabBarPresenter?.Dispose();
_tabBarPresenter = null;
}
// ── UI 블로킹 ──────────────────────────────────────────────
private void RegisterUIBlocking(VisualElement root)
{
var sidebarRoot = root.Q<VisualElement>("sidebar-root");
var tabbarRoot = root.Q<VisualElement>("tabbar-root");
if (sidebarRoot != null)
{
sidebarRoot.RegisterCallback<PointerEnterEvent>(_ => _cameraController!.OnUIPointerEnter());
sidebarRoot.RegisterCallback<PointerLeaveEvent>(_ => _cameraController!.OnUIPointerLeave());
}
if (tabbarRoot != null)
{
tabbarRoot.RegisterCallback<PointerEnterEvent>(_ => _cameraController!.OnUIPointerEnter());
tabbarRoot.RegisterCallback<PointerLeaveEvent>(_ => _cameraController!.OnUIPointerLeave());
}
}
// ── 선택 이벤트 ───────────────────────────────────────────
/// <summary>
/// 탭/사이드바 항목 선택 시 호출됩니다.
/// 추후 씬 전환, 콘텐츠 패널 갱신 등을 여기에 연결하세요.
/// </summary>
private void OnNavItemSelected(string? itemId)
{
Debug.Log($"[Nav] 선택된 항목: {itemId}");
}
}
}