ProjectDDD/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/TabUi/CommonTabGroupUi.cs
2025-08-17 08:57:23 +09:00

271 lines
8.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace DDD
{
public enum TabGroupType
{
None = 0,
InventoryCategory,
SectionCategory
}
public enum TabButtonType
{
None = 0,
SectionButtonType,
MenuButtonType, // Menu 그룹용 (Food, Drink, Ingredient)
CookwareButtonType, // Cookware 그룹용 (Cookware, Special, Ingredient)
WorkerButtonType // Worker 그룹용 (필요시 확장)
}
/// <summary>
/// 공통 탭 그룹 UI 클래스
/// 제네릭 없이 탭을 관리합니다.
/// </summary>
public class CommonTabGroupUi : MonoBehaviour
{
[Header("정적 배치된 탭 버튼들")]
[SerializeField] private List<CommonTabButtonUi> _tabButtons = new();
[Header("탭 버튼 타입 설정")]
[SerializeField] private TabButtonType _tabButtonType = TabButtonType.None;
private Dictionary<int, CommonTabButtonUi> _tabLookup = new();
// 그룹별 기본 허용 값 정의 (List<int>로 통일하여 일관성 확보)
private static readonly Dictionary<TabButtonType, List<int>> TabButtonConfig = new()
{
{ TabButtonType.SectionButtonType, new List<int> {
(int)SectionButtonType.Menu,
(int)SectionButtonType.Cookware,
(int)SectionButtonType.Worker
}},
{ TabButtonType.MenuButtonType, new List<int> {
(int)InventoryCategoryType.Food,
(int)InventoryCategoryType.Drink,
(int)InventoryCategoryType.Ingredient
}},
{ TabButtonType.CookwareButtonType, new List<int> {
(int)InventoryCategoryType.Cookware,
(int)InventoryCategoryType.Special,
(int)InventoryCategoryType.Ingredient
}},
{ TabButtonType.WorkerButtonType, new List<int> { } }
};
public int CurrentTabValue { get; private set; }
public int TabCount => _tabButtons.Count;
public event Action<int> OnTabSelected;
private void OnDestroy()
{
if (_tabButtons == null) return;
foreach (var tabButton in _tabButtons)
{
if (tabButton != null)
{
tabButton.OnTabClicked -= HandleTabButtonClicked;
}
}
}
public void Initialize(Action<int> onTabSelected)
{
if (onTabSelected != null)
{
OnTabSelected += onTabSelected;
}
InitializeTabs();
}
/// <summary>
/// 기본 허용 값들을 사용하여 탭을 초기화합니다.
/// </summary>
public void UseDefaultAllowedValues()
{
if (TabButtonConfig.TryGetValue(_tabButtonType, out List<int> defaultValues))
{
// 기본값을 바로 사용하여 탭 초기화
InitializeTabsWithValues(defaultValues);
}
else
{
Debug.LogWarning($"TabButtonType {_tabButtonType}에 대한 설정이 정의되지 않았습니다.", this);
}
}
/// <summary>
/// 지정된 값들로 탭들을 초기화합니다.
/// </summary>
public void InitializeTabsWithValues(List<int> allowedValues)
{
if (allowedValues == null || allowedValues.Count == 0)
{
Debug.LogWarning("허용된 값이 설정되지 않았습니다.", this);
return;
}
// 탭 버튼들과 허용된 값들을 연결
for (int i = 0; i < Mathf.Min(allowedValues.Count, _tabButtons.Count); i++)
{
var enumValue = allowedValues[i];
var tabButton = _tabButtons[i];
if (tabButton != null)
{
// 탭 버튼 데이터 설정
tabButton.SetTabData(enumValue);
// 클릭 이벤트 설정 (add/remove 패턴 사용)
tabButton.OnTabClicked += HandleTabButtonClicked;
// 딕셔너리에 추가
_tabLookup[enumValue] = tabButton;
}
}
}
/// <summary>
/// 탭들을 설정하고 초기화합니다.
/// </summary>
private void InitializeTabs()
{
if (_tabButtons == null || _tabButtons.Count == 0)
{
Debug.LogWarning("탭 버튼들이 설정되지 않았습니다.", this);
return;
}
// 기본값을 사용하여 탭 초기화
if (TabButtonConfig.TryGetValue(_tabButtonType, out List<int> defaultValues))
{
InitializeTabsWithValues(defaultValues);
}
else
{
Debug.LogWarning($"TabButtonType {_tabButtonType}에 대한 설정이 정의되지 않았습니다.", this);
}
}
/// <summary>
/// 탭 버튼 클릭 이벤트 처리
/// </summary>
private void HandleTabButtonClicked(int tabValue)
{
SelectTab(tabValue);
}
/// <summary>
/// 지정된 값을 가진 탭을 선택합니다.
/// </summary>
public void SelectTab(int tabValue)
{
if (_tabLookup == null || _tabLookup.Count == 0)
{
Debug.LogWarning("탭 룩업이 초기화되지 않았습니다.", this);
return;
}
if (!_tabLookup.ContainsKey(tabValue))
{
Debug.LogWarning($"탭 값 {tabValue}에 해당하는 탭을 찾을 수 없습니다.", this);
return;
}
CurrentTabValue = tabValue;
// 모든 탭의 선택 상태 업데이트
foreach (var tabValueButton in _tabLookup)
{
tabValueButton.Value.SetSelected(tabValueButton.Key == tabValue);
}
// 이벤트 호출
OnTabSelected?.Invoke(tabValue);
}
/// <summary>
/// 첫 번째 탭을 선택합니다.
/// </summary>
public void SelectFirstTab()
{
if (_tabButtons == null || _tabButtons.Count == 0) return;
if (_tabButtons[0] != null)
{
var firstTabValue = _tabButtons[0].TabValue;
SelectTab(firstTabValue);
}
}
/// <summary>
/// 현재 탭에서 지정된 방향으로 이동합니다.
/// </summary>
public void Move(int direction)
{
if (_tabButtons == null || _tabButtons.Count == 0) return;
if (_tabLookup == null || _tabLookup.Count == 0) return;
// 성능 최적화: List 생성 대신 직접 반복
var tabValues = _tabLookup.Keys.ToArray();
int currentIndex = Array.IndexOf(tabValues, CurrentTabValue);
if (currentIndex == -1) return;
// 상호작용 가능한 탭으로만 이동
int newIndex = currentIndex;
int attempts = 0;
int maxAttempts = tabValues.Length; // 무한 루프 방지
do
{
newIndex = (newIndex + direction + tabValues.Length) % tabValues.Length;
attempts++;
// 상호작용 가능한 탭을 찾았거나 모든 탭을 확인했으면 종료
if (IsTabInteractable(tabValues[newIndex]) || attempts >= maxAttempts)
{
break;
}
} while (newIndex != currentIndex);
// 상호작용 가능한 탭을 찾았으면 이동
if (IsTabInteractable(tabValues[newIndex]))
{
SelectTab(tabValues[newIndex]);
}
}
/// <summary>
/// 탭 버튼이 상호작용 가능한지 확인합니다.
/// </summary>
public bool IsTabInteractable(int tabValue)
{
if (_tabLookup == null) return false;
return _tabLookup.TryGetValue(tabValue, out var tabButton) && tabButton.IsInteractable == true;
}
/// <summary>
/// 첫 번째 상호작용 가능한 탭 버튼을 반환합니다.
/// </summary>
public GameObject GetFirstInteractableButton()
{
if (_tabButtons == null || _tabButtons.Count == 0) return null;
foreach (var tabButton in _tabButtons)
{
if (tabButton != null && tabButton.IsInteractable == true)
{
return tabButton.gameObject;
}
}
return null;
}
}
}