340 lines
9.0 KiB
C#
340 lines
9.0 KiB
C#
using System.Collections;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.UI;
|
|
|
|
public enum InventorySlotClickMode
|
|
{
|
|
None,
|
|
ShowDetail,
|
|
RequestUse
|
|
}
|
|
|
|
/// <summary>
|
|
/// 인벤토리 슬롯 하나를 담당하는 UI 스크립트입니다.
|
|
/// VR 포인터 Hover/Select, NEW 배지, 0개 흐림 표시, 중요 아이템 강조, 상세보기/사용 클릭을 지원합니다.
|
|
/// </summary>
|
|
[DisallowMultipleComponent]
|
|
public class InventorySlotUI : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler, ISelectHandler, IDeselectHandler, ISubmitHandler
|
|
{
|
|
[Header("Item")]
|
|
[SerializeField] private InventoryItemType itemType;
|
|
|
|
[Header("UI References")]
|
|
[SerializeField] private Image slotBackground;
|
|
[SerializeField] private Image itemIcon;
|
|
[SerializeField] private TMP_Text countText;
|
|
[SerializeField] private GameObject newBadge;
|
|
[SerializeField] private CanvasGroup canvasGroup;
|
|
[SerializeField] private GameObject importantGlowObject;
|
|
[SerializeField] private GameObject filteredOutOverlay;
|
|
|
|
[Header("Tooltip / Parent UI")]
|
|
[SerializeField] private InventoryTooltipUI tooltipUI;
|
|
[SerializeField] private InventoryUI inventoryUI;
|
|
|
|
[Header("Click")]
|
|
[SerializeField] private InventorySlotClickMode clickMode = InventorySlotClickMode.ShowDetail;
|
|
|
|
[Header("Settings")]
|
|
[Tooltip("VR에서는 false 권장. 슬롯이 사라지면 Ray 조작 위치가 바뀌어 불편할 수 있습니다.")]
|
|
[SerializeField] private bool hideWhenZero = false;
|
|
[SerializeField] private bool dimWhenZero = true;
|
|
[SerializeField] private float zeroAlpha = 0.35f;
|
|
[SerializeField] private float ownedAlpha = 1f;
|
|
[SerializeField] private float filteredAlpha = 0.15f;
|
|
[SerializeField] private bool showCountWhenZero = true;
|
|
[SerializeField] private bool showMaxCount = false;
|
|
[SerializeField] private float newBadgeShowTime = 1.2f;
|
|
|
|
[Header("Hover Effect")]
|
|
[SerializeField] private bool useHoverScale = true;
|
|
[SerializeField] private float hoverScale = 1.08f;
|
|
[SerializeField] private bool bringToFrontOnHover = true;
|
|
|
|
private int currentCount;
|
|
private int currentMaxCount;
|
|
private bool filteredOut;
|
|
private Coroutine newBadgeRoutine;
|
|
private Vector3 originalScale;
|
|
private InventoryItemDefinition definition;
|
|
|
|
public InventoryItemType ItemType => itemType;
|
|
public int CurrentCount => currentCount;
|
|
public InventoryItemCategory Category => definition != null ? definition.category : InventoryItemCategory.Other;
|
|
|
|
private void Awake()
|
|
{
|
|
originalScale = transform.localScale;
|
|
|
|
if (canvasGroup == null)
|
|
canvasGroup = GetComponent<CanvasGroup>();
|
|
|
|
if (slotBackground == null)
|
|
slotBackground = GetComponent<Image>();
|
|
|
|
if (inventoryUI == null)
|
|
inventoryUI = GetComponentInParent<InventoryUI>();
|
|
|
|
if (tooltipUI == null)
|
|
tooltipUI = GetComponentInParent<InventoryTooltipUI>();
|
|
|
|
if (newBadge != null)
|
|
newBadge.SetActive(false);
|
|
|
|
UpdateVisualState();
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
HideNewBadge();
|
|
HideTooltip();
|
|
ResetHoverVisual();
|
|
}
|
|
|
|
public void SetInventoryUI(InventoryUI ui)
|
|
{
|
|
inventoryUI = ui;
|
|
}
|
|
|
|
public void SetItemType(InventoryItemType newItemType)
|
|
{
|
|
itemType = newItemType;
|
|
}
|
|
|
|
public void SetDefinition(InventoryItemDefinition newDefinition)
|
|
{
|
|
definition = newDefinition;
|
|
|
|
if (definition == null)
|
|
{
|
|
UpdateVisualState();
|
|
return;
|
|
}
|
|
|
|
if (itemIcon != null)
|
|
{
|
|
itemIcon.sprite = definition.icon;
|
|
itemIcon.enabled = definition.icon != null;
|
|
}
|
|
|
|
if (slotBackground != null && definition.slotBackground != null)
|
|
{
|
|
slotBackground.sprite = definition.slotBackground;
|
|
slotBackground.enabled = true;
|
|
}
|
|
|
|
if (definition.overrideSlotDisplaySettings)
|
|
{
|
|
hideWhenZero = definition.hideWhenZero;
|
|
dimWhenZero = definition.dimWhenZero;
|
|
zeroAlpha = definition.zeroAlpha;
|
|
ownedAlpha = definition.ownedAlpha;
|
|
}
|
|
|
|
if (importantGlowObject != null)
|
|
importantGlowObject.SetActive(definition.importantItem);
|
|
|
|
UpdateVisualState();
|
|
}
|
|
|
|
public void SetCount(int count, bool showNewBadge)
|
|
{
|
|
SetCount(count, showNewBadge, currentMaxCount);
|
|
}
|
|
|
|
public void SetCount(int count, bool showNewBadge, int maxCount)
|
|
{
|
|
int previousCount = currentCount;
|
|
currentCount = Mathf.Max(0, count);
|
|
currentMaxCount = Mathf.Max(0, maxCount);
|
|
|
|
UpdateVisualState();
|
|
|
|
if (showNewBadge && currentCount > previousCount)
|
|
ShowNewBadge();
|
|
}
|
|
|
|
public void SetIcon(Sprite sprite)
|
|
{
|
|
if (itemIcon == null)
|
|
return;
|
|
|
|
itemIcon.sprite = sprite;
|
|
itemIcon.enabled = sprite != null;
|
|
}
|
|
|
|
public void SetSlotBackground(Sprite sprite)
|
|
{
|
|
if (slotBackground == null)
|
|
return;
|
|
|
|
slotBackground.sprite = sprite;
|
|
slotBackground.enabled = sprite != null;
|
|
}
|
|
|
|
public void SetFilteredOut(bool value)
|
|
{
|
|
filteredOut = value;
|
|
|
|
if (filteredOutOverlay != null)
|
|
filteredOutOverlay.SetActive(value);
|
|
|
|
UpdateVisualState();
|
|
}
|
|
|
|
public void SetHoverSettings(bool useScale, float scale, bool bringToFront)
|
|
{
|
|
useHoverScale = useScale;
|
|
hoverScale = Mathf.Max(1f, scale);
|
|
bringToFrontOnHover = bringToFront;
|
|
}
|
|
|
|
public void ShowNewBadge()
|
|
{
|
|
if (newBadge == null)
|
|
return;
|
|
|
|
if (newBadgeRoutine != null)
|
|
StopCoroutine(newBadgeRoutine);
|
|
|
|
newBadgeRoutine = StartCoroutine(NewBadgeRoutine());
|
|
}
|
|
|
|
public void HideNewBadge()
|
|
{
|
|
if (newBadgeRoutine != null)
|
|
{
|
|
StopCoroutine(newBadgeRoutine);
|
|
newBadgeRoutine = null;
|
|
}
|
|
|
|
if (newBadge != null)
|
|
newBadge.SetActive(false);
|
|
}
|
|
|
|
private IEnumerator NewBadgeRoutine()
|
|
{
|
|
newBadge.SetActive(true);
|
|
yield return new WaitForSecondsRealtime(newBadgeShowTime);
|
|
newBadge.SetActive(false);
|
|
newBadgeRoutine = null;
|
|
}
|
|
|
|
private void UpdateVisualState()
|
|
{
|
|
bool hasItem = currentCount > 0;
|
|
|
|
if (countText != null)
|
|
{
|
|
if (!showCountWhenZero && currentCount <= 0)
|
|
countText.text = string.Empty;
|
|
else if (showMaxCount && currentMaxCount > 0)
|
|
countText.text = $"x{currentCount}/{currentMaxCount}";
|
|
else
|
|
countText.text = $"x{currentCount}";
|
|
}
|
|
|
|
if (hideWhenZero)
|
|
gameObject.SetActive(hasItem);
|
|
|
|
if (canvasGroup != null && dimWhenZero)
|
|
{
|
|
float targetAlpha = hasItem ? ownedAlpha : zeroAlpha;
|
|
if (filteredOut)
|
|
targetAlpha = Mathf.Min(targetAlpha, filteredAlpha);
|
|
|
|
canvasGroup.alpha = targetAlpha;
|
|
canvasGroup.interactable = !filteredOut;
|
|
canvasGroup.blocksRaycasts = !filteredOut;
|
|
}
|
|
}
|
|
|
|
public void OnPointerEnter(PointerEventData eventData)
|
|
{
|
|
ApplyHoverVisual();
|
|
ShowTooltip();
|
|
}
|
|
|
|
public void OnPointerExit(PointerEventData eventData)
|
|
{
|
|
ResetHoverVisual();
|
|
HideTooltip();
|
|
}
|
|
|
|
public void OnPointerClick(PointerEventData eventData)
|
|
{
|
|
ActivateSlot();
|
|
}
|
|
|
|
public void OnSelect(BaseEventData eventData)
|
|
{
|
|
ApplyHoverVisual();
|
|
ShowTooltip();
|
|
}
|
|
|
|
public void OnDeselect(BaseEventData eventData)
|
|
{
|
|
ResetHoverVisual();
|
|
HideTooltip();
|
|
}
|
|
|
|
public void OnSubmit(BaseEventData eventData)
|
|
{
|
|
ActivateSlot();
|
|
}
|
|
|
|
private void ActivateSlot()
|
|
{
|
|
if (filteredOut)
|
|
return;
|
|
|
|
if (inventoryUI == null)
|
|
inventoryUI = GetComponentInParent<InventoryUI>();
|
|
|
|
if (inventoryUI == null)
|
|
return;
|
|
|
|
switch (clickMode)
|
|
{
|
|
case InventorySlotClickMode.ShowDetail:
|
|
inventoryUI.ShowItemDetail(itemType);
|
|
break;
|
|
case InventorySlotClickMode.RequestUse:
|
|
inventoryUI.RequestUseItem(itemType, 1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void ApplyHoverVisual()
|
|
{
|
|
if (bringToFrontOnHover)
|
|
transform.SetAsLastSibling();
|
|
|
|
if (useHoverScale)
|
|
transform.localScale = originalScale * hoverScale;
|
|
}
|
|
|
|
private void ResetHoverVisual()
|
|
{
|
|
if (useHoverScale)
|
|
transform.localScale = originalScale;
|
|
}
|
|
|
|
public void ShowTooltip()
|
|
{
|
|
if (tooltipUI == null)
|
|
tooltipUI = GetComponentInParent<InventoryTooltipUI>();
|
|
|
|
if (tooltipUI != null)
|
|
tooltipUI.ShowTooltip(itemType, currentCount, currentMaxCount);
|
|
}
|
|
|
|
public void HideTooltip()
|
|
{
|
|
if (tooltipUI != null)
|
|
tooltipUI.HideTooltip();
|
|
}
|
|
}
|