#nullable enable
using System;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks;
using GLTFast;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.Util;
namespace SHI.Modal.ISOP
{
///
/// glTF/glb 3D 모델을 로드하고 UI Toolkit에서 실시간 렌더링하는 뷰 컴포넌트입니다.
///
/// 개요:
///
/// glTFast 라이브러리를 사용하여 3D 모델을 비동기 로드하고,
/// 전용 카메라로 오프스크린 렌더링하여 RenderTexture를 UI Toolkit의 배경으로 출력합니다.
/// 마우스로 모델을 회전, 이동, 확대/축소할 수 있습니다.
///
///
/// 주요 기능:
///
/// - glTF/glb 모델 비동기 로드 (GLTFast)
/// - 오프스크린 렌더링 (전용 카메라 + RenderTexture)
/// - 마우스 조작: 가운데 버튼=이동, 오른쪽 버튼=회전, 휠=확대/축소
/// - 와이어프레임 모드 토글
/// - 항목 하이라이트 및 가시성 제어
/// - TreeList와 연동되는 계층 구조 생성
///
///
/// 사용 예시:
///
/// var modelView = root.Q<ISOPModelView>();
/// var items = await modelView.LoadModelAsync(gltfPath, cancellationToken);
/// treeList.SetData(items.ToList());
/// modelView.FocusItemById(itemId);
///
///
/// 렌더링 구조:
///
/// - ISOPModelViewRig - 카메라와 조명을 담는 부모 GameObject
/// - ISOPModelViewCamera - 전용 렌더링 카메라 (Layer 6만 렌더링)
/// - ISOPModelViewRoot - 로드된 모델의 루트 GameObject
///
///
[UxmlElement]
public partial class ISOPModelView : VisualElement, IDisposable
{
#region IDisposable
private bool _disposed = false;
#endregion
#region 외부 이벤트 (Public Events)
///
/// 뷰 내부에서 항목이 선택될 때 발생합니다.
/// TreeList와의 선택 동기화에 사용됩니다.
///
public Action? OnItemSelected;
///
/// 모델 뷰 확장 버튼이 클릭될 때 발생합니다.
/// ISOPModal에서 모델 뷰를 전체 화면으로 확장하는 데 사용됩니다.
///
public Action? OnExpand;
#endregion
#region 상수 및 설정 (Constants and Configuration)
/// UXML 파일 경로 (Resources 폴더 기준)
private const string UXML_PATH = "SHI/Modal/ISOP/ISOPModelView";
/// 카메라 배경색 (흰색)
private Color cameraBackgroundColor = new Color(1f, 1f, 1f, 1f);
/// 모델이 렌더링되는 레이어 (Layer 6)
private int modelLayer = 6;
/// 기본 조명 생성 여부
private bool createDefaultLight = true;
/// 이동 속도 (가운데 마우스 드래그)
private float panSpeed = 1.0f;
/// 회전 감도 (픽셀당 회전 각도)
private float rotateDegPerPixel = 0.2f;
/// 확대/축소 속도 (마우스 휠)
private float zoomSpeed = 5f;
/// 와이어프레임 모드 활성화 여부
private bool wireframeMode = true;
#endregion
private Camera? _viewCamera;
private RenderTexture? _rt;
private Material? _wireframeMat;
private bool _wireframeApplied;
// Orbit controls state
private Vector3 _orbitTarget;
private float _orbitDistance = 5f;
private float _yaw = 0f;
private float _pitch = 20f;
// Drag state
private bool _mmbDragging;
private bool _rmbDragging;
private Vector3 _mmbLastPos;
private Vector3 _rmbStartPos;
private float _yawStart;
private float _pitchStart;
private Quaternion _modelStartRot;
private Vector3 _modelStartPos;
private Vector3 _rmbPivot;
private readonly Dictionary _idToObject = new Dictionary();
private readonly Dictionary _originalSharedByRenderer = new Dictionary();
private GameObject? _root;
private int? _focusedId;
// UI Element for rendering
private VisualElement? _renderContainer;
private Button? _expandBtn;
private int itemIdSeed = 1;
public ISOPModelView()
{
// UXML 로드
var visualTree = Resources.Load(UXML_PATH);
if (visualTree != null)
{
visualTree.CloneTree(this);
}
else
{
Debug.LogError($"Failed to load UXML at path: {UXML_PATH}");
}
// 렌더링 컨테이너 생성
_renderContainer = this.Q("render-container");
_expandBtn = this.Q