286 lines
9.1 KiB
C#
286 lines
9.1 KiB
C#
#nullable enable
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
namespace UVC.UI.Tab
|
|
{
|
|
/// <summary>
|
|
/// 탭 컨텐츠의 동적 로딩을 관리하는 클래스입니다.
|
|
/// TabView에 소속되어 지연 로딩 기능을 제공합니다.
|
|
/// </summary>
|
|
public class TabContentLoader : MonoBehaviour
|
|
{
|
|
[Tooltip("지연 로딩 사용 여부")]
|
|
[SerializeField] private bool lazyLoadTabs = true;
|
|
|
|
[Tooltip("최대 동시 로드 탭 수")]
|
|
[SerializeField] private int maxLoadedTabs = 3;
|
|
|
|
[Tooltip("탭 전환 시 자동 로드/언로드 여부")]
|
|
[SerializeField] private bool autoManageTabs = true;
|
|
|
|
/// <summary>
|
|
/// 지연 로딩할 탭 컨텐츠 정보를 정의하는 클래스입니다.
|
|
/// </summary>
|
|
[System.Serializable]
|
|
public class LazyTabContent
|
|
{
|
|
public string tabID = "";
|
|
public string contentPrefabPath = "";
|
|
public bool isLoaded = false;
|
|
|
|
[HideInInspector] public GameObject? instance = null;
|
|
[HideInInspector] public object? contentData = null;
|
|
|
|
public LazyTabContent(string id, string path, object? data = null)
|
|
{
|
|
tabID = id;
|
|
contentPrefabPath = path;
|
|
contentData = data;
|
|
isLoaded = false;
|
|
instance = null;
|
|
}
|
|
}
|
|
|
|
// 지연 로드 컨텐츠 목록
|
|
private List<LazyTabContent> _lazyContents = new List<LazyTabContent>();
|
|
|
|
// 초기화 여부
|
|
private bool _isInitialized = false;
|
|
|
|
// 현재 활성화된 탭 ID
|
|
private string? _currentTabID = null;
|
|
|
|
// 부모 TabView 참조
|
|
private TabView? _parentTabView;
|
|
|
|
// 이벤트
|
|
public UnityEvent<string> OnTabContentLoaded = new UnityEvent<string>();
|
|
public UnityEvent<string> OnTabContentUnloaded = new UnityEvent<string>();
|
|
|
|
private void Awake()
|
|
{
|
|
_parentTabView = GetComponentInParent<TabView>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 탭 로더를 초기화합니다.
|
|
/// </summary>
|
|
public void InitializeTabLoader()
|
|
{
|
|
if (_isInitialized) return;
|
|
|
|
if (!lazyLoadTabs)
|
|
{
|
|
PreloadAllTabs();
|
|
}
|
|
|
|
_isInitialized = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 지연 로드 탭 설정을 추가합니다.
|
|
/// </summary>
|
|
public bool AddLazyTabContent(string tabID, string prefabPath, object? initialData = null)
|
|
{
|
|
LazyTabContent content = new LazyTabContent(tabID, prefabPath, initialData);
|
|
_lazyContents.Add(content);
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 모든 지연 로드 설정을 제거합니다.
|
|
/// </summary>
|
|
public void ClearLazyContents()
|
|
{
|
|
foreach (var content in _lazyContents)
|
|
{
|
|
if (content.isLoaded && content.instance != null)
|
|
{
|
|
Destroy(content.instance);
|
|
}
|
|
}
|
|
|
|
_lazyContents.Clear();
|
|
_isInitialized = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 탭의 컨텐츠를 로드합니다.
|
|
/// </summary>
|
|
public GameObject? LoadTabContent(string tabID, object? data = null)
|
|
{
|
|
LazyTabContent? contentToLoad = _lazyContents.Find(c => c.tabID == tabID);
|
|
if (contentToLoad == null)
|
|
{
|
|
Debug.LogWarning($"지연 로드할 탭 컨텐츠를 찾을 수 없음: {tabID}");
|
|
return null;
|
|
}
|
|
|
|
// 이미 로드된 경우
|
|
if (contentToLoad.isLoaded && contentToLoad.instance != null)
|
|
{
|
|
if (data != null)
|
|
{
|
|
contentToLoad.contentData = data;
|
|
UpdateContentData(contentToLoad);
|
|
}
|
|
return contentToLoad.instance;
|
|
}
|
|
|
|
try
|
|
{
|
|
// 프리팹 로드
|
|
GameObject prefab = Resources.Load<GameObject>(contentToLoad.contentPrefabPath);
|
|
if (prefab == null)
|
|
{
|
|
Debug.LogError($"탭 컨텐츠 프리팹을 찾을 수 없음: {contentToLoad.contentPrefabPath}");
|
|
return null;
|
|
}
|
|
|
|
// TabView의 ContentContainer를 부모로 사용
|
|
Transform parentTransform = _parentTabView?.ContentContainer ?? transform;
|
|
|
|
// 인스턴스 생성
|
|
contentToLoad.instance = Instantiate(prefab, parentTransform);
|
|
contentToLoad.instance.name = $"LazyTabContent_{tabID}";
|
|
contentToLoad.instance.SetActive(false);
|
|
contentToLoad.isLoaded = true;
|
|
|
|
// 데이터 설정
|
|
if (data != null)
|
|
{
|
|
contentToLoad.contentData = data;
|
|
}
|
|
UpdateContentData(contentToLoad);
|
|
|
|
// 이벤트 발생
|
|
OnTabContentLoaded.Invoke(tabID);
|
|
|
|
Debug.Log($"지연 로드 탭 컨텐츠 로드됨: {tabID}");
|
|
return contentToLoad.instance;
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.LogError($"탭 컨텐츠 로드 중 오류 발생: {ex.Message}");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 탭 컨텐츠의 데이터를 업데이트합니다.
|
|
/// </summary>
|
|
private void UpdateContentData(LazyTabContent content)
|
|
{
|
|
if (content.instance != null && content.contentData != null)
|
|
{
|
|
ITabContent? tabContent = content.instance.GetComponent<ITabContent>();
|
|
tabContent?.SetContentData(content.contentData);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 탭의 컨텐츠를 언로드합니다.
|
|
/// </summary>
|
|
public bool UnloadTabContent(string tabID)
|
|
{
|
|
LazyTabContent? contentToUnload = _lazyContents.Find(c => c.tabID == tabID);
|
|
if (contentToUnload == null || !contentToUnload.isLoaded || contentToUnload.instance == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
Destroy(contentToUnload.instance);
|
|
contentToUnload.instance = null;
|
|
contentToUnload.isLoaded = false;
|
|
|
|
OnTabContentUnloaded.Invoke(tabID);
|
|
Debug.Log($"지연 로드 탭 컨텐츠 언로드됨: {tabID}");
|
|
return true;
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.LogError($"탭 컨텐츠 언로드 중 오류 발생: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 현재 활성화된 탭을 제외한 모든 탭을 언로드합니다.
|
|
/// </summary>
|
|
public void UnloadAllExceptCurrent(string currentTabID)
|
|
{
|
|
foreach (var content in _lazyContents)
|
|
{
|
|
if (content.tabID != currentTabID && content.isLoaded)
|
|
{
|
|
UnloadTabContent(content.tabID);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 모든 탭 컨텐츠를 미리 로드합니다.
|
|
/// </summary>
|
|
public void PreloadAllTabs()
|
|
{
|
|
foreach (var content in _lazyContents)
|
|
{
|
|
if (!content.isLoaded)
|
|
{
|
|
LoadTabContent(content.tabID);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 탭의 데이터를 설정합니다.
|
|
/// </summary>
|
|
public void SetTabContentData(string tabID, object? data)
|
|
{
|
|
LazyTabContent? content = _lazyContents.Find(c => c.tabID == tabID);
|
|
if (content != null)
|
|
{
|
|
content.contentData = data;
|
|
|
|
if (content.isLoaded && content.instance != null)
|
|
{
|
|
UpdateContentData(content);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 탭이 로드되었는지 확인합니다.
|
|
/// </summary>
|
|
public bool IsTabLoaded(string tabID)
|
|
{
|
|
LazyTabContent? content = _lazyContents.Find(c => c.tabID == tabID);
|
|
return content?.isLoaded == true && content.instance != null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 특정 탭의 컨텐츠 인스턴스를 가져옵니다.
|
|
/// </summary>
|
|
public GameObject? GetTabInstance(string tabID)
|
|
{
|
|
LazyTabContent? content = _lazyContents.Find(c => c.tabID == tabID);
|
|
return content?.isLoaded == true ? content.instance : null;
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
foreach (var content in _lazyContents)
|
|
{
|
|
if (content.isLoaded && content.instance != null)
|
|
{
|
|
Destroy(content.instance);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|