355 lines
11 KiB
C#
355 lines
11 KiB
C#
using System.Collections.Generic;
|
|
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 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<BuildingSlotButton> slotButtons = new List<BuildingSlotButton>();
|
|
private BuildingPlacement buildingPlacement;
|
|
private int currentSelectedIndex = -1;
|
|
private int lastSelectedIndex = 0;
|
|
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();
|
|
}
|
|
|
|
|
|
|
|
/// <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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <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();
|
|
|
|
// Level 1 건물만 슬롯 생성 (건설 모드에서는 기본 건물만 표시)
|
|
var buildableBuildings = BuildingManager.Instance.GetBuildableBuildings();
|
|
|
|
for (int i = 0; i < buildableBuildings.Count; i++)
|
|
{
|
|
CreateSlot(buildableBuildings[i], i);
|
|
}
|
|
}
|
|
|
|
/// <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);
|
|
}
|
|
|
|
if (descriptionPanel != null)
|
|
{
|
|
descriptionPanel.SetActive(true);
|
|
}
|
|
|
|
// 퀵슬롯 입력 활성화
|
|
EnableQuickslotActions(true);
|
|
|
|
// 마지막으로 선택된 건물 선택
|
|
if (slotButtons.Count > 0 && lastSelectedIndex >= 0 && lastSelectedIndex < slotButtons.Count)
|
|
{
|
|
SelectBuilding(lastSelectedIndex);
|
|
}
|
|
else if (slotButtons.Count > 0)
|
|
{
|
|
SelectBuilding(0);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 건설 모드 비활성화
|
|
/// </summary>
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <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;
|
|
lastSelectedIndex = index;
|
|
slotButtons[index].SetSelected(true);
|
|
|
|
// BuildingPlacement에 알림
|
|
if (buildingPlacement != null)
|
|
{
|
|
buildingPlacement.SetSelectedBuilding(index);
|
|
}
|
|
|
|
// Description Panel 업데이트
|
|
UpdateDescriptionPanel();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Description Panel 업데이트
|
|
/// </summary>
|
|
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}" : $"<color=red>{buildingData.mana}</color>";
|
|
buildingCostText.text = $"{costTextT}";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 현재 선택된 건물 인덱스
|
|
/// </summary>
|
|
public int GetSelectedIndex()
|
|
{
|
|
return currentSelectedIndex;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 슬롯 개수 반환
|
|
/// </summary>
|
|
public int GetSlotCount()
|
|
{
|
|
return slotButtons.Count;
|
|
}
|
|
}
|
|
} |