Files
Northbound/Assets/Scripts/BuildingQuickslotUI.cs

330 lines
10 KiB
C#

using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using TMPro;
using Northbound.Data;
namespace Northbound
{
/// <summary>
/// 건설 모드 시 건축 가능한 건물들을 표시하는 퀵슬롯 UI
/// </summary>
public class BuildingQuickslotUI : MonoBehaviour
{
public static BuildingQuickslotUI Instance { get; private set; }
[Header("UI References")]
[SerializeField] private GameObject quickslotPanel;
[SerializeField] private Transform slotContainer;
[SerializeField] private GameObject slotButtonPrefab;
[Header("Settings")]
[SerializeField] private int maxSlots = 8;
private List<BuildingSlotButton> slotButtons = new List<BuildingSlotButton>();
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);
}
InitializeSlots();
}
private void Update()
{
if (quickslotPanel != null && quickslotPanel.activeSelf)
{
UpdateCostDisplays();
}
}
/// <summary>
/// 모든 슬롯의 비용 표시 업데이트
/// </summary>
public void UpdateCostDisplays()
{
foreach (var slot in slotButtons)
{
if (slot != null)
{
slot.UpdateCostDisplay();
}
}
}
/// <summary>
/// 퀵슬롯 Input Actions 초기화 및 구독 (직접 참조)
/// </summary>
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개 키 바인딩)");
}
/// <summary>
/// 퀵슬롯 액션 구독 해제
/// </summary>
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);
}
}
}
/// <summary>
/// 퀵슬롯 액션 활성화
/// </summary>
private void EnableQuickslotActions(bool enable)
{
if (_quickslotActions == null) return;
foreach (var action in _quickslotActions)
{
if (action != null)
{
if (enable)
action.Enable();
else
action.Disable();
}
}
}
/// <summary>
/// 퀵슬롯 액션 비활성화
/// </summary>
private void DisableQuickslotActions()
{
EnableQuickslotActions(false);
}
/// <summary>
/// 퀵슬롯 키 입력 처리
/// </summary>
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}은 존재하지 않습니다. 마우스로 클릭하여 선택하세요.");
}
}
/// <summary>
/// BuildingManager의 건물 목록으로 슬롯 초기화
/// </summary>
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}개의 건물 슬롯 생성됨");
}
/// <summary>
/// 개별 슬롯 버튼 생성
/// </summary>
private void CreateSlot(TowerData buildingData, int index)
{
GameObject slotObj = Instantiate(slotButtonPrefab, slotContainer);
BuildingSlotButton slotButton = slotObj.GetComponent<BuildingSlotButton>();
if (slotButton != null)
{
slotButton.Initialize(buildingData, index, this);
slotButtons.Add(slotButton);
// 핫키 표시 (1-8)
slotButton.SetHotkeyText((index + 1).ToString());
}
}
/// <summary>
/// 건설 모드 활성화 (BuildingPlacement에서 호출)
/// </summary>
public void ShowQuickslot(BuildingPlacement placement)
{
buildingPlacement = placement;
if (quickslotPanel != null)
{
quickslotPanel.SetActive(true);
}
// 퀵슬롯 입력 활성화
EnableQuickslotActions(true);
// 기본 선택 (첫 번째 건물)
if (slotButtons.Count > 0)
{
SelectBuilding(0);
}
Debug.Log("[BuildingQuickslotUI] 건설 퀵슬롯 표시됨");
}
/// <summary>
/// 건설 모드 비활성화
/// </summary>
public void HideQuickslot()
{
if (quickslotPanel != null)
{
quickslotPanel.SetActive(false);
}
// 퀵슬롯 입력 비활성화
DisableQuickslotActions();
buildingPlacement = null;
currentSelectedIndex = -1;
// 모든 슬롯 선택 해제
foreach (var slot in slotButtons)
{
if (slot != null)
slot.SetSelected(false);
}
Debug.Log("[BuildingQuickslotUI] 건설 퀵슬롯 숨김");
}
/// <summary>
/// 건물 선택 (슬롯 버튼 클릭 또는 핫키)
/// </summary>
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);
}
Debug.Log($"[BuildingQuickslotUI] 건물 선택됨: {slotButtons[index].GetBuildingName()} (인덱스: {index})");
}
/// <summary>
/// 현재 선택된 건물 인덱스
/// </summary>
public int GetSelectedIndex()
{
return currentSelectedIndex;
}
/// <summary>
/// 슬롯 개수 반환
/// </summary>
public int GetSlotCount()
{
return slotButtons.Count;
}
}
}