using System.Collections.Generic; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; using TMPro; using Northbound.Data; namespace Northbound { /// /// 건설 모드 시 건축 가능한 건물들을 표시하는 퀵슬롯 UI /// public class BuildingQuickslotUI : MonoBehaviour { public static BuildingQuickslotUI Instance { get; private set; } [Header("UI References")] [SerializeField] private GameObject quickslotPanel; [SerializeField] private GameObject descriptionPanel; [SerializeField] private Transform slotContainer; [SerializeField] private GameObject slotButtonPrefab; [SerializeField] private TextMeshProUGUI buildingNameText; [SerializeField] private TextMeshProUGUI buildingDescriptionText; [SerializeField] private TextMeshProUGUI buildingCostText; [Header("Settings")] [SerializeField] private int maxSlots = 8; private List slotButtons = new List(); private BuildingPlacement buildingPlacement; private int currentSelectedIndex = -1; private PlayerInputActions _inputActions; private InputAction[] _quickslotActions; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; // Input Actions 초기화 _inputActions = new PlayerInputActions(); InitializeQuickslotActions(); } private void OnEnable() { EnableQuickslotActions(false); // 초기에는 비활성화 } private void OnDisable() { DisableQuickslotActions(); } private void OnDestroy() { UnsubscribeQuickslotActions(); _inputActions?.Dispose(); } private void Start() { if (quickslotPanel != null) { quickslotPanel.SetActive(false); } if (descriptionPanel != null) { descriptionPanel.SetActive(false); } InitializeSlots(); } /// /// 퀵슬롯 Input Actions 초기화 및 구독 (직접 참조) /// private void InitializeQuickslotActions() { _quickslotActions = new InputAction[maxSlots]; // 수동으로 각 액션 할당 // Input Actions 에셋에 QuickSlot1~8 액션을 추가했는지 확인하세요 _quickslotActions[0] = _inputActions.Player.QuickSlot1; _quickslotActions[1] = _inputActions.Player.QuickSlot2; _quickslotActions[2] = _inputActions.Player.QuickSlot3; _quickslotActions[3] = _inputActions.Player.QuickSlot4; _quickslotActions[4] = _inputActions.Player.QuickSlot5; _quickslotActions[5] = _inputActions.Player.QuickSlot6; _quickslotActions[6] = _inputActions.Player.QuickSlot7; _quickslotActions[7] = _inputActions.Player.QuickSlot8; // 이벤트 구독 for (int i = 0; i < _quickslotActions.Length; i++) { if (_quickslotActions[i] != null) { int slotIndex = i; // 클로저 캡처를 위한 로컬 변수 _quickslotActions[i].performed += ctx => OnQuickslotPressed(slotIndex); // Debug.Log($"[BuildingQuickslotUI] QuickSlot{i + 1} 액션 바인딩 성공"); } else { Debug.LogWarning($"[BuildingQuickslotUI] QuickSlot{i + 1} 액션이 null입니다. Input Actions 에셋을 확인하세요."); } } Debug.Log($"[BuildingQuickslotUI] {_quickslotActions.Length}개의 퀵슬롯 액션 초기화됨 (최대 8개 키 바인딩)"); } /// /// 퀵슬롯 액션 구독 해제 /// private void UnsubscribeQuickslotActions() { if (_quickslotActions == null) return; for (int i = 0; i < _quickslotActions.Length; i++) { if (_quickslotActions[i] != null) { int slotIndex = i; _quickslotActions[i].performed -= ctx => OnQuickslotPressed(slotIndex); } } } /// /// 퀵슬롯 액션 활성화 /// private void EnableQuickslotActions(bool enable) { if (_quickslotActions == null) return; foreach (var action in _quickslotActions) { if (action != null) { if (enable) action.Enable(); else action.Disable(); } } } /// /// 퀵슬롯 액션 비활성화 /// private void DisableQuickslotActions() { EnableQuickslotActions(false); } /// /// 퀵슬롯 키 입력 처리 /// private void OnQuickslotPressed(int slotIndex) { // 퀵슬롯이 활성화되어 있고, 유효한 인덱스인 경우만 처리 if (quickslotPanel != null && quickslotPanel.activeSelf && slotIndex < slotButtons.Count) { SelectBuilding(slotIndex); } else if (slotIndex >= slotButtons.Count && quickslotPanel != null && quickslotPanel.activeSelf) { Debug.LogWarning($"[BuildingQuickslotUI] 슬롯 {slotIndex + 1}은 존재하지 않습니다. 마우스로 클릭하여 선택하세요."); } } /// /// BuildingManager의 건물 목록으로 슬롯 초기화 /// private void InitializeSlots() { if (BuildingManager.Instance == null || slotContainer == null || slotButtonPrefab == null) { Debug.LogWarning("[BuildingQuickslotUI] 필수 컴포넌트가 설정되지 않았습니다."); return; } // 기존 슬롯 제거 foreach (var slot in slotButtons) { if (slot != null) Destroy(slot.gameObject); } slotButtons.Clear(); // 모든 건물 슬롯 생성 (제한 없음) var buildings = BuildingManager.Instance.availableBuildings; for (int i = 0; i < buildings.Count; i++) { CreateSlot(buildings[i], i); } Debug.Log($"[BuildingQuickslotUI] {slotButtons.Count}개의 건물 슬롯 생성됨"); } /// /// 개별 슬롯 버튼 생성 /// private void CreateSlot(TowerData buildingData, int index) { GameObject slotObj = Instantiate(slotButtonPrefab, slotContainer); BuildingSlotButton slotButton = slotObj.GetComponent(); if (slotButton != null) { slotButton.Initialize(buildingData, index, this); slotButtons.Add(slotButton); // 핫키 표시 (1-8) slotButton.SetHotkeyText((index + 1).ToString()); } } /// /// 건설 모드 활성화 (BuildingPlacement에서 호출) /// public void ShowQuickslot(BuildingPlacement placement) { buildingPlacement = placement; if (quickslotPanel != null) { quickslotPanel.SetActive(true); } if (descriptionPanel != null) { descriptionPanel.SetActive(true); } // 퀵슬롯 입력 활성화 EnableQuickslotActions(true); // 기본 선택 (첫 번째 건물) if (slotButtons.Count > 0) { SelectBuilding(0); } Debug.Log("[BuildingQuickslotUI] 건설 퀵슬롯 표시됨"); } /// /// 건설 모드 비활성화 /// public void HideQuickslot() { if (quickslotPanel != null) { quickslotPanel.SetActive(false); } if (descriptionPanel != null) { descriptionPanel.SetActive(false); } // 퀵슬롯 입력 비활성화 DisableQuickslotActions(); buildingPlacement = null; currentSelectedIndex = -1; // 모든 슬롯 선택 해제 foreach (var slot in slotButtons) { if (slot != null) slot.SetSelected(false); } Debug.Log("[BuildingQuickslotUI] 건설 퀵슬롯 숨김"); } /// /// 건물 선택 (슬롯 버튼 클릭 또는 핫키) /// public void SelectBuilding(int index) { if (index < 0 || index >= slotButtons.Count) return; // 이전 선택 해제 if (currentSelectedIndex >= 0 && currentSelectedIndex < slotButtons.Count) { slotButtons[currentSelectedIndex].SetSelected(false); } // 새로운 선택 currentSelectedIndex = index; slotButtons[index].SetSelected(true); // BuildingPlacement에 알림 if (buildingPlacement != null) { buildingPlacement.SetSelectedBuilding(index); } // Description Panel 업데이트 UpdateDescriptionPanel(); Debug.Log($"[BuildingQuickslotUI] 건물 선택됨: {slotButtons[index].GetBuildingName()} (인덱스: {index})"); } /// /// Description Panel 업데이트 /// private void UpdateDescriptionPanel() { if (currentSelectedIndex < 0 || currentSelectedIndex >= slotButtons.Count) return; var selectedSlot = slotButtons[currentSelectedIndex]; if (selectedSlot == null || selectedSlot.BuildingData == null) return; var buildingData = selectedSlot.BuildingData; if (buildingNameText != null) { buildingNameText.text = buildingData.buildingName; } if (buildingDescriptionText != null) { buildingDescriptionText.text = buildingData.memo; } if (buildingCostText != null) { var coreResourceManager = CoreResourceManager.Instance; bool canAfford = coreResourceManager != null && coreResourceManager.CanAfford(buildingData.mana); string costTextT = canAfford ? $"{buildingData.mana}" : $"{buildingData.mana}"; buildingCostText.text = $"{costTextT}"; } } /// /// 현재 선택된 건물 인덱스 /// public int GetSelectedIndex() { return currentSelectedIndex; } /// /// 슬롯 개수 반환 /// public int GetSlotCount() { return slotButtons.Count; } } }