디자인 적용

This commit is contained in:
logonkhi
2025-08-07 21:12:44 +09:00
parent 2e4718291e
commit 3297a5d1f3
139 changed files with 35760 additions and 736 deletions

View File

@@ -1,4 +1,6 @@
#nullable enable
using Cysharp.Threading.Tasks;
namespace UVC.UI.Tab
{
/// <summary>
@@ -12,5 +14,11 @@ namespace UVC.UI.Tab
/// </summary>
/// <param name="data">전달할 데이터 객체</param>
void SetContentData(object? data);
/// <summary>
/// 닫힐 때 실행되는 로직을 처리합니다.
/// </summary>
/// <returns>비동기 닫기 작업을 나타내는 <see cref="UniTask"/>입니다.</returns>
UniTask OnCloseAsync();
}
}

View File

@@ -3,6 +3,7 @@ using System;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UVC.Extention;
namespace UVC.UI.Tab
{
@@ -23,11 +24,17 @@ namespace UVC.UI.Tab
[Tooltip("탭 배경 이미지 컴포넌트")]
[SerializeField] private Image? background;
[Tooltip("탭이 활성화되었을 때의 색상")]
[SerializeField] private Color? activeColor;// = Color.white;
[Tooltip("탭이 활성화되었을 때의 배경 색상")]
[SerializeField] private Color activeColor = Color.white;
[Tooltip("탭이 비활성화되었을 때의 색상")]
[SerializeField] private Color? inactiveColor;// = new Color(0.8f, 0.8f, 0.8f);
[Tooltip("탭이 비활성화되었을 때의 배경 색상")]
[SerializeField] private Color inactiveColor = Color.gray;
[Tooltip("탭이 활성화되었을 때의 배경 색상")]
[SerializeField] private Color activeTextColor = Color.black;
[Tooltip("탭이 비활성화되었을 때의 배경 색상")]
[SerializeField] private Color inactiveTextColor = Color.white;
private int _tabIndex;
private Action<int>? _onTabSelected;
@@ -40,7 +47,10 @@ namespace UVC.UI.Tab
// 버튼 클릭 이벤트 연결
if (button != null)
{
button.onClick.AddListener(OnButtonClick);
button.transition = Selectable.Transition.None; // 버튼의 전환 효과를 비활성화
}
}
/// <summary>
@@ -48,9 +58,9 @@ namespace UVC.UI.Tab
/// </summary>
/// <param name="index">탭 인덱스</param>
/// <param name="tabName">탭 이름</param>
/// <param name="icon">탭 아이콘</param>
/// <param name="iconpath">탭 아이콘 경로</param>
/// <param name="onSelectedCallback">탭 선택 시 호출될 콜백</param>
public void Setup(int index, string tabName, Sprite? icon, Action<int> onSelectedCallback)
public void Setup(int index, string tabName, string iconpath, Action<int> onSelectedCallback)
{
_tabIndex = index;
_onTabSelected = onSelectedCallback;
@@ -62,9 +72,9 @@ namespace UVC.UI.Tab
// 탭 아이콘 설정
if (tabIcon != null)
{
if (icon != null)
if (!iconpath.IsNullOrEmpty())
{
tabIcon.sprite = icon;
tabIcon.sprite = iconpath.LoadResource<Sprite>();
tabIcon.gameObject.SetActive(true);
}
else
@@ -81,18 +91,24 @@ namespace UVC.UI.Tab
public void SetActive(bool isActive)
{
// 배경 색상 변경
if (background != null && activeColor.HasValue && inactiveColor.HasValue)
if (background != null)
{
background.color = isActive ? activeColor.Value : inactiveColor.Value;
background.color = isActive ? activeColor : inactiveColor;
}
else if(button != null)
{
button.image.color = isActive ? button.colors.pressedColor : button.colors.normalColor;
}
if(tabIcon != null)
{
tabIcon.color = isActive ? activeTextColor : inactiveTextColor;
}
// 텍스트 스타일 변경
if (tabText != null) {
tabText.fontStyle = isActive ? FontStyles.Bold : FontStyles.Normal;
tabText.color = isActive ? activeTextColor : inactiveTextColor;
}
}
@@ -105,6 +121,7 @@ namespace UVC.UI.Tab
// 게임 오브젝트가 제거될 때 이벤트 리스너 제거
private void OnDestroy()
{
_onTabSelected = null;
if (button != null)
button.onClick.RemoveListener(OnButtonClick);
}

View File

@@ -12,16 +12,16 @@ namespace UVC.UI.Tab
public string tabID = "";
public string tabName = "";
public string contentPath = "";
public Sprite? tabIcon = null;
public string tabIconPath = "";
public bool useLazyLoading = false;
public object? initialData = null;
public TabContentConfig(string id, string name, string path, Sprite? icon = null, bool lazy = false, object? data = null)
public TabContentConfig(string id, string name, string path, string iconPath = "", bool lazy = false, object? data = null)
{
tabID = id;
tabName = name;
contentPath = path;
tabIcon = icon;
tabIconPath = iconPath;
useLazyLoading = lazy;
initialData = data;
}

View File

@@ -1,4 +1,5 @@
#nullable enable
using Cysharp.Threading.Tasks;
using System;
using System.Collections.Generic;
using UnityEngine;
@@ -101,7 +102,7 @@ namespace UVC.UI.Tab
/// <summary>
/// 코드에서 탭 설정을 추가합니다.
/// </summary>
public bool AddTabConfig(string id, string name, string path, Sprite? icon = null, object? data = null, bool useLazyLoading = false)
public bool AddTabConfig(string id, string name, string path, string iconPath = "", object? data = null, bool useLazyLoading = false)
{
if (_isInitialized)
{
@@ -109,7 +110,7 @@ namespace UVC.UI.Tab
return false;
}
var config = new TabContentConfig(id, name, path, icon, useLazyLoading, data);
var config = new TabContentConfig(id, name, path, iconPath, useLazyLoading, data);
_additionalTabConfigs.Add(config);
return true;
}
@@ -182,7 +183,7 @@ namespace UVC.UI.Tab
config.tabID,
config.tabName,
config.contentPath,
config.tabIcon,
config.tabIconPath,
config.initialData
));
}
@@ -207,10 +208,12 @@ namespace UVC.UI.Tab
if (activeTabData == null) return;
// TabView에 탭 변경 전달
tabView.UpdateActiveTab(newTabIndex, activeTabData);
tabView.UpdateActiveTab(newTabIndex, _tabModel.PrevTabIndex, activeTabData).ContinueWith(() =>
{
// 외부 이벤트 발생
OnTabChanged?.Invoke(newTabIndex);
});
// 외부 이벤트 발생
OnTabChanged?.Invoke(newTabIndex);
}
#endregion

View File

@@ -13,7 +13,7 @@ namespace UVC.UI.Tab
public string tabID; // 탭 고유 식별자
public string tabName; // 탭 표시 이름
public string contentPath; // 탭 내용을 담고 있는 Prefab 경로 (Resources 폴더 기준)
public Sprite? tabIcon; // 탭 아이콘 (선택사항, null 가능)
public string tabIconPath; // 탭 아이콘 (선택사항, null 가능)
public object? contentData; // 탭 콘텐츠에 전달할 데이터 객체 (null 가능)
// 프리팹 경로로 초기화하는 생성자
@@ -23,14 +23,14 @@ namespace UVC.UI.Tab
/// <param name="id">탭의 고유 식별자 (예: "inventory", "settings")</param>
/// <param name="name">탭의 표시 이름 (예: "인벤토리", "설정")</param>
/// <param name="path">탭 컨텐츠 프리팹의 리소스 경로 (예: "Prefabs/UI/InventoryTab")</param>
/// <param name="icon">탭 아이콘 이미지 (선택사항)</param>
/// <param name="iconPath">탭 아이콘 이미지 리소스 경로(선택사항)</param>
/// <param name="data">탭 컨텐츠에 전달할 초기 데이터 (선택사항)</param>
public TabData(string id, string name, string path, Sprite? icon = null, object? data = null)
public TabData(string id, string name, string path, string iconPath = "", object? data = null)
{
tabID = id;
tabName = name;
contentPath = path;
tabIcon = icon;
tabIconPath = iconPath;
contentData = data;
}
}

View File

@@ -14,6 +14,7 @@ namespace UVC.UI.Tab
private List<TabData> _tabs = new List<TabData>();
// 현재 활성화된 탭의 인덱스 (-1은 활성화된 탭이 없음을 의미)
private int _activeTabIndex = -1;
private int _prevTabIndex = -1;
// 탭 컨텐츠 인스턴스를 저장하는 Dictionary (키: tabID)
private Dictionary<string, GameObject> _contentInstances = new Dictionary<string, GameObject>();
@@ -23,6 +24,11 @@ namespace UVC.UI.Tab
/// </summary>
public int ActiveTabIndex => _activeTabIndex;
/// <summary>
/// 이전에 선택된 탭 인덱스를 가져옵니다.
/// </summary>
public int PrevTabIndex => _prevTabIndex;
/// <summary>
/// 등록된 모든 탭의 목록을 가져옵니다.
/// </summary>
@@ -66,6 +72,8 @@ namespace UVC.UI.Tab
{
return;
}
Debug.Log($"탭 전환: {_activeTabIndex} -> {tabIndex}");
_prevTabIndex = _activeTabIndex;
// 활성화 탭 인덱스 업데이트
_activeTabIndex = tabIndex;

View File

@@ -1,6 +1,9 @@
#nullable enable
using Cysharp.Threading.Tasks;
using NUnit.Framework.Interfaces;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
namespace UVC.UI.Tab
@@ -195,7 +198,7 @@ namespace UVC.UI.Tab
}
// 탭 버튼 설정
tabButton.Setup(index, tabData.tabName, tabData.tabIcon, OnTabButtonClicked);
tabButton.Setup(index, tabData.tabName, tabData.tabIconPath, OnTabButtonClicked);
_tabButtons.Add(tabButton);
}
@@ -212,11 +215,11 @@ namespace UVC.UI.Tab
/// 필요한 경우 컨텐츠를 로드합니다.
/// </summary>
/// <param name="tabIndex">활성화할 탭 인덱스</param>
/// <param name="prevTabIndex">현재 활성화 된 탭 인덱스. 없으면 -1</param>
/// <param name="tabData">탭 데이터</param>
public void UpdateActiveTab(int tabIndex, TabData tabData)
public async UniTask UpdateActiveTab(int tabIndex, int prevTabIndex, TabData tabData)
{
if (tabIndex < 0 || tabIndex >= _tabConfigs.Count) return;
var config = _tabConfigs[tabIndex];
// 컨텐츠가 아직 로드되지 않은 경우 로드
@@ -243,6 +246,17 @@ namespace UVC.UI.Tab
}
}
//현재 활성화 된 탭의 컨텐츠가 있다면 OnClose 호출
if (prevTabIndex > -1)
{
GameObject? contentInstance = _allContentInstances[prevTabIndex];
if (contentInstance != null)
{
ITabContent? tabContent = contentInstance.GetComponent<ITabContent>();
if (tabContent != null) await tabContent.OnCloseAsync();
}
}
// 모든 컨텐츠 비활성화
foreach (var content in _allContentInstances)
{
@@ -257,11 +271,8 @@ namespace UVC.UI.Tab
activeContent.SetActive(true);
// 데이터 업데이트
if (tabData.contentData != null)
{
ITabContent? tabContent = activeContent.GetComponent<ITabContent>();
tabContent?.SetContentData(tabData.contentData);
}
ITabContent? tabContent = activeContent.GetComponent<ITabContent>();
tabContent?.SetContentData(tabData.contentData);
}
// 탭 버튼 상태 업데이트
@@ -476,6 +487,20 @@ namespace UVC.UI.Tab
// 설정 클리어
_tabConfigs.Clear();
_onTabButtonClicked = null;
}
protected virtual void OnDestroy()
{
// 탭과 관련된 모든 리소스를 정리합니다.
ClearTabs();
// ContentLoader가 있다면 정리
if (contentLoader != null)
{
contentLoader.ClearLazyContents();
contentLoader = null;
}
}
}
}