1515 lines
47 KiB
C#
1515 lines
47 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Bansonic;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.UI;
|
|
using TMPro;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
public class uBag : MonoBehaviour
|
|
{
|
|
private const string MemorySystemComingSoonMessage = "\"记忆\"系统即将上线,敬请期待!";
|
|
|
|
private enum BagFilterMode
|
|
{
|
|
All,
|
|
Cultivation,
|
|
Precious,
|
|
Other
|
|
}
|
|
|
|
private enum BagSortMode
|
|
{
|
|
Default,
|
|
Name,
|
|
Rarity,
|
|
Count
|
|
}
|
|
|
|
private enum BagCategory
|
|
{
|
|
All,
|
|
Cultivation,
|
|
Precious,
|
|
Other
|
|
}
|
|
|
|
private enum PreciousKind
|
|
{
|
|
NotebookClue,
|
|
Character,
|
|
Level
|
|
}
|
|
|
|
private sealed class BagEntry
|
|
{
|
|
public string stableId;
|
|
public string displayName;
|
|
public string countText;
|
|
public string amountText;
|
|
public string usage;
|
|
public string description;
|
|
public Sprite icon;
|
|
public BagCategory category;
|
|
public int sortPriority;
|
|
public ItemRarity rarity;
|
|
}
|
|
|
|
[Header("category toggles")]
|
|
public ToggleGroup bagToggleGroup;
|
|
public Toggle allToggle;
|
|
public Toggle cultivateToggle;
|
|
public Toggle preciousToggle;
|
|
public Toggle otherToggle;
|
|
public Toggle equipSystemToggle;
|
|
|
|
[Header("OBJ")]
|
|
public GameObject bagObj;
|
|
public GameObject equipObj;
|
|
|
|
[Header("right panel")]
|
|
public Image btmImg;
|
|
public Image itemDprofile;
|
|
public TextMeshProUGUI itemAmount;
|
|
public Text itemName;
|
|
public Text itemUse;
|
|
public Text itemUsageLegacy;
|
|
public Text itemDescription;
|
|
public Image bottom_rarityImg;
|
|
public Sprite[] bottom_rarityImg_sprites;
|
|
|
|
[Header("list")]
|
|
public Transform itemParent;
|
|
public GameObject itemPrefab;
|
|
public Text emptyText;
|
|
[Min(1)] public int spawnBatchSize = 16;
|
|
|
|
[Header("introduction")]
|
|
public GameObject itemIntroductionPrefab;
|
|
public float introductionHoverDelay = 0.5f;
|
|
public int introductionHorizontalOffset = 12;
|
|
|
|
[Header("colors")]
|
|
public bool useRarityColorForItemName = true;
|
|
public Color fallbackColor = Color.white;
|
|
public Sprite fallbackItemIcon;
|
|
public Sprite fallbackBackgroundSprite;
|
|
public ItemRarityColorConfigSO rarityColorConfig;
|
|
|
|
[Header("filters")]
|
|
public Dropdown bag_filterDropdown;
|
|
public Dropdown bag_sortDropdown;
|
|
|
|
[Header("paths")]
|
|
[SerializeField] private string notebookEditorPath = "Assets/Resources/so/notebook";
|
|
[SerializeField] private string notebookRuntimePath = "so/notebook";
|
|
[SerializeField] private string storeItemEditorPath = "Assets/Resources/so/storeSO";
|
|
[SerializeField] private string storeItemRuntimePath = "so/storeSO";
|
|
[SerializeField] private string expBottleEditorPath = "Assets/storeSystem/items/medicines";
|
|
[SerializeField] private string growthMaterialEditorPath = "Assets/storeSystem/items/medicines";
|
|
[SerializeField] private string equipmentConsumableEditorPath = "Assets/storeSystem/items/medicines";
|
|
|
|
private readonly List<GameObject> spawnedItems = new List<GameObject>();
|
|
private readonly List<BagEntry> allEntries = new List<BagEntry>();
|
|
private readonly Dictionary<uBagItemPrefab, BagEntry> viewEntries = new Dictionary<uBagItemPrefab, BagEntry>();
|
|
private readonly List<Dropdown.OptionData> filterOptions = new List<Dropdown.OptionData>();
|
|
private readonly List<Dropdown.OptionData> sortOptions = new List<Dropdown.OptionData>();
|
|
private Coroutine rebuildRoutine;
|
|
private BagCategory currentCategory = BagCategory.All;
|
|
private BagFilterMode currentFilterMode = BagFilterMode.All;
|
|
private BagSortMode currentSortMode = BagSortMode.Default;
|
|
private GameObject spawnedIntroduction;
|
|
private uBagItemPrefab activePreviewSource;
|
|
|
|
private void Awake()
|
|
{
|
|
InitializeToggleGroup();
|
|
InitializeFilterDropdowns();
|
|
BindToggles();
|
|
BindFilterDropdowns();
|
|
BindLedgerEvents();
|
|
InitializeViewMode();
|
|
SelectDefaultCategory();
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
InitializeToggleGroup();
|
|
InitializeFilterDropdowns();
|
|
BindToggles();
|
|
BindFilterDropdowns();
|
|
BindLedgerEvents();
|
|
InitializeViewMode();
|
|
Rebuild();
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
UnbindToggle(allToggle, HandleAllChanged);
|
|
UnbindToggle(cultivateToggle, HandleCultivateChanged);
|
|
UnbindToggle(preciousToggle, HandlePreciousChanged);
|
|
UnbindToggle(otherToggle, HandleOtherChanged);
|
|
UnbindToggle(equipSystemToggle, HandleEquipSystemChanged);
|
|
UnbindDropdown(bag_filterDropdown, HandleFilterDropdownChanged);
|
|
UnbindDropdown(bag_sortDropdown, HandleSortDropdownChanged);
|
|
UnbindLedgerEvents();
|
|
HideCurrentPreview();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
btmandtopController.RefreshOverlayVisibilityState();
|
|
}
|
|
|
|
private void InitializeToggleGroup()
|
|
{
|
|
if (bagToggleGroup == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
bagToggleGroup.allowSwitchOff = false;
|
|
AssignToggleGroup(allToggle);
|
|
AssignToggleGroup(cultivateToggle);
|
|
AssignToggleGroup(preciousToggle);
|
|
AssignToggleGroup(otherToggle);
|
|
}
|
|
|
|
private void AssignToggleGroup(Toggle toggle)
|
|
{
|
|
if (toggle == null || bagToggleGroup == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
toggle.group = bagToggleGroup;
|
|
}
|
|
|
|
private void BindToggles()
|
|
{
|
|
RebindToggle(allToggle, HandleAllChanged);
|
|
RebindToggle(cultivateToggle, HandleCultivateChanged);
|
|
RebindToggle(preciousToggle, HandlePreciousChanged);
|
|
RebindToggle(otherToggle, HandleOtherChanged);
|
|
RebindToggle(equipSystemToggle, HandleEquipSystemChanged);
|
|
}
|
|
|
|
private void InitializeFilterDropdowns()
|
|
{
|
|
InitializeFilterDropdown(bag_filterDropdown, filterOptions, new[]
|
|
{
|
|
"全部",
|
|
"培养",
|
|
"珍贵",
|
|
"其他"
|
|
});
|
|
|
|
InitializeFilterDropdown(bag_sortDropdown, sortOptions, new[]
|
|
{
|
|
"默认",
|
|
"名称",
|
|
"稀有度",
|
|
"数量"
|
|
});
|
|
}
|
|
|
|
private void InitializeFilterDropdown(Dropdown dropdown, List<Dropdown.OptionData> cache, string[] labels)
|
|
{
|
|
if (dropdown == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
bool wasActive = dropdown.gameObject.activeInHierarchy;
|
|
cache.Clear();
|
|
for (int i = 0; i < labels.Length; i++)
|
|
{
|
|
cache.Add(new Dropdown.OptionData(labels[i]));
|
|
}
|
|
|
|
dropdown.ClearOptions();
|
|
dropdown.AddOptions(cache);
|
|
if (dropdown.value < 0 || dropdown.value >= labels.Length)
|
|
{
|
|
dropdown.value = 0;
|
|
}
|
|
dropdown.RefreshShownValue();
|
|
dropdown.gameObject.SetActive(wasActive);
|
|
}
|
|
|
|
private void BindFilterDropdowns()
|
|
{
|
|
RebindDropdown(bag_filterDropdown, HandleFilterDropdownChanged);
|
|
RebindDropdown(bag_sortDropdown, HandleSortDropdownChanged);
|
|
}
|
|
|
|
private void RebindDropdown(Dropdown dropdown, UnityAction<int> action)
|
|
{
|
|
if (dropdown == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
dropdown.onValueChanged.RemoveListener(action);
|
|
dropdown.onValueChanged.AddListener(action);
|
|
}
|
|
|
|
private void UnbindDropdown(Dropdown dropdown, UnityAction<int> action)
|
|
{
|
|
if (dropdown == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
dropdown.onValueChanged.RemoveListener(action);
|
|
}
|
|
|
|
private void HandleFilterDropdownChanged(int value)
|
|
{
|
|
currentFilterMode = (BagFilterMode)Mathf.Clamp(value, 0, 3);
|
|
currentCategory = (BagCategory)currentFilterMode;
|
|
Rebuild();
|
|
}
|
|
|
|
private void HandleSortDropdownChanged(int value)
|
|
{
|
|
currentSortMode = (BagSortMode)Mathf.Clamp(value, 0, 3);
|
|
Rebuild();
|
|
}
|
|
|
|
private void RebindToggle(Toggle toggle, UnityAction<bool> action)
|
|
{
|
|
if (toggle == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
toggle.onValueChanged.RemoveListener(action);
|
|
toggle.onValueChanged.AddListener(action);
|
|
}
|
|
|
|
private void UnbindToggle(Toggle toggle, UnityAction<bool> action)
|
|
{
|
|
if (toggle == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
toggle.onValueChanged.RemoveListener(action);
|
|
}
|
|
|
|
private void BindLedgerEvents()
|
|
{
|
|
ExpBottleLedger.EnsureInstance().OnBottleCountChanged -= HandleInventoryChanged;
|
|
ExpBottleLedger.EnsureInstance().OnBottleCountChanged += HandleInventoryChanged;
|
|
ExpBottleLedger.EnsureInstance().OnLedgerReloaded -= HandleInventoryReloaded;
|
|
ExpBottleLedger.EnsureInstance().OnLedgerReloaded += HandleInventoryReloaded;
|
|
|
|
DushMaterialLedger.EnsureInstance().OnMaterialCountChanged -= HandleGrowthMaterialChanged;
|
|
DushMaterialLedger.EnsureInstance().OnMaterialCountChanged += HandleGrowthMaterialChanged;
|
|
|
|
EquipmentConsumableLedger.EnsureInstance().OnCountChanged -= HandleEquipmentConsumableChanged;
|
|
EquipmentConsumableLedger.EnsureInstance().OnCountChanged += HandleEquipmentConsumableChanged;
|
|
}
|
|
|
|
private void UnbindLedgerEvents()
|
|
{
|
|
ExpBottleLedger.EnsureInstance().OnBottleCountChanged -= HandleInventoryChanged;
|
|
ExpBottleLedger.EnsureInstance().OnLedgerReloaded -= HandleInventoryReloaded;
|
|
DushMaterialLedger.EnsureInstance().OnMaterialCountChanged -= HandleGrowthMaterialChanged;
|
|
EquipmentConsumableLedger.EnsureInstance().OnCountChanged -= HandleEquipmentConsumableChanged;
|
|
}
|
|
|
|
private void SelectDefaultCategory()
|
|
{
|
|
if (allToggle != null)
|
|
{
|
|
allToggle.isOn = true;
|
|
ApplyCategory(BagCategory.All);
|
|
return;
|
|
}
|
|
|
|
ApplyCategory(BagCategory.All);
|
|
}
|
|
|
|
private void HandleAllChanged(bool isOn)
|
|
{
|
|
if (isOn)
|
|
{
|
|
ApplyCategory(BagCategory.All);
|
|
}
|
|
}
|
|
|
|
private void HandleCultivateChanged(bool isOn)
|
|
{
|
|
if (isOn)
|
|
{
|
|
ApplyCategory(BagCategory.Cultivation);
|
|
}
|
|
}
|
|
|
|
private void HandlePreciousChanged(bool isOn)
|
|
{
|
|
if (isOn)
|
|
{
|
|
ApplyCategory(BagCategory.Precious);
|
|
}
|
|
}
|
|
|
|
private void HandleOtherChanged(bool isOn)
|
|
{
|
|
if (isOn)
|
|
{
|
|
ApplyCategory(BagCategory.Other);
|
|
}
|
|
}
|
|
|
|
private void HandleEquipSystemChanged(bool isOn)
|
|
{
|
|
if (isOn)
|
|
{
|
|
ShowMemorySystemComingSoon();
|
|
}
|
|
|
|
ForceBagViewMode();
|
|
}
|
|
|
|
private void ApplyCategory(BagCategory category)
|
|
{
|
|
ForceBagViewMode();
|
|
currentCategory = category;
|
|
currentFilterMode = (BagFilterMode)category;
|
|
if (bag_filterDropdown != null)
|
|
{
|
|
bag_filterDropdown.SetValueWithoutNotify((int)currentFilterMode);
|
|
bag_filterDropdown.RefreshShownValue();
|
|
}
|
|
SetToggleInteractable(allToggle, category != BagCategory.All);
|
|
SetToggleInteractable(cultivateToggle, category != BagCategory.Cultivation);
|
|
SetToggleInteractable(preciousToggle, category != BagCategory.Precious);
|
|
SetToggleInteractable(otherToggle, category != BagCategory.Other);
|
|
Rebuild();
|
|
}
|
|
|
|
private void SetToggleInteractable(Toggle toggle, bool interactable)
|
|
{
|
|
if (toggle != null)
|
|
{
|
|
toggle.interactable = interactable;
|
|
}
|
|
}
|
|
|
|
private void SetObjectActive(GameObject target, bool active)
|
|
{
|
|
if (target != null)
|
|
{
|
|
target.SetActive(active);
|
|
}
|
|
}
|
|
|
|
private void InitializeViewMode()
|
|
{
|
|
if (equipSystemToggle != null)
|
|
{
|
|
equipSystemToggle.onValueChanged.RemoveListener(HandleEquipSystemChanged);
|
|
equipSystemToggle.onValueChanged.AddListener(HandleEquipSystemChanged);
|
|
}
|
|
|
|
ForceBagViewMode();
|
|
}
|
|
|
|
private void ForceBagViewMode()
|
|
{
|
|
if (equipSystemToggle != null)
|
|
{
|
|
equipSystemToggle.SetIsOnWithoutNotify(false);
|
|
}
|
|
|
|
SetObjectActive(bagObj, true);
|
|
SetObjectActive(equipObj, false);
|
|
}
|
|
|
|
private static void ShowMemorySystemComingSoon()
|
|
{
|
|
gNotice.error.display(MemorySystemComingSoonMessage);
|
|
}
|
|
|
|
private void HandleInventoryChanged(ExpBottleKind _, int __)
|
|
{
|
|
Rebuild();
|
|
}
|
|
|
|
private void HandleInventoryReloaded()
|
|
{
|
|
Rebuild();
|
|
}
|
|
|
|
private void HandleGrowthMaterialChanged(DushMaterialKind _, int __)
|
|
{
|
|
Rebuild();
|
|
}
|
|
|
|
private void HandleEquipmentConsumableChanged(EquipmentConsumableKind _, int __)
|
|
{
|
|
Rebuild();
|
|
}
|
|
|
|
public void Rebuild()
|
|
{
|
|
BuildEntries();
|
|
|
|
if (rebuildRoutine != null)
|
|
{
|
|
StopCoroutine(rebuildRoutine);
|
|
rebuildRoutine = null;
|
|
}
|
|
|
|
ClearSpawnedItems();
|
|
|
|
if (!isActiveAndEnabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ClearRightPanel();
|
|
rebuildRoutine = StartCoroutine(RebuildAsync());
|
|
}
|
|
|
|
public void SelectItemForDetail(uBagItemPrefab source)
|
|
{
|
|
if (source == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!viewEntries.TryGetValue(source, out BagEntry entry) || entry == null)
|
|
{
|
|
ClearRightPanel();
|
|
return;
|
|
}
|
|
|
|
ApplyRightPanel(entry);
|
|
}
|
|
|
|
public void ShowPreviewFor(uBagItemPrefab source)
|
|
{
|
|
if (source == null || itemIntroductionPrefab == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!viewEntries.TryGetValue(source, out BagEntry entry) || entry == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
HideCurrentPreview();
|
|
|
|
Transform previewParent = ResolveIntroductionParent(source);
|
|
if (previewParent == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
spawnedIntroduction = Instantiate(itemIntroductionPrefab, previewParent);
|
|
spawnedIntroduction.name = $"uBagPreview_{entry.stableId}";
|
|
spawnedIntroduction.SetActive(true);
|
|
spawnedIntroduction.transform.SetAsLastSibling();
|
|
activePreviewSource = source;
|
|
|
|
var previewView = spawnedIntroduction.GetComponent<bagItemPreviewPrefab>();
|
|
if (previewView != null)
|
|
{
|
|
Sprite icon = entry.icon != null ? entry.icon : fallbackItemIcon;
|
|
Color color = rarityColorConfig != null
|
|
? rarityColorConfig.GetColor(entry.rarity, fallbackColor)
|
|
: fallbackColor;
|
|
Sprite backgroundSprite = rarityColorConfig != null
|
|
? rarityColorConfig.GetBackgroundSprite(entry.rarity, fallbackBackgroundSprite)
|
|
: fallbackBackgroundSprite;
|
|
previewView.Bind(color, backgroundSprite, icon, entry.displayName, entry.usage, entry.description, entry.amountText);
|
|
}
|
|
|
|
PositionIntroduction(source, spawnedIntroduction);
|
|
UI_OrderedEntryAnimator.PlayFadeOnly(spawnedIntroduction, 0, 0.16f, 0f, true);
|
|
}
|
|
|
|
public void HidePreviewFor(uBagItemPrefab source)
|
|
{
|
|
if (source != null && source != activePreviewSource)
|
|
{
|
|
return;
|
|
}
|
|
|
|
HideCurrentPreview();
|
|
}
|
|
|
|
private void BuildEntries()
|
|
{
|
|
allEntries.Clear();
|
|
List<storeItemSO> storeItems = new List<storeItemSO>(LoadStoreItems());
|
|
AddExpBottleEntries(storeItems);
|
|
AddGrowthMaterialEntries(storeItems);
|
|
AddEquipmentConsumableEntries(storeItems);
|
|
AddNotebookPreciousEntries();
|
|
AddOwnedStorePreciousEntries(storeItems);
|
|
allEntries.Sort(CompareEntries);
|
|
ApplySortMode(allEntries);
|
|
}
|
|
|
|
private void AddExpBottleEntries(List<storeItemSO> storeItems)
|
|
{
|
|
var ledger = ExpBottleLedger.EnsureInstance();
|
|
var definitions = LoadExpBottleDefinitions();
|
|
|
|
foreach (var descriptor in ExpBottleCatalog.All)
|
|
{
|
|
int count = ledger.GetCount(descriptor.Kind);
|
|
if (count <= 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
expBottlesSO definition = FindExpBottleDefinition(definitions, descriptor.Kind);
|
|
storeItemSO storeItem = FindStoreItemForExpBottle(storeItems, descriptor.Kind);
|
|
expBottlesSO sourceDefinition = storeItem != null && storeItem.associatedExpBottle != null
|
|
? storeItem.associatedExpBottle
|
|
: definition;
|
|
allEntries.Add(new BagEntry
|
|
{
|
|
stableId = descriptor.Key,
|
|
displayName = storeItem != null && !string.IsNullOrEmpty(storeItem.itemName)
|
|
? storeItem.itemName
|
|
: definition != null && !string.IsNullOrEmpty(definition.expBottleName) ? definition.expBottleName : descriptor.DisplayName,
|
|
countText = count.ToString(),
|
|
amountText = count.ToString(),
|
|
usage = ItemUsageTagUtility.ResolveDisplayName(sourceDefinition),
|
|
description = BuildPreferredDescription(
|
|
storeItem != null ? storeItem.itemDetailedDescription : null,
|
|
sourceDefinition != null ? sourceDefinition.expBottleDescription : null,
|
|
storeItem != null ? storeItem.itemDescription : null),
|
|
icon = ResolvePreferredSprite(
|
|
storeItem != null ? storeItem.itemIcon : null,
|
|
sourceDefinition != null ? sourceDefinition.expBottleSprite : null,
|
|
fallbackItemIcon),
|
|
category = BagCategory.Cultivation,
|
|
sortPriority = 10,
|
|
rarity = storeItem != null ? storeItem.itemRarity : sourceDefinition != null ? sourceDefinition.itemRarity : ItemRarity.Common
|
|
});
|
|
}
|
|
}
|
|
|
|
private void AddGrowthMaterialEntries(List<storeItemSO> storeItems)
|
|
{
|
|
var ledger = DushMaterialLedger.EnsureInstance();
|
|
var definitions = LoadGrowthMaterialDefinitions();
|
|
|
|
foreach (var descriptor in DushMaterialCatalog.All)
|
|
{
|
|
int count = ledger.GetCount(descriptor.Kind);
|
|
if (count <= 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
growthMaterialSO definition = FindGrowthMaterialDefinition(definitions, descriptor.Kind);
|
|
storeItemSO storeItem = FindStoreItemForGrowthMaterial(storeItems, descriptor.Kind);
|
|
growthMaterialSO sourceDefinition = storeItem != null && storeItem.associatedGrowthMaterial != null
|
|
? storeItem.associatedGrowthMaterial
|
|
: definition;
|
|
allEntries.Add(new BagEntry
|
|
{
|
|
stableId = descriptor.Key,
|
|
displayName = storeItem != null && !string.IsNullOrEmpty(storeItem.itemName)
|
|
? storeItem.itemName
|
|
: definition != null && !string.IsNullOrEmpty(definition.growthMaterialName) ? definition.growthMaterialName : descriptor.DisplayName,
|
|
countText = count.ToString(),
|
|
amountText = count.ToString(),
|
|
usage = ItemUsageTagUtility.ResolveDisplayName(sourceDefinition),
|
|
description = BuildPreferredDescription(
|
|
storeItem != null ? storeItem.itemDetailedDescription : null,
|
|
sourceDefinition != null ? sourceDefinition.growthMaterialDescription : null,
|
|
storeItem != null ? storeItem.itemDescription : null),
|
|
icon = ResolvePreferredSprite(
|
|
storeItem != null ? storeItem.itemIcon : null,
|
|
sourceDefinition != null ? sourceDefinition.growthMaterialSprite : null,
|
|
fallbackItemIcon),
|
|
category = BagCategory.Cultivation,
|
|
sortPriority = 20,
|
|
rarity = storeItem != null ? storeItem.itemRarity : sourceDefinition != null ? sourceDefinition.itemRarity : ItemRarity.Uncommon
|
|
});
|
|
}
|
|
}
|
|
|
|
private void AddEquipmentConsumableEntries(List<storeItemSO> storeItems)
|
|
{
|
|
var ledger = EquipmentConsumableLedger.EnsureInstance();
|
|
var definitions = LoadEquipmentConsumableDefinitions();
|
|
|
|
foreach (var descriptor in EquipmentConsumableCatalog.All)
|
|
{
|
|
int count = ledger.GetCount(descriptor.Kind);
|
|
if (count <= 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
equipmentConsumableSO definition = FindEquipmentConsumableDefinition(definitions, descriptor.Kind);
|
|
storeItemSO storeItem = FindStoreItemForEquipmentConsumable(storeItems, descriptor.Kind);
|
|
equipmentConsumableSO sourceDefinition = storeItem != null && storeItem.associatedEquipmentConsumable != null
|
|
? storeItem.associatedEquipmentConsumable
|
|
: definition;
|
|
allEntries.Add(new BagEntry
|
|
{
|
|
stableId = descriptor.Key,
|
|
displayName = storeItem != null && !string.IsNullOrEmpty(storeItem.itemName)
|
|
? storeItem.itemName
|
|
: definition != null && !string.IsNullOrEmpty(definition.consumableName) ? definition.consumableName : descriptor.DisplayName,
|
|
countText = count.ToString(),
|
|
amountText = count.ToString(),
|
|
usage = ItemUsageTagUtility.ResolveDisplayName(sourceDefinition),
|
|
description = BuildPreferredDescription(
|
|
storeItem != null ? storeItem.itemDetailedDescription : null,
|
|
sourceDefinition != null ? sourceDefinition.consumableDescription : null,
|
|
storeItem != null ? storeItem.itemDescription : null),
|
|
icon = ResolvePreferredSprite(
|
|
storeItem != null ? storeItem.itemIcon : null,
|
|
sourceDefinition != null ? sourceDefinition.consumableSprite : null,
|
|
fallbackItemIcon),
|
|
category = BagCategory.Cultivation,
|
|
sortPriority = 30,
|
|
rarity = storeItem != null ? storeItem.itemRarity : sourceDefinition != null ? sourceDefinition.itemRarity : ItemRarity.Uncommon
|
|
});
|
|
}
|
|
}
|
|
|
|
private void AddNotebookPreciousEntries()
|
|
{
|
|
var seenIds = new HashSet<string>();
|
|
foreach (var story in LoadNotebookDefinitions())
|
|
{
|
|
if (story == null || !story.isUnlocked)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!story.showInBag)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
string stableId = $"notebook_{story.class_id}";
|
|
if (!seenIds.Add(stableId))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
allEntries.Add(new BagEntry
|
|
{
|
|
stableId = stableId,
|
|
displayName = story.class_name,
|
|
countText = "1",
|
|
amountText = "1",
|
|
usage = ItemUsageTagUtility.ResolveDisplayName(story),
|
|
description = story.class_description,
|
|
icon = ResolvePreferredSprite(story.class_image, fallbackItemIcon),
|
|
category = BagCategory.Precious,
|
|
sortPriority = 100,
|
|
rarity = story.itemRarity
|
|
});
|
|
}
|
|
}
|
|
|
|
private void AddOwnedStorePreciousEntries(List<storeItemSO> storeItems)
|
|
{
|
|
var ownership = StoreOwnershipLedger.EnsureInstance();
|
|
foreach (var item in storeItems)
|
|
{
|
|
if (item == null || !ownership.IsOwned(item))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (item.itemType != storeItemSO.ItemType.character && item.itemType != storeItemSO.ItemType.song)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
PreciousKind kind = item.itemType == storeItemSO.ItemType.character ? PreciousKind.Character : PreciousKind.Level;
|
|
allEntries.Add(new BagEntry
|
|
{
|
|
stableId = $"store_{item.itemID}",
|
|
displayName = item.itemName,
|
|
countText = "1",
|
|
amountText = "1",
|
|
usage = ItemUsageTagUtility.ResolveDisplayName(item),
|
|
description = BuildPreferredDescription(item.itemDetailedDescription, item.itemDescription),
|
|
icon = ResolvePreferredSprite(item.itemIcon, fallbackItemIcon),
|
|
category = BagCategory.Precious,
|
|
sortPriority = kind == PreciousKind.Character ? 110 : 120,
|
|
rarity = item.itemRarity
|
|
});
|
|
}
|
|
}
|
|
|
|
private IEnumerator RebuildAsync()
|
|
{
|
|
List<BagEntry> visibleEntries = FilterEntries();
|
|
UpdateEmptyState(visibleEntries.Count == 0);
|
|
|
|
uBagItemPrefab firstView = null;
|
|
int spawnedInBatch = 0;
|
|
for (int i = 0; i < visibleEntries.Count; i++)
|
|
{
|
|
uBagItemPrefab spawnedView = SpawnEntry(visibleEntries[i]);
|
|
if (firstView == null && spawnedView != null)
|
|
{
|
|
firstView = spawnedView;
|
|
}
|
|
|
|
spawnedInBatch++;
|
|
if (spawnedInBatch >= spawnBatchSize)
|
|
{
|
|
spawnedInBatch = 0;
|
|
yield return null;
|
|
}
|
|
}
|
|
|
|
if (firstView != null)
|
|
{
|
|
SelectItemForDetail(firstView);
|
|
}
|
|
else
|
|
{
|
|
ClearRightPanel();
|
|
}
|
|
|
|
rebuildRoutine = null;
|
|
}
|
|
|
|
private List<BagEntry> FilterEntries()
|
|
{
|
|
var result = new List<BagEntry>();
|
|
for (int i = 0; i < allEntries.Count; i++)
|
|
{
|
|
BagEntry entry = allEntries[i];
|
|
if (entry == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (currentCategory != BagCategory.All && entry.category != currentCategory)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
result.Add(entry);
|
|
}
|
|
|
|
ApplySortMode(result);
|
|
return result;
|
|
}
|
|
|
|
private void ApplySortMode(List<BagEntry> entries)
|
|
{
|
|
if (entries == null || entries.Count <= 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch (currentSortMode)
|
|
{
|
|
case BagSortMode.Name:
|
|
entries.Sort((left, right) => string.CompareOrdinal(
|
|
left != null ? left.displayName : string.Empty,
|
|
right != null ? right.displayName : string.Empty));
|
|
break;
|
|
case BagSortMode.Rarity:
|
|
entries.Sort((left, right) =>
|
|
{
|
|
int rarityResult = (left != null ? left.rarity : ItemRarity.None).CompareTo(right != null ? right.rarity : ItemRarity.None);
|
|
if (rarityResult != 0) return rarityResult;
|
|
return CompareEntries(left, right);
|
|
});
|
|
break;
|
|
case BagSortMode.Count:
|
|
entries.Sort((left, right) =>
|
|
{
|
|
int leftCount = ParseSafeInt(left != null ? left.amountText : null);
|
|
int rightCount = ParseSafeInt(right != null ? right.amountText : null);
|
|
int countResult = rightCount.CompareTo(leftCount);
|
|
if (countResult != 0) return countResult;
|
|
return CompareEntries(left, right);
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static int ParseSafeInt(string value)
|
|
{
|
|
return int.TryParse(value, out int parsed) ? parsed : 0;
|
|
}
|
|
|
|
private uBagItemPrefab SpawnEntry(BagEntry entry)
|
|
{
|
|
if (entry == null || itemPrefab == null || itemParent == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
GameObject instance = Instantiate(itemPrefab, itemParent);
|
|
instance.name = $"uBagItem_{entry.stableId}";
|
|
spawnedItems.Add(instance);
|
|
UI_OrderedEntryAnimator.PlaySingle(instance, spawnedItems.Count - 1, 0.18f, 0.01f, -16f, 0.965f, true);
|
|
|
|
uBagItemPrefab prefabView = instance.GetComponent<uBagItemPrefab>();
|
|
if (prefabView != null)
|
|
{
|
|
Sprite icon = entry.icon != null ? entry.icon : fallbackItemIcon;
|
|
Color color = rarityColorConfig != null
|
|
? rarityColorConfig.GetColor(entry.rarity, fallbackColor)
|
|
: fallbackColor;
|
|
Sprite backgroundSprite = rarityColorConfig != null
|
|
? rarityColorConfig.GetBackgroundSprite(entry.rarity, fallbackBackgroundSprite)
|
|
: fallbackBackgroundSprite;
|
|
prefabView.Bind(this, icon, entry.countText, color, backgroundSprite, introductionHoverDelay);
|
|
viewEntries[prefabView] = entry;
|
|
}
|
|
|
|
return prefabView;
|
|
}
|
|
|
|
private void ClearSpawnedItems()
|
|
{
|
|
HideCurrentPreview();
|
|
viewEntries.Clear();
|
|
|
|
for (int i = itemParent != null ? itemParent.childCount - 1 : -1; i >= 0; i--)
|
|
{
|
|
Transform child = itemParent.GetChild(i);
|
|
if (child != null)
|
|
{
|
|
Destroy(child.gameObject);
|
|
}
|
|
}
|
|
|
|
spawnedItems.Clear();
|
|
UpdateEmptyState(false);
|
|
}
|
|
|
|
private void UpdateEmptyState(bool visible)
|
|
{
|
|
if (emptyText != null)
|
|
{
|
|
emptyText.gameObject.SetActive(visible);
|
|
if (visible)
|
|
{
|
|
emptyText.text = "暂无物品";
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ApplyRightPanel(BagEntry entry)
|
|
{
|
|
if (entry == null)
|
|
{
|
|
ClearRightPanel();
|
|
return;
|
|
}
|
|
|
|
Sprite icon = entry.icon != null ? entry.icon : fallbackItemIcon;
|
|
Color color = rarityColorConfig != null
|
|
? rarityColorConfig.GetColor(entry.rarity, fallbackColor)
|
|
: fallbackColor;
|
|
Sprite backgroundSprite = rarityColorConfig != null
|
|
? rarityColorConfig.GetBackgroundSprite(entry.rarity, fallbackBackgroundSprite)
|
|
: fallbackBackgroundSprite;
|
|
|
|
if (btmImg != null)
|
|
{
|
|
btmImg.sprite = backgroundSprite;
|
|
btmImg.color = backgroundSprite != null ? Color.white : color;
|
|
}
|
|
|
|
if (bottom_rarityImg != null)
|
|
{
|
|
Sprite raritySprite = ResolveBottomRaritySprite(entry.rarity);
|
|
bottom_rarityImg.sprite = raritySprite;
|
|
bottom_rarityImg.enabled = raritySprite != null;
|
|
bottom_rarityImg.color = Color.white;
|
|
}
|
|
|
|
if (itemDprofile != null)
|
|
{
|
|
itemDprofile.sprite = icon;
|
|
itemDprofile.enabled = icon != null;
|
|
itemDprofile.color = Color.white;
|
|
}
|
|
|
|
if (itemAmount != null)
|
|
{
|
|
itemAmount.text = entry.amountText ?? string.Empty;
|
|
}
|
|
|
|
if (itemName != null)
|
|
{
|
|
itemName.supportRichText = false;
|
|
itemName.text = StripRichTextTags(entry.displayName);
|
|
itemName.color = useRarityColorForItemName ? color : Color.white;
|
|
}
|
|
|
|
if (itemUse != null)
|
|
{
|
|
itemUse.text = entry.usage ?? string.Empty;
|
|
}
|
|
|
|
if (itemUsageLegacy != null)
|
|
{
|
|
itemUsageLegacy.text = entry.usage ?? string.Empty;
|
|
}
|
|
|
|
if (itemDescription != null)
|
|
{
|
|
itemDescription.text = entry.description ?? string.Empty;
|
|
}
|
|
|
|
PlayRightPanelRefresh();
|
|
}
|
|
|
|
private void ClearRightPanel()
|
|
{
|
|
if (btmImg != null)
|
|
{
|
|
btmImg.sprite = fallbackBackgroundSprite;
|
|
btmImg.color = fallbackBackgroundSprite != null ? Color.white : fallbackColor;
|
|
}
|
|
|
|
if (bottom_rarityImg != null)
|
|
{
|
|
Sprite fallbackRaritySprite = GetBottomRarityFallbackSprite();
|
|
bottom_rarityImg.sprite = fallbackRaritySprite;
|
|
bottom_rarityImg.enabled = fallbackRaritySprite != null;
|
|
bottom_rarityImg.color = Color.white;
|
|
}
|
|
|
|
if (itemDprofile != null)
|
|
{
|
|
itemDprofile.sprite = fallbackItemIcon;
|
|
itemDprofile.enabled = fallbackItemIcon != null;
|
|
itemDprofile.color = Color.white;
|
|
}
|
|
|
|
if (itemAmount != null)
|
|
{
|
|
itemAmount.text = string.Empty;
|
|
}
|
|
|
|
if (itemName != null)
|
|
{
|
|
itemName.supportRichText = false;
|
|
itemName.text = string.Empty;
|
|
itemName.color = Color.white;
|
|
}
|
|
|
|
if (itemUse != null)
|
|
{
|
|
itemUse.text = string.Empty;
|
|
}
|
|
|
|
if (itemUsageLegacy != null)
|
|
{
|
|
itemUsageLegacy.text = string.Empty;
|
|
}
|
|
|
|
if (itemDescription != null)
|
|
{
|
|
itemDescription.text = string.Empty;
|
|
}
|
|
|
|
PlayRightPanelRefresh();
|
|
}
|
|
|
|
private void PlayRightPanelRefresh()
|
|
{
|
|
GameObject target = null;
|
|
if (btmImg != null) target = btmImg.gameObject;
|
|
if (target == null && itemDprofile != null) target = itemDprofile.gameObject;
|
|
if (target == null && itemName != null) target = itemName.gameObject;
|
|
UI_OrderedEntryAnimator.PlayRefresh(target, 0.14f, -6f, 0.99f, true);
|
|
}
|
|
|
|
private static int CompareEntries(BagEntry left, BagEntry right)
|
|
{
|
|
if (ReferenceEquals(left, right))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (left == null)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (right == null)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int categoryResult = left.category.CompareTo(right.category);
|
|
if (categoryResult != 0)
|
|
{
|
|
return categoryResult;
|
|
}
|
|
|
|
int priorityResult = left.sortPriority.CompareTo(right.sortPriority);
|
|
if (priorityResult != 0)
|
|
{
|
|
return priorityResult;
|
|
}
|
|
|
|
return string.CompareOrdinal(left.displayName, right.displayName);
|
|
}
|
|
|
|
private static string StripRichTextTags(string value)
|
|
{
|
|
if (string.IsNullOrEmpty(value))
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
bool insideTag = false;
|
|
System.Text.StringBuilder builder = null;
|
|
for (int i = 0; i < value.Length; i++)
|
|
{
|
|
char current = value[i];
|
|
if (current == '<')
|
|
{
|
|
if (!insideTag)
|
|
{
|
|
builder ??= new System.Text.StringBuilder(value.Length);
|
|
}
|
|
|
|
insideTag = true;
|
|
continue;
|
|
}
|
|
|
|
if (current == '>')
|
|
{
|
|
insideTag = false;
|
|
continue;
|
|
}
|
|
|
|
if (!insideTag)
|
|
{
|
|
if (builder != null)
|
|
{
|
|
builder.Append(current);
|
|
}
|
|
}
|
|
}
|
|
|
|
return builder != null ? builder.ToString() : value;
|
|
}
|
|
|
|
private Sprite ResolveBottomRaritySprite(ItemRarity rarity)
|
|
{
|
|
if (bottom_rarityImg_sprites != null)
|
|
{
|
|
if (bottom_rarityImg_sprites.Length >= System.Enum.GetValues(typeof(ItemRarity)).Length)
|
|
{
|
|
int enumIndex = (int)rarity;
|
|
if (enumIndex >= 0 && enumIndex < bottom_rarityImg_sprites.Length)
|
|
{
|
|
Sprite directSprite = bottom_rarityImg_sprites[enumIndex];
|
|
if (directSprite != null)
|
|
{
|
|
return directSprite;
|
|
}
|
|
}
|
|
}
|
|
else if (rarity != ItemRarity.None)
|
|
{
|
|
int compactIndex = (int)rarity - 1;
|
|
if (compactIndex >= 0 && compactIndex < bottom_rarityImg_sprites.Length)
|
|
{
|
|
Sprite compactSprite = bottom_rarityImg_sprites[compactIndex];
|
|
if (compactSprite != null)
|
|
{
|
|
return compactSprite;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return GetBottomRarityFallbackSprite();
|
|
}
|
|
|
|
private Sprite GetBottomRarityFallbackSprite()
|
|
{
|
|
if (rarityColorConfig != null)
|
|
{
|
|
Sprite noneSprite = rarityColorConfig.GetBackgroundSprite(ItemRarity.None, fallbackBackgroundSprite);
|
|
if (noneSprite != null)
|
|
{
|
|
return noneSprite;
|
|
}
|
|
}
|
|
|
|
return fallbackBackgroundSprite;
|
|
}
|
|
|
|
private expBottlesSO[] LoadExpBottleDefinitions()
|
|
{
|
|
var result = new List<expBottlesSO>();
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying && !string.IsNullOrEmpty(expBottleEditorPath))
|
|
{
|
|
string[] guids = AssetDatabase.FindAssets("t:expBottlesSO", new[] { expBottleEditorPath });
|
|
for (int i = 0; i < guids.Length; i++)
|
|
{
|
|
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
|
|
expBottlesSO asset = AssetDatabase.LoadAssetAtPath<expBottlesSO>(path);
|
|
if (asset != null)
|
|
{
|
|
result.Add(asset);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
result.AddRange(Resources.LoadAll<expBottlesSO>(string.Empty));
|
|
return result.ToArray();
|
|
}
|
|
|
|
private growthMaterialSO[] LoadGrowthMaterialDefinitions()
|
|
{
|
|
var result = new List<growthMaterialSO>();
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying && !string.IsNullOrEmpty(growthMaterialEditorPath))
|
|
{
|
|
string[] guids = AssetDatabase.FindAssets("t:growthMaterialSO", new[] { growthMaterialEditorPath });
|
|
for (int i = 0; i < guids.Length; i++)
|
|
{
|
|
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
|
|
growthMaterialSO asset = AssetDatabase.LoadAssetAtPath<growthMaterialSO>(path);
|
|
if (asset != null)
|
|
{
|
|
result.Add(asset);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
result.AddRange(Resources.LoadAll<growthMaterialSO>(string.Empty));
|
|
return result.ToArray();
|
|
}
|
|
|
|
private equipmentConsumableSO[] LoadEquipmentConsumableDefinitions()
|
|
{
|
|
var result = new List<equipmentConsumableSO>();
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying && !string.IsNullOrEmpty(equipmentConsumableEditorPath))
|
|
{
|
|
string[] guids = AssetDatabase.FindAssets("t:equipmentConsumableSO", new[] { equipmentConsumableEditorPath });
|
|
for (int i = 0; i < guids.Length; i++)
|
|
{
|
|
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
|
|
equipmentConsumableSO asset = AssetDatabase.LoadAssetAtPath<equipmentConsumableSO>(path);
|
|
if (asset != null)
|
|
{
|
|
result.Add(asset);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
result.AddRange(Resources.LoadAll<equipmentConsumableSO>(string.Empty));
|
|
return result.ToArray();
|
|
}
|
|
|
|
private IEnumerable<notebook_faterType> LoadNotebookDefinitions()
|
|
{
|
|
var result = new List<notebook_faterType>();
|
|
var seen = new HashSet<int>();
|
|
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying && !string.IsNullOrEmpty(notebookEditorPath))
|
|
{
|
|
string[] guids = AssetDatabase.FindAssets("t:notebook_faterType", new[] { notebookEditorPath });
|
|
for (int i = 0; i < guids.Length; i++)
|
|
{
|
|
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
|
|
notebook_faterType asset = AssetDatabase.LoadAssetAtPath<notebook_faterType>(path);
|
|
if (asset != null && seen.Add(asset.class_id))
|
|
{
|
|
result.Add(asset);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (!string.IsNullOrEmpty(notebookRuntimePath))
|
|
{
|
|
notebook_faterType[] resources = Resources.LoadAll<notebook_faterType>(notebookRuntimePath);
|
|
for (int i = 0; i < resources.Length; i++)
|
|
{
|
|
notebook_faterType asset = resources[i];
|
|
if (asset != null && seen.Add(asset.class_id))
|
|
{
|
|
result.Add(asset);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private IEnumerable<storeItemSO> LoadStoreItems()
|
|
{
|
|
var result = new List<storeItemSO>();
|
|
var seen = new HashSet<int>();
|
|
|
|
#if UNITY_EDITOR
|
|
if (!Application.isPlaying && !string.IsNullOrEmpty(storeItemEditorPath))
|
|
{
|
|
string[] guids = AssetDatabase.FindAssets("t:storeItemSO", new[] { storeItemEditorPath });
|
|
for (int i = 0; i < guids.Length; i++)
|
|
{
|
|
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
|
|
storeItemSO asset = AssetDatabase.LoadAssetAtPath<storeItemSO>(path);
|
|
if (asset != null && seen.Add(asset.itemID))
|
|
{
|
|
result.Add(asset);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (!string.IsNullOrEmpty(storeItemRuntimePath))
|
|
{
|
|
storeItemSO[] resources = Resources.LoadAll<storeItemSO>(storeItemRuntimePath);
|
|
for (int i = 0; i < resources.Length; i++)
|
|
{
|
|
storeItemSO asset = resources[i];
|
|
if (asset != null && seen.Add(asset.itemID))
|
|
{
|
|
result.Add(asset);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static expBottlesSO FindExpBottleDefinition(expBottlesSO[] definitions, ExpBottleKind kind)
|
|
{
|
|
if (definitions == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
for (int i = 0; i < definitions.Length; i++)
|
|
{
|
|
if (definitions[i] != null && definitions[i].bottleKind == kind)
|
|
{
|
|
return definitions[i];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static growthMaterialSO FindGrowthMaterialDefinition(growthMaterialSO[] definitions, DushMaterialKind kind)
|
|
{
|
|
if (definitions == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
for (int i = 0; i < definitions.Length; i++)
|
|
{
|
|
if (definitions[i] != null && definitions[i].materialKind == kind)
|
|
{
|
|
return definitions[i];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static equipmentConsumableSO FindEquipmentConsumableDefinition(equipmentConsumableSO[] definitions, EquipmentConsumableKind kind)
|
|
{
|
|
if (definitions == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
for (int i = 0; i < definitions.Length; i++)
|
|
{
|
|
if (definitions[i] != null && definitions[i].consumableKind == kind)
|
|
{
|
|
return definitions[i];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static storeItemSO FindStoreItemForExpBottle(List<storeItemSO> storeItems, ExpBottleKind kind)
|
|
{
|
|
if (storeItems == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
for (int i = 0; i < storeItems.Count; i++)
|
|
{
|
|
storeItemSO item = storeItems[i];
|
|
if (item != null
|
|
&& item.itemType == storeItemSO.ItemType.consumable
|
|
&& item.associatedExpBottle != null
|
|
&& item.associatedExpBottle.bottleKind == kind)
|
|
{
|
|
return item;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static storeItemSO FindStoreItemForGrowthMaterial(List<storeItemSO> storeItems, DushMaterialKind kind)
|
|
{
|
|
if (storeItems == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
for (int i = 0; i < storeItems.Count; i++)
|
|
{
|
|
storeItemSO item = storeItems[i];
|
|
if (item != null
|
|
&& item.itemType == storeItemSO.ItemType.consumable
|
|
&& item.associatedGrowthMaterial != null
|
|
&& item.associatedGrowthMaterial.materialKind == kind)
|
|
{
|
|
return item;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static storeItemSO FindStoreItemForEquipmentConsumable(List<storeItemSO> storeItems, EquipmentConsumableKind kind)
|
|
{
|
|
if (storeItems == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
for (int i = 0; i < storeItems.Count; i++)
|
|
{
|
|
storeItemSO item = storeItems[i];
|
|
if (item != null
|
|
&& item.itemType == storeItemSO.ItemType.consumable
|
|
&& item.associatedEquipmentConsumable != null
|
|
&& item.associatedEquipmentConsumable.consumableKind == kind)
|
|
{
|
|
return item;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static Sprite ResolvePreferredSprite(params Sprite[] sprites)
|
|
{
|
|
for (int i = 0; i < sprites.Length; i++)
|
|
{
|
|
if (sprites[i] != null)
|
|
{
|
|
return sprites[i];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static string BuildPreferredDescription(params string[] candidates)
|
|
{
|
|
for (int i = 0; i < candidates.Length; i++)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(candidates[i]))
|
|
{
|
|
return candidates[i];
|
|
}
|
|
}
|
|
|
|
return string.Empty;
|
|
}
|
|
|
|
private Transform ResolveIntroductionParent(uBagItemPrefab source)
|
|
{
|
|
if (source == null)
|
|
{
|
|
return itemParent;
|
|
}
|
|
|
|
Canvas canvas = source.GetComponentInParent<Canvas>();
|
|
if (canvas != null)
|
|
{
|
|
return canvas.transform;
|
|
}
|
|
|
|
return itemParent;
|
|
}
|
|
|
|
private void PositionIntroduction(uBagItemPrefab source, GameObject introduction)
|
|
{
|
|
if (source == null || introduction == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
RectTransform sourceRect = source.transform as RectTransform;
|
|
RectTransform introductionRect = introduction.transform as RectTransform;
|
|
Canvas canvas = introduction.GetComponentInParent<Canvas>();
|
|
RectTransform canvasRect = canvas != null ? canvas.transform as RectTransform : null;
|
|
if (sourceRect == null || introductionRect == null || canvasRect == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Canvas.ForceUpdateCanvases();
|
|
LayoutRebuilder.ForceRebuildLayoutImmediate(introductionRect);
|
|
|
|
Vector3[] corners = new Vector3[4];
|
|
sourceRect.GetWorldCorners(corners);
|
|
Vector3 sourceRightCenter = (corners[2] + corners[3]) * 0.5f;
|
|
Camera uiCamera = canvas != null ? canvas.worldCamera : null;
|
|
Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(uiCamera, sourceRightCenter);
|
|
|
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
|
canvasRect,
|
|
screenPoint,
|
|
uiCamera,
|
|
out Vector2 localPoint);
|
|
|
|
introductionRect.anchorMin = new Vector2(0.5f, 0.5f);
|
|
introductionRect.anchorMax = new Vector2(0.5f, 0.5f);
|
|
introductionRect.pivot = new Vector2(0f, 0.5f);
|
|
introductionRect.anchoredPosition = localPoint + new Vector2(introductionHorizontalOffset, 0f);
|
|
introductionRect.localScale = Vector3.one;
|
|
introductionRect.localRotation = Quaternion.identity;
|
|
}
|
|
|
|
private void HideCurrentPreview()
|
|
{
|
|
activePreviewSource = null;
|
|
if (spawnedIntroduction != null)
|
|
{
|
|
Destroy(spawnedIntroduction);
|
|
spawnedIntroduction = null;
|
|
}
|
|
}
|
|
}
|