fack
This commit is contained in:
291
Assets/Inventory/Scripts/InventoryUIBuilder.cs
Normal file
291
Assets/Inventory/Scripts/InventoryUIBuilder.cs
Normal file
@@ -0,0 +1,291 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
|
||||
/// <summary>
|
||||
/// Создаёт UI инвентаря программно с использованием TextMeshPro
|
||||
/// </summary>
|
||||
public class InventoryUIBuilder : MonoBehaviour
|
||||
{
|
||||
[Header("Settings")]
|
||||
public int hotbarSlots = 9;
|
||||
public int inventoryRows = 4;
|
||||
public int inventoryCols = 9;
|
||||
|
||||
[Header("Visual Settings")]
|
||||
public float slotSize = 50f;
|
||||
public float slotSpacing = 4f;
|
||||
public float inventoryPadding = 10f;
|
||||
public float hotbarPadding = 10f;
|
||||
|
||||
[Header("Colors")]
|
||||
[SerializeField] private Color inventoryPanelColor = new Color(0.15f, 0.15f, 0.15f, 0.95f);
|
||||
[SerializeField] private Color hotbarPanelColor = new Color(0.1f, 0.1f, 0.1f, 0.9f);
|
||||
[SerializeField] private Color slotEmptyColor = new Color(0.25f, 0.25f, 0.25f, 0.8f);
|
||||
[SerializeField] private Color slotFilledColor = new Color(0.35f, 0.35f, 0.35f, 0.95f);
|
||||
|
||||
[Header("Container References")]
|
||||
public RectTransform inventoryPanelRect;
|
||||
public RectTransform hotbarPanelRect;
|
||||
public Canvas inventoryCanvas;
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Проверяем, не запущен ли уже BuildInventoryUI
|
||||
if (InventoryManager.Instance != null &&
|
||||
InventoryManager.Instance.slots != null &&
|
||||
InventoryManager.Instance.slots.Length > 0)
|
||||
{
|
||||
Debug.Log("[InventoryUIBuilder] UI already built, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
BuildInventoryUI();
|
||||
}
|
||||
|
||||
public void BuildInventoryUI()
|
||||
{
|
||||
// Создаём или получаем Canvas
|
||||
var canvas = GetComponent<Canvas>();
|
||||
if (canvas == null)
|
||||
{
|
||||
canvas = gameObject.AddComponent<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
canvas.sortingOrder = 100;
|
||||
gameObject.AddComponent<GraphicRaycaster>();
|
||||
}
|
||||
inventoryCanvas = canvas;
|
||||
|
||||
// Настраиваем EventSystem если нет
|
||||
if (FindObjectOfType<TMPro.TMP_InputField>() != null || FindObjectsOfType<TMPro.TextMeshProUGUI>().Length > 0)
|
||||
{
|
||||
// EventSystem уже есть
|
||||
}
|
||||
|
||||
// Создаём панель инвентаря
|
||||
GameObject inventoryPanel = CreatePanel("InventoryPanel", transform, inventoryPanelColor);
|
||||
inventoryPanelRect = inventoryPanel.GetComponent<RectTransform>();
|
||||
|
||||
float inventoryWidth = inventoryCols * (slotSize + slotSpacing) + inventoryPadding * 2;
|
||||
float inventoryHeight = inventoryRows * (slotSize + slotSpacing) + inventoryPadding * 2 + 40; // +40 для заголовка
|
||||
|
||||
inventoryPanelRect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
inventoryPanelRect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
inventoryPanelRect.pivot = new Vector2(0.5f, 0.5f);
|
||||
inventoryPanelRect.anchoredPosition = Vector2.zero;
|
||||
inventoryPanelRect.sizeDelta = new Vector2(inventoryWidth, inventoryHeight);
|
||||
|
||||
// Заголовок
|
||||
CreateTitle(inventoryPanel.transform, "Инвентарь", new Vector2(0, inventoryHeight / 2 - 20));
|
||||
|
||||
// Сетка инвентаря (4x9 = 36 слотов)
|
||||
float gridHeight = inventoryRows * (slotSize + slotSpacing);
|
||||
var inventoryGrid = CreateGrid(
|
||||
inventoryPanel.transform,
|
||||
"InventoryGrid",
|
||||
inventoryCols,
|
||||
inventoryRows,
|
||||
slotSize,
|
||||
slotSpacing,
|
||||
new Vector2(inventoryPadding, inventoryPadding + 30)
|
||||
);
|
||||
InventoryManager.Instance.slots = CreateSlots(inventoryGrid, "InventorySlot_", 0, inventoryCols * inventoryRows);
|
||||
|
||||
// Создаём хотбар
|
||||
GameObject hotbarPanel = CreatePanel("HotbarPanel", transform, hotbarPanelColor);
|
||||
hotbarPanelRect = hotbarPanel.GetComponent<RectTransform>();
|
||||
|
||||
float hotbarWidth = hotbarSlots * (slotSize + slotSpacing) + hotbarPadding * 2;
|
||||
|
||||
hotbarPanelRect.anchorMin = new Vector2(0.5f, 0f);
|
||||
hotbarPanelRect.anchorMax = new Vector2(0.5f, 0f);
|
||||
hotbarPanelRect.pivot = new Vector2(0.5f, 0f);
|
||||
hotbarPanelRect.anchoredPosition = new Vector2(0, 15);
|
||||
hotbarPanelRect.sizeDelta = new Vector2(hotbarWidth, slotSize + hotbarPadding * 2);
|
||||
|
||||
var hotbarGrid = CreateGrid(
|
||||
hotbarPanel.transform,
|
||||
"HotbarGrid",
|
||||
hotbarSlots,
|
||||
1,
|
||||
slotSize,
|
||||
slotSpacing,
|
||||
new Vector2(hotbarPadding, hotbarPadding)
|
||||
);
|
||||
InventoryManager.Instance.hotbarSlots = CreateSlots(hotbarGrid, "HotbarSlot_", 0, hotbarSlots);
|
||||
|
||||
// Настраиваем InventoryManager
|
||||
InventoryManager.Instance.inventoryPanel = inventoryPanel;
|
||||
InventoryManager.Instance.inventoryCanvas = inventoryCanvas;
|
||||
|
||||
Debug.Log($"[InventoryUIBuilder] Created {inventoryCols * inventoryRows} inventory slots + {hotbarSlots} hotbar slots");
|
||||
}
|
||||
|
||||
GameObject CreatePanel(string name, Transform parent, Color color)
|
||||
{
|
||||
GameObject panel = new GameObject(name);
|
||||
panel.transform.SetParent(parent, false);
|
||||
|
||||
var rect = panel.AddComponent<RectTransform>();
|
||||
panel.AddComponent<Image>().color = color;
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
void CreateTitle(Transform parent, string text, Vector2 position)
|
||||
{
|
||||
GameObject titleObj = new GameObject("Title");
|
||||
titleObj.transform.SetParent(parent, false);
|
||||
|
||||
var rect = titleObj.AddComponent<RectTransform>();
|
||||
rect.anchorMin = new Vector2(0, 1);
|
||||
rect.anchorMax = new Vector2(1, 1);
|
||||
rect.pivot = new Vector2(0.5f, 1);
|
||||
rect.anchoredPosition = position;
|
||||
rect.sizeDelta = new Vector2(-20, 30);
|
||||
|
||||
var tmp = titleObj.AddComponent<TextMeshProUGUI>();
|
||||
tmp.text = text;
|
||||
tmp.fontSize = 18;
|
||||
tmp.alignment = TextAlignmentOptions.Center;
|
||||
tmp.color = Color.white;
|
||||
}
|
||||
|
||||
Transform CreateGrid(Transform parent, string name, int cols, int rows, float cellSize, float spacing, Vector2 offset)
|
||||
{
|
||||
GameObject gridObj = new GameObject(name);
|
||||
gridObj.transform.SetParent(parent, false);
|
||||
|
||||
var rect = gridObj.AddComponent<RectTransform>();
|
||||
rect.anchorMin = Vector2.zero;
|
||||
rect.anchorMax = Vector2.one;
|
||||
rect.offsetMin = offset;
|
||||
rect.offsetMax = -offset;
|
||||
|
||||
var grid = gridObj.AddComponent<GridLayoutGroup>();
|
||||
grid.cellSize = new Vector2(cellSize, cellSize);
|
||||
grid.spacing = new Vector2(spacing, spacing);
|
||||
grid.startCorner = GridLayoutGroup.Corner.UpperLeft;
|
||||
grid.startAxis = GridLayoutGroup.Axis.Horizontal;
|
||||
grid.constraint = GridLayoutGroup.Constraint.FixedColumnCount;
|
||||
grid.constraintCount = cols;
|
||||
grid.padding = new RectOffset(0, 0, 0, 0);
|
||||
|
||||
return gridObj.transform;
|
||||
}
|
||||
|
||||
Slot[] CreateSlots(Transform parent, string prefix, int startIndex, int count)
|
||||
{
|
||||
var slots = new Slot[count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
GameObject slotObj = new GameObject(prefix + (startIndex + i));
|
||||
slotObj.transform.SetParent(parent, false);
|
||||
|
||||
var rect = slotObj.AddComponent<RectTransform>();
|
||||
rect.sizeDelta = new Vector2(slotSize, slotSize);
|
||||
|
||||
// Background
|
||||
var bg = slotObj.AddComponent<Image>();
|
||||
bg.color = slotEmptyColor;
|
||||
|
||||
// Slot компонент
|
||||
var slot = slotObj.AddComponent<Slot>();
|
||||
slot.slotIndex = startIndex + i;
|
||||
|
||||
// Icon
|
||||
GameObject iconObj = new GameObject("Icon");
|
||||
iconObj.transform.SetParent(slotObj.transform, false);
|
||||
var iconRect = iconObj.AddComponent<RectTransform>();
|
||||
iconRect.anchorMin = Vector2.zero;
|
||||
iconRect.anchorMax = Vector2.one;
|
||||
iconRect.offsetMin = new Vector2(4, 4);
|
||||
iconRect.offsetMax = new Vector2(-4, -4);
|
||||
slot.iconImage = iconObj.AddComponent<Image>();
|
||||
slot.iconImage.preserveAspect = true;
|
||||
slot.iconImage.enabled = false;
|
||||
|
||||
// Amount panel
|
||||
GameObject amountObj = new GameObject("AmountPanel");
|
||||
amountObj.transform.SetParent(slotObj.transform, false);
|
||||
var amountRect = amountObj.AddComponent<RectTransform>();
|
||||
amountRect.anchorMin = Vector2.one;
|
||||
amountRect.anchorMax = Vector2.one;
|
||||
amountRect.pivot = new Vector2(1, 0);
|
||||
amountRect.anchoredPosition = new Vector2(-2, 2);
|
||||
amountRect.sizeDelta = new Vector2(22, 22);
|
||||
slot.amountPanel = amountObj;
|
||||
|
||||
var amountBg = amountObj.AddComponent<Image>();
|
||||
amountBg.color = new Color(0, 0, 0, 0.7f);
|
||||
|
||||
GameObject amountTextObj = new GameObject("Text");
|
||||
amountTextObj.transform.SetParent(amountObj.transform, false);
|
||||
var amountTextRect = amountTextObj.AddComponent<RectTransform>();
|
||||
amountTextRect.anchorMin = Vector2.zero;
|
||||
amountTextRect.anchorMax = Vector2.one;
|
||||
slot.amountText = amountTextObj.AddComponent<TextMeshProUGUI>();
|
||||
slot.amountText.fontSize = 14;
|
||||
slot.amountText.alignment = TextAlignmentOptions.Right;
|
||||
slot.amountText.color = Color.white;
|
||||
slot.amountText.fontStyle = FontStyles.Bold;
|
||||
|
||||
// Применяем настройки через сеттер
|
||||
slot.amountPanel.SetActive(false);
|
||||
slot.slotBackground = bg;
|
||||
|
||||
// Drag & Drop
|
||||
var dragDrop = slotObj.AddComponent<InventoryDragDrop>();
|
||||
dragDrop.slot = slot;
|
||||
dragDrop.slotIndex = slot.slotIndex;
|
||||
|
||||
// Подписка на события слота
|
||||
slot.OnSlotClicked += OnSlotClicked;
|
||||
|
||||
slots[i] = slot;
|
||||
}
|
||||
|
||||
return slots;
|
||||
}
|
||||
|
||||
private int _selectedSlot = -1;
|
||||
|
||||
private void OnSlotClicked(Slot slot)
|
||||
{
|
||||
// Снимаем выделение с предыдущего
|
||||
if (_selectedSlot >= 0 && _selectedSlot < InventoryManager.Instance.slots.Length)
|
||||
{
|
||||
InventoryManager.Instance.slots[_selectedSlot].SetSelected(false);
|
||||
}
|
||||
|
||||
// Выделяем новый
|
||||
slot.SetSelected(true);
|
||||
_selectedSlot = slot.slotIndex;
|
||||
|
||||
Debug.Log($"[UI] Selected slot: {_selectedSlot} - {slot.GetItem()?.itemName ?? "Empty"}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Пересоздать UI (например, при изменении настроек)
|
||||
/// </summary>
|
||||
public void Rebuild()
|
||||
{
|
||||
// Удаляем старые панели
|
||||
if (inventoryPanelRect != null)
|
||||
Destroy(inventoryPanelRect.gameObject);
|
||||
if (hotbarPanelRect != null)
|
||||
Destroy(hotbarPanelRect.gameObject);
|
||||
|
||||
BuildInventoryUI();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Показать/скрыть инвентарь
|
||||
/// </summary>
|
||||
public void ToggleInventory(bool show)
|
||||
{
|
||||
if (inventoryPanelRect != null)
|
||||
inventoryPanelRect.gameObject.SetActive(show);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user