#nullable enable
using Cysharp.Threading.Tasks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using UnityEngine;
using UnityEngine.UIElements;
namespace SHI.Modal.ISOP
{
///
/// ISOP(조선소 공정 계획) 모달 창을 관리하는 메인 컨트롤러입니다.
///
/// 개요:
///
/// TreeList, ISOPModelView, ISOPChart 세 가지 뷰를 통합 관리하며,
/// 뷰 간의 선택 동기화, 드래그를 통한 뷰 크기 조절, 확장/축소 기능을 제공합니다.
/// UIDocument를 통해 UXML 기반 UI와 연결됩니다.
///
///
/// 주요 기능:
///
/// - glTF 모델과 간트 데이터 동시 로드
/// - TreeList ↔ ModelView ↔ Chart 선택 동기화
/// - 드래그 버튼으로 ModelView/Chart 크기 비율 조절
/// - 개별 뷰 전체화면 확장/복원
/// - TreeList 가시성 토글 시 3D 모델 가시성 동기화
///
///
/// UI 구조:
///
/// ISOPModal (UXML)
/// ├── TreeList (왼쪽 패널) - 모델 계층 구조
/// ├── ISOPModelView (중앙) - 3D 모델 뷰어
/// ├── drag-btn (구분선) - 수평 드래그로 크기 조절
/// └── ISOPChart (오른쪽) - 간트 차트
///
///
/// 사용 예시:
///
/// var modal = Instantiate(isopModalPrefab);
/// await modal.GetComponent<ISOPModal>().LoadData(gltfPath, ganttPath);
///
///
public class ISOPModal : MonoBehaviour
{
[SerializeField]
public UIDocument uiDocument;
private VisualElement? content;
private TreeList? listView;
private ISOPModelView? modelView;
private ISOPChart? chartView;
private Button? closeBtn;
private Button? showTreeBtn;
private Button? dragBtn;
private CancellationTokenSource? _cts;
private bool _suppressSelection = false;
// key<->id 매핑(차트-리스트/모델 동기화)
private readonly Dictionary _keyToId = new Dictionary();
private readonly Dictionary _idToKey = new Dictionary();
private int selectedItemId = -1;
private enum ExpandedSide { None, Model, Chart }
private ExpandedSide _expanded = ExpandedSide.None;
// 드래그 상태 저장
private bool _isDragging = false;
private int _activePointerId = -1;
private float _dragOffset = 0f; // 포인터와 drag 버튼 중심 간 오프셋
// 확장 전 비율 저장
private float _lastModelFlexGrow = 1f;
private float _lastChartFlexGrow = 1f;
// GeometryChangedEvent 콜백 (해제용)
private EventCallback? _contentGeometryChangedCallback;
// 로딩 UI
private VisualElement? _loadingOverlay;
private VisualElement? _loadingSpinner;
private IVisualElementScheduledItem? _spinnerAnimation;
private void OnEnable()
{
OnDestroy(); // 중복 초기화 방지
var root = uiDocument.rootVisualElement;
content = root.Q("content");
// UXML에서 태그로 추가했다면 Query로 찾음
listView = root.Q();
if (listView != null)
{
listView.OnSelectionChanged += OnListItemSelectionChanged;
listView.OnClosed += OnListClosed;
listView.OnVisibilityChanged += OnListVisibilityChanged;
// listView가 다른 요소 위에 표시되도록 설정
listView.style.unityOverflowClipBox = OverflowClipBox.ContentBox;
// 더미 데이터 생성
// var data = GenerateDummyData();
// listView.SetData(data);
}
modelView = root.Q();
if (modelView != null)
{
// 선택 동기화: 모델 -> 리스트/차트
modelView.OnItemSelected += OnModelItemSelected;
modelView.OnExpand += ToggleExpandModel;
// modelView의 내용이 범위를 벗어나지 않도록 overflow 설정
modelView.style.overflow = Overflow.Hidden;
}
chartView = root.Q();
if (chartView != null)
{
chartView.OnExpand += ToggleExpandChart;
}
showTreeBtn = root.Q