353 lines
12 KiB
C#
353 lines
12 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace Bansonic
|
|
{
|
|
public static class gItemGet
|
|
{
|
|
private const string PrefabResourcePath = "itemGet";
|
|
private static readonly Color FallbackColor = Color.white;
|
|
|
|
private static GameObject currentInstance;
|
|
private static itemGetPrefab currentController;
|
|
private static ItemRarityColorConfigSO cachedRarityConfig;
|
|
|
|
public struct ItemEntry
|
|
{
|
|
public Sprite icon;
|
|
public string displayName;
|
|
public int amount;
|
|
public ItemRarity rarity;
|
|
public bool useCustomColor;
|
|
public Color customColor;
|
|
}
|
|
|
|
public static void display(params ItemEntry[] items)
|
|
{
|
|
display((IEnumerable<ItemEntry>)items);
|
|
}
|
|
|
|
public static void display(IEnumerable<ItemEntry> items)
|
|
{
|
|
EnsureInstance();
|
|
if (currentController == null)
|
|
{
|
|
Debug.LogWarning("[gItemGet] itemGet prefab missing itemGetPrefab component.");
|
|
return;
|
|
}
|
|
|
|
currentController.ClearItems();
|
|
|
|
if (items == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
foreach (ItemEntry entry in items)
|
|
{
|
|
get_item_prefab item = currentController.AddItem();
|
|
if (item == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Sprite backgroundSprite = entry.useCustomColor
|
|
? null
|
|
: ResolveRarityBackgroundSprite(entry.rarity);
|
|
|
|
Color qualityColor = entry.useCustomColor
|
|
? entry.customColor
|
|
: ResolveRarityColor(entry.rarity);
|
|
|
|
item.Bind(entry.icon, entry.displayName, entry.amount, qualityColor, backgroundSprite);
|
|
}
|
|
}
|
|
|
|
public static ItemEntry Create(string displayName, Sprite icon, int amount = 1, ItemRarity rarity = ItemRarity.None)
|
|
{
|
|
return new ItemEntry
|
|
{
|
|
displayName = displayName,
|
|
icon = icon,
|
|
amount = Mathf.Max(1, amount),
|
|
rarity = rarity,
|
|
useCustomColor = false,
|
|
customColor = default
|
|
};
|
|
}
|
|
|
|
public static ItemEntry Create(string displayName, Sprite icon, int amount, Color qualityColor)
|
|
{
|
|
return new ItemEntry
|
|
{
|
|
displayName = displayName,
|
|
icon = icon,
|
|
amount = Mathf.Max(1, amount),
|
|
rarity = ItemRarity.None,
|
|
useCustomColor = true,
|
|
customColor = qualityColor
|
|
};
|
|
}
|
|
|
|
public static ItemEntry FromStoreItem(storeItemSO item, int amount = 1)
|
|
{
|
|
if (item == null)
|
|
{
|
|
return Create(LocalizationService.Get("item.unknown.store_item", "Unknown Item"), null, amount, ItemRarity.None);
|
|
}
|
|
|
|
return Create(item.itemName, item.itemIcon, amount, item.itemRarity);
|
|
}
|
|
|
|
public static ItemEntry FromExpBottle(expBottlesSO item, int amount = 1)
|
|
{
|
|
if (item == null)
|
|
{
|
|
return Create(LocalizationService.Get("item.unknown.exp_bottle", "Unknown EXP Bottle"), null, amount, ItemRarity.None);
|
|
}
|
|
|
|
return Create(item.expBottleName, item.expBottleSprite, amount, item.itemRarity);
|
|
}
|
|
|
|
public static ItemEntry FromGrowthMaterial(growthMaterialSO item, int amount = 1)
|
|
{
|
|
if (item == null)
|
|
{
|
|
return Create(LocalizationService.Get("item.unknown.growth_material", "Unknown Growth Material"), null, amount, ItemRarity.None);
|
|
}
|
|
|
|
return Create(item.growthMaterialName, item.growthMaterialSprite, amount, item.itemRarity);
|
|
}
|
|
|
|
public static ItemEntry FromEquipmentConsumable(equipmentConsumableSO item, int amount = 1)
|
|
{
|
|
if (item == null)
|
|
{
|
|
return Create(LocalizationService.Get("item.unknown.equipment_material", "Unknown Equipment Material"), null, amount, ItemRarity.None);
|
|
}
|
|
|
|
return Create(item.consumableName, item.consumableSprite, amount, item.itemRarity);
|
|
}
|
|
|
|
public static ItemEntry FromEquipment(equipmentSO equipment, int amount = 1)
|
|
{
|
|
if (equipment == null)
|
|
{
|
|
return Create(LocalizationService.Get("item.unknown.memory", "Unknown Memory"), null, amount, ItemRarity.None);
|
|
}
|
|
|
|
return Create(
|
|
equipment.GetDisplayTierName(),
|
|
equipment.GetCurrentEquipmentSprite(),
|
|
amount,
|
|
ResolveEquipmentColor(equipment));
|
|
}
|
|
|
|
private static void EnsureInstance()
|
|
{
|
|
if (currentInstance != null && currentController != null)
|
|
{
|
|
ReparentIfNeeded();
|
|
EnsureTopMostSorting();
|
|
if (!currentInstance.activeInHierarchy)
|
|
{
|
|
currentInstance.SetActive(true);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
GameObject prefab = Resources.Load<GameObject>(PrefabResourcePath);
|
|
if (prefab == null)
|
|
{
|
|
Debug.LogWarning("[gItemGet] Failed to load Resources/itemGet.prefab");
|
|
return;
|
|
}
|
|
|
|
Transform parent = ResolveParent();
|
|
currentInstance = parent != null
|
|
? Object.Instantiate(prefab, parent, false)
|
|
: Object.Instantiate(prefab);
|
|
|
|
currentInstance.name = prefab.name;
|
|
currentController = currentInstance.GetComponent<itemGetPrefab>();
|
|
ReparentIfNeeded();
|
|
EnsureTopMostSorting();
|
|
}
|
|
|
|
// 确保 itemGet 弹窗永远显示在所有 UI 之上(包括名为 "top" 的高层覆盖界面)。
|
|
// itemGet.prefab 本身无 Canvas,靠父 Canvas 渲染,故会被 sortingOrder 更高的 Canvas 遮挡。
|
|
// 方案:在实例根挂一个 override sorting 的 Canvas,设定极高 sortingOrder。
|
|
// 仅表现层:不改 itemGet 内部结构/引用/逻辑,只保证其可见性置顶。
|
|
private const int ItemGetSortingOrder = 32760; // 接近 short.MaxValue,高于常规 UI/top
|
|
private static void EnsureTopMostSorting()
|
|
{
|
|
if (currentInstance == null) return;
|
|
|
|
Canvas canvas = currentInstance.GetComponent<Canvas>();
|
|
if (canvas == null) canvas = currentInstance.AddComponent<Canvas>();
|
|
canvas.overrideSorting = true;
|
|
canvas.sortingOrder = ItemGetSortingOrder;
|
|
|
|
// override Canvas 需配 GraphicRaycaster 才能接收点击(关闭按钮等)。
|
|
if (currentInstance.GetComponent<UnityEngine.UI.GraphicRaycaster>() == null)
|
|
currentInstance.AddComponent<UnityEngine.UI.GraphicRaycaster>();
|
|
}
|
|
|
|
private static Transform ResolveParent()
|
|
{
|
|
Canvas[] canvases = Object.FindObjectsByType<Canvas>(FindObjectsInactive.Exclude, FindObjectsSortMode.None);
|
|
Canvas best = null;
|
|
|
|
for (int i = 0; i < canvases.Length; i++)
|
|
{
|
|
Canvas canvas = canvases[i];
|
|
if (canvas == null || !canvas.gameObject.activeInHierarchy || !canvas.isRootCanvas)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (IsTransitionCanvas(canvas))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (best == null || canvas.sortingOrder >= best.sortingOrder)
|
|
{
|
|
best = canvas;
|
|
}
|
|
}
|
|
|
|
return best != null ? best.transform : null;
|
|
}
|
|
|
|
private static void ReparentIfNeeded()
|
|
{
|
|
if (currentInstance == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Transform currentParent = currentInstance.transform.parent;
|
|
bool needsReparent = currentParent == null || HasTransitionAncestor(currentParent);
|
|
if (!needsReparent)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Transform targetParent = ResolveParent();
|
|
if (targetParent == null || targetParent == currentParent)
|
|
{
|
|
return;
|
|
}
|
|
|
|
currentInstance.transform.SetParent(targetParent, false);
|
|
currentInstance.transform.SetAsLastSibling();
|
|
}
|
|
|
|
private static bool IsTransitionCanvas(Canvas canvas)
|
|
{
|
|
return canvas != null && HasTransitionAncestor(canvas.transform);
|
|
}
|
|
|
|
private static bool HasTransitionAncestor(Transform transform)
|
|
{
|
|
Transform current = transform;
|
|
while (current != null)
|
|
{
|
|
if (current.GetComponent<gTransBlack>() != null ||
|
|
current.GetComponent<BansonicSceneTransitionOverlay>() != null)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
current = current.parent;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static Color ResolveRarityColor(ItemRarity rarity)
|
|
{
|
|
ItemRarityColorConfigSO rarityConfig = GetRarityConfig();
|
|
if (rarityConfig != null)
|
|
{
|
|
return rarityConfig.GetColor(rarity, FallbackColor);
|
|
}
|
|
|
|
switch (rarity)
|
|
{
|
|
case ItemRarity.Common:
|
|
return new Color32(95, 155, 107, 255);
|
|
case ItemRarity.Uncommon:
|
|
return new Color32(74, 134, 184, 255);
|
|
case ItemRarity.Rare:
|
|
return new Color32(106, 76, 156, 255);
|
|
case ItemRarity.Epic:
|
|
return new Color32(184, 134, 69, 255);
|
|
case ItemRarity.Legendary:
|
|
return new Color32(184, 76, 76, 255);
|
|
case ItemRarity.Mythic:
|
|
return new Color32(217, 108, 158, 255);
|
|
case ItemRarity.Supreme:
|
|
return new Color32(255, 103, 164, 255);
|
|
default:
|
|
return FallbackColor;
|
|
}
|
|
}
|
|
|
|
private static Sprite ResolveRarityBackgroundSprite(ItemRarity rarity)
|
|
{
|
|
ItemRarityColorConfigSO rarityConfig = GetRarityConfig();
|
|
return rarityConfig != null
|
|
? rarityConfig.GetBackgroundSprite(rarity, null)
|
|
: null;
|
|
}
|
|
|
|
private static ItemRarityColorConfigSO GetRarityConfig()
|
|
{
|
|
if (currentController != null && currentController.rarityColorConfig != null)
|
|
{
|
|
cachedRarityConfig = currentController.rarityColorConfig;
|
|
return cachedRarityConfig;
|
|
}
|
|
|
|
if (cachedRarityConfig != null)
|
|
{
|
|
return cachedRarityConfig;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
cachedRarityConfig = UnityEditor.AssetDatabase.LoadAssetAtPath<ItemRarityColorConfigSO>(
|
|
"Assets/playerBagSystem/ItemRarityColorConfig.asset");
|
|
#endif
|
|
return cachedRarityConfig;
|
|
}
|
|
|
|
private static Color ResolveEquipmentColor(equipmentSO equipment)
|
|
{
|
|
if (equipment == null)
|
|
{
|
|
return FallbackColor;
|
|
}
|
|
|
|
int index = equipment.GetVisualQualityColorIndex();
|
|
switch (index)
|
|
{
|
|
case 1:
|
|
return new Color32(95, 155, 107, 255);
|
|
case 2:
|
|
return new Color32(74, 134, 184, 255);
|
|
case 3:
|
|
return new Color32(106, 76, 156, 255);
|
|
case 4:
|
|
return new Color32(184, 134, 69, 255);
|
|
case 5:
|
|
return new Color32(184, 76, 76, 255);
|
|
default:
|
|
return new Color32(255, 103, 164, 255);
|
|
}
|
|
}
|
|
}
|
|
}
|