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 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; }