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 그룹용 (필요시 확장) } /// /// 공통 탭 그룹 UI 클래스 /// 제네릭 없이 탭을 관리합니다. /// public class CommonTabGroupUi : MonoBehaviour { [Header("정적 배치된 탭 버튼들")] [SerializeField] private List _tabButtons = new(); [Header("탭 버튼 타입 설정")] [SerializeField] private TabButtonType _tabButtonType = TabButtonType.None; private Dictionary _tabLookup = new(); // 그룹별 기본 허용 값 정의 (List로 통일하여 일관성 확보) private static readonly Dictionary> TabButtonConfig = new() { { TabButtonType.SectionButtonType, new List { (int)SectionButtonType.Menu, (int)SectionButtonType.Cookware, (int)SectionButtonType.Worker }}, { TabButtonType.MenuButtonType, new List { (int)InventoryCategoryType.Food, (int)InventoryCategoryType.Drink, (int)InventoryCategoryType.Ingredient }}, { TabButtonType.CookwareButtonType, new List { (int)InventoryCategoryType.Cookware, (int)InventoryCategoryType.Special, (int)InventoryCategoryType.Ingredient }}, { TabButtonType.WorkerButtonType, new List { } } }; public int CurrentTabValue { get; private set; } public int TabCount => _tabButtons.Count; public event Action OnTabSelected; private void OnDestroy() { if (_tabButtons == null) return; foreach (var tabButton in _tabButtons) { if (tabButton != null) { tabButton.OnTabClicked -= HandleTabButtonClicked; } } } public void Initialize(Action onTabSelected) { if (onTabSelected != null) { OnTabSelected += onTabSelected; } InitializeTabs(); } /// /// 기본 허용 값들을 사용하여 탭을 초기화합니다. /// public void UseDefaultAllowedValues() { if (TabButtonConfig.TryGetValue(_tabButtonType, out List defaultValues)) { // 기본값을 바로 사용하여 탭 초기화 InitializeTabsWithValues(defaultValues); } else { Debug.LogWarning($"TabButtonType {_tabButtonType}에 대한 설정이 정의되지 않았습니다.", this); } } /// /// 지정된 값들로 탭들을 초기화합니다. /// public void InitializeTabsWithValues(List 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; } } } /// /// 탭들을 설정하고 초기화합니다. /// private void InitializeTabs() { if (_tabButtons == null || _tabButtons.Count == 0) { Debug.LogWarning("탭 버튼들이 설정되지 않았습니다.", this); return; } // 기본값을 사용하여 탭 초기화 if (TabButtonConfig.TryGetValue(_tabButtonType, out List defaultValues)) { InitializeTabsWithValues(defaultValues); } else { Debug.LogWarning($"TabButtonType {_tabButtonType}에 대한 설정이 정의되지 않았습니다.", this); } } /// /// 탭 버튼 클릭 이벤트 처리 /// private void HandleTabButtonClicked(int tabValue) { SelectTab(tabValue); } /// /// 지정된 값을 가진 탭을 선택합니다. /// 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); } /// /// 첫 번째 탭을 선택합니다. /// public void SelectFirstTab() { if (_tabButtons == null || _tabButtons.Count == 0) return; if (_tabButtons[0] != null) { var firstTabValue = _tabButtons[0].TabValue; SelectTab(firstTabValue); } } /// /// 현재 탭에서 지정된 방향으로 이동합니다. /// 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]); } } /// /// 탭 버튼이 상호작용 가능한지 확인합니다. /// public bool IsTabInteractable(int tabValue) { if (_tabLookup == null) return false; return _tabLookup.TryGetValue(tabValue, out var tabButton) && tabButton.IsInteractable == true; } /// /// 첫 번째 상호작용 가능한 탭 버튼을 반환합니다. /// 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; } } }