using UnityEngine; using UnityEngine.UI; using TMPro; using System; using System.Collections.Generic; using UnityEngine.EventSystems; using DG.Tweening; using UnityEngine.InputSystem; namespace Ashwild.Inventory { public class SlotContextMenu : MonoBehaviour { [Header("References")] [SerializeField] private RectTransform panelRect; [SerializeField] private CanvasGroup canvasGroup; [SerializeField] private Transform buttonContainer; [SerializeField] private GameObject buttonPrefab; [Header("Settings")] [SerializeField] private Vector2 offset = new Vector2(10f, -10f); [Header("Animation")] [SerializeField] private float showDuration = 0.2f; [SerializeField] private float hideDuration = 0.15f; [SerializeField] private Ease showEase = Ease.OutBack; [SerializeField] private Ease hideEase = Ease.InQuad; private int currentSlotIndex = -1; private readonly List activeButtons = new List(); private Canvas rootCanvas; private bool isVisible; private Tweener scaleTween; private Tweener fadeTween; private void Awake() { rootCanvas = GetComponentInParent(); SetHidden(); } private void SetHidden() { canvasGroup.gameObject.SetActive(false); canvasGroup.alpha = 0f; canvasGroup.interactable = false; canvasGroup.blocksRaycasts = false; panelRect.localScale = Vector3.zero; } private void OnDestroy() { scaleTween?.Kill(); fadeTween?.Kill(); } private void Update() { if (!isVisible) return; Mouse mouse = Mouse.current; if (mouse == null) return; if (mouse.leftButton.wasPressedThisFrame || mouse.rightButton.wasPressedThisFrame) { if (!IsPointerOverMenu()) Hide(); } } public void Show(int slotIndex) { PlayerInventory inv = PlayerInventory.Instance; InventorySlot slot = inv.GetSlot(slotIndex); if (slot == null || slot.IsEmpty) return; // Kill any running animation and clear previous buttons scaleTween?.Kill(); fadeTween?.Kill(); ClearButtons(); currentSlotIndex = slotIndex; bool isHotbar = slotIndex < inv.HotbarSize; bool canSplit = slot.Quantity > 1; if (isHotbar) AddButton("Move to Inventory", OnMoveToInventory); else AddButton("Equip", OnEquipToHotbar); if (slot.ItemData.ItemType == ItemType.Consumable) AddButton("Use", OnUseItem); AddButton("Drop", OnDrop); if (canSplit) AddButton("Split", OnSplit); // Activate and position canvasGroup.gameObject.SetActive(true); Vector2 mousePos = Mouse.current != null ? Mouse.current.position.ReadValue() : Vector2.zero; PositionMenu(mousePos); // Animate in isVisible = true; panelRect.localScale = Vector3.one * 0.5f; canvasGroup.alpha = 0f; scaleTween?.Kill(); fadeTween?.Kill(); scaleTween = panelRect.DOScale(1f, showDuration).SetEase(showEase).SetUpdate(true); fadeTween = canvasGroup.DOFade(1f, showDuration).SetUpdate(true).OnComplete(() => { canvasGroup.interactable = true; canvasGroup.blocksRaycasts = true; }); } public void Hide() { if (!isVisible) return; isVisible = false; canvasGroup.interactable = false; canvasGroup.blocksRaycasts = false; scaleTween?.Kill(); fadeTween?.Kill(); scaleTween = panelRect.DOScale(0f, hideDuration).SetEase(hideEase).SetUpdate(true); fadeTween = canvasGroup.DOFade(0f, hideDuration).SetUpdate(true).OnComplete(() => { canvasGroup.gameObject.SetActive(false); ClearButtons(); currentSlotIndex = -1; }); } private void PositionMenu(Vector2 screenPosition) { if (rootCanvas == null) rootCanvas = GetComponentInParent(); RectTransform canvasRect = rootCanvas.transform as RectTransform; RectTransformUtility.ScreenPointToLocalPointInRectangle( canvasRect, screenPosition, rootCanvas.worldCamera, out Vector2 anchoredPos); anchoredPos += offset; // Clamp to stay within canvas bounds Vector2 menuSize = panelRect.sizeDelta; Vector2 canvasSize = canvasRect.sizeDelta; float halfW = canvasSize.x * 0.5f; float halfH = canvasSize.y * 0.5f; if (anchoredPos.x + menuSize.x > halfW) anchoredPos.x = halfW - menuSize.x; if (anchoredPos.y - menuSize.y < -halfH) anchoredPos.y = -halfH + menuSize.y; panelRect.anchoredPosition = anchoredPos; } private void AddButton(string label, Action onClick) { GameObject btnGO = Instantiate(buttonPrefab, buttonContainer); btnGO.SetActive(true); TextMeshProUGUI text = btnGO.GetComponentInChildren(); if (text != null) text.text = label; Button btn = btnGO.GetComponent