using UnityEngine;
using UnityEngine.UI;
using TMPro;
///
/// Слот инвентаря - отображает предмет и его количество
///
public class Slot : MonoBehaviour
{
public int slotIndex;
public ItemData item;
public int amount;
[Header("UI References")]
public Image iconImage;
public TextMeshProUGUI amountText;
public GameObject amountPanel;
public Image slotBackground;
[Header("Visual Settings")]
[SerializeField] private Color emptySlotColor = new Color(0.2f, 0.2f, 0.2f, 0.5f);
[SerializeField] private Color filledSlotColor = new Color(0.3f, 0.3f, 0.3f, 0.9f);
[SerializeField] private Color hoverColor = new Color(0.5f, 0.5f, 0.5f, 1f);
[SerializeField] private Color selectedColor = new Color(0.4f, 0.6f, 0.9f, 1f);
[Header("Drag & Drop")]
[SerializeField] private bool allowDrag = true;
public bool IsEmpty => item == null || amount <= 0;
public bool HasItem => !IsEmpty;
// События для внешних подписчиков
public System.Action OnSlotClicked;
public System.Action OnSlotRightClicked;
public System.Action OnSlotHovered;
public System.Action OnSlotDragStart;
private bool _isSelected;
void Awake()
{
// Автоматическое получение компонентов если не назначены
if (iconImage == null)
iconImage = transform.Find("Icon")?.GetComponent();
if (amountText == null)
amountText = transform.Find("AmountPanel/Text")?.GetComponent();
if (amountPanel == null)
amountPanel = transform.Find("AmountPanel")?.gameObject;
if (slotBackground == null)
slotBackground = GetComponent();
}
void Start()
{
UpdateSlotUI();
}
///
/// Обновить визуальное отображение слота
///
public void UpdateSlotUI()
{
if (IsEmpty)
{
ClearVisuals();
return;
}
// Иконка
if (item.icon != null)
{
iconImage.sprite = item.icon;
iconImage.enabled = true;
}
else
{
iconImage.enabled = false;
}
// Количество
if (amount > 1)
{
amountText.text = amount.ToString();
amountPanel.SetActive(true);
}
else
{
amountPanel.SetActive(false);
}
// Цвет фона
if (slotBackground != null)
slotBackground.color = filledSlotColor;
}
private void ClearVisuals()
{
iconImage.sprite = null;
iconImage.enabled = false;
amountPanel?.SetActive(false);
if (slotBackground != null)
slotBackground.color = emptySlotColor;
}
///
/// Очистить слот
///
public void Clear()
{
item = null;
amount = 0;
UpdateSlotUI();
// Уведомляем менеджер
if (InventoryManager.Instance != null)
{
InventoryManager.Instance.OnSlotCleared(slotIndex);
}
// Вызываем событие
InventoryEvents.Instance?.InvokeSlotChanged(slotIndex, null);
}
///
/// Установить предмет в слот
///
public void SetItem(ItemData newItem, int newAmount)
{
item = newItem;
amount = newAmount;
UpdateSlotUI();
// Вызываем событие изменения
InventoryEvents.Instance?.InvokeSlotChanged(slotIndex, item?.id);
}
///
/// Добавить предметы в слот
///
/// Количество не поместившихся предметов
public int AddItems(ItemData newItem, int addAmount)
{
if (item == null)
{
// Пустой слот - просто кладём
item = newItem;
amount = Mathf.Min(addAmount, newItem.maxStack);
UpdateSlotUI();
// Событие добавления
InventoryEvents.Instance?.InvokeItemAdded(item.id, amount);
InventoryEvents.Instance?.InvokeSlotChanged(slotIndex, item.id);
return addAmount - amount;
}
if (item.id != newItem.id)
{
// Другой предмет - нельзя добавить
return addAmount;
}
// Тот же предмет - пытаемся добавить в стек
int space = item.maxStack - amount;
if (space <= 0) return addAmount;
int toAdd = Mathf.Min(space, addAmount);
amount += toAdd;
UpdateSlotUI();
// Событие изменения
InventoryEvents.Instance?.InvokeItemCountChanged(item.id, amount);
InventoryEvents.Instance?.InvokeSlotChanged(slotIndex, item.id);
return addAmount - toAdd;
}
///
/// Взять часть предметов из слота
///
/// (предмет, взятое количество)
public (ItemData, int) TakeItems(int takeAmount)
{
if (IsEmpty) return (null, 0);
int actualTake = Mathf.Min(takeAmount, amount);
amount -= actualTake;
ItemData resultItem = item;
if (amount <= 0)
{
Clear();
}
else
{
UpdateSlotUI();
// Событие изменения количества
InventoryEvents.Instance?.InvokeItemCountChanged(item.id, amount);
}
// Событие удаления
InventoryEvents.Instance?.InvokeItemRemoved(resultItem.id, actualTake);
return (resultItem, actualTake);
}
///
/// Взять все предметы из слота
///
public (ItemData, int) TakeAll()
{
return TakeItems(amount);
}
// ==================== UI Events ====================
void OnMouseEnter()
{
if (slotBackground != null && !_isSelected)
slotBackground.color = hoverColor;
OnSlotHovered?.Invoke(this);
}
void OnMouseExit()
{
if (slotBackground != null && !_isSelected)
slotBackground.color = IsEmpty ? emptySlotColor : filledSlotColor;
}
void OnMouseDown()
{
if (Input.GetMouseButton(0))
{
OnSlotClicked?.Invoke(this);
if (allowDrag)
{
OnSlotDragStart?.Invoke(this);
}
}
else if (Input.GetMouseButton(1))
{
OnSlotRightClicked?.Invoke(this);
}
}
///
/// Установить состояние выделения слота
///
public void SetSelected(bool selected)
{
_isSelected = selected;
if (slotBackground != null)
{
slotBackground.color = selected ? selectedColor :
(IsEmpty ? emptySlotColor : filledSlotColor);
}
}
///
/// Поменять содержимое с другим слотом
///
public void SwapWith(Slot other)
{
if (other == null || other == this) return;
var tempItem = this.item;
var tempAmount = this.amount;
this.SetItem(other.item, other.amount);
other.SetItem(tempItem, tempAmount);
}
// ==================== Getters ====================
public ItemData GetItem() => item;
public int GetAmount() => amount;
public string GetItemId() => item?.id;
public bool IsSelected() => _isSelected;
}