Files
2026-07-22 05:35:53 +08:00

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