using System; using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UI; using Bansonic; #if UNITY_EDITOR using UnityEditor; #endif public class equipBag : MonoBehaviour { private enum EquipFilterMode { All, HasSpecialSkill, HasIllusionSkill, HasAnySkill, HasNoSkill, HasDualSkill, Type0, Type1, Type2, Type3, Type4, Type5, Type6, Type7 } private enum EquipOrderMode { AcquireAsc, AcquireDesc, QualityAsc, QualityDesc } [Header("prefab")] public GameObject eqpmtItemPrefab; public Transform eqpmtItemParent; [Header("dropdown")] public Dropdown orderDropdown; public Dropdown filterDropdown; [Header("source paths")] public string runtimeEquipmentFolder = "so/uEquip"; public string editorEquipmentFolder = "Assets/Resources/so/uEquip"; [Header("async spawn")] public int spawnBatchSize = 12; private readonly List spawnedItems = new List(); private Coroutine rebuildCoroutine; private bool suppressDropdownCallbacks; private static readonly (EquipFilterMode mode, string label)[] FilterOptions = { (EquipFilterMode.All, "全部"), (EquipFilterMode.HasSpecialSkill, "含特效技能"), (EquipFilterMode.HasIllusionSkill, "含巡演技能"), (EquipFilterMode.HasAnySkill, "含技能"), (EquipFilterMode.HasNoSkill, "不含技能"), (EquipFilterMode.HasDualSkill, "含双技能"), (EquipFilterMode.Type0, equipmentSO.EquipmentSkillType.题海战术.ToString()), (EquipFilterMode.Type1, equipmentSO.EquipmentSkillType.诛锄异己.ToString()), (EquipFilterMode.Type2, equipmentSO.EquipmentSkillType.逸乐共谋.ToString()), (EquipFilterMode.Type3, equipmentSO.EquipmentSkillType.完美至上.ToString()), (EquipFilterMode.Type4, equipmentSO.EquipmentSkillType.涵养心境.ToString()), (EquipFilterMode.Type5, equipmentSO.EquipmentSkillType.众志成城.ToString()), (EquipFilterMode.Type6, equipmentSO.EquipmentSkillType.过激行为.ToString()), (EquipFilterMode.Type7, equipmentSO.EquipmentSkillType.二次形变.ToString()) }; private static readonly (EquipOrderMode mode, string label)[] OrderOptions = { (EquipOrderMode.AcquireAsc, "获取时间升序"), (EquipOrderMode.AcquireDesc, "获取时间降序"), (EquipOrderMode.QualityAsc, "品质升序"), (EquipOrderMode.QualityDesc, "品质降序") }; private void Awake() { InitializeDropdowns(); } private void Start() { Rebuild(); } private void OnEnable() { InitializeDropdowns(); Rebuild(); } private void OnDisable() { if (orderDropdown != null) { orderDropdown.onValueChanged.RemoveListener(HandleOrderChanged); } if (filterDropdown != null) { filterDropdown.onValueChanged.RemoveListener(HandleFilterChanged); } if (rebuildCoroutine != null) { StopCoroutine(rebuildCoroutine); rebuildCoroutine = null; } } public void Rebuild() { if (rebuildCoroutine != null) { StopCoroutine(rebuildCoroutine); rebuildCoroutine = null; } ClearSpawnedItems(); if (eqpmtItemPrefab == null || eqpmtItemParent == null) { return; } List equipments = LoadEquipments() .Where(equipment => equipment != null && !equipSmelt.IsEquipmentAssignedToSmeltPool(equipment) && !equipSmelt.ShouldHideConsumedEquipment(equipment)) .Where(MatchesCurrentFilter) .ToList(); SortEquipments(equipments); if (Application.isPlaying && isActiveAndEnabled && gameObject.activeInHierarchy) { rebuildCoroutine = StartCoroutine(RebuildAsync(equipments)); return; } SpawnAllImmediate(equipments); } private void InitializeDropdowns() { InitializeFilterDropdown(); InitializeOrderDropdown(); } private void InitializeFilterDropdown() { if (filterDropdown == null) { return; } suppressDropdownCallbacks = true; filterDropdown.onValueChanged.RemoveListener(HandleFilterChanged); filterDropdown.ClearOptions(); filterDropdown.AddOptions(FilterOptions.Select(option => new Dropdown.OptionData(option.label)).ToList()); filterDropdown.value = 0; filterDropdown.RefreshShownValue(); filterDropdown.onValueChanged.AddListener(HandleFilterChanged); suppressDropdownCallbacks = false; } private void InitializeOrderDropdown() { if (orderDropdown == null) { return; } suppressDropdownCallbacks = true; orderDropdown.onValueChanged.RemoveListener(HandleOrderChanged); orderDropdown.ClearOptions(); orderDropdown.AddOptions(OrderOptions.Select(option => new Dropdown.OptionData(option.label)).ToList()); orderDropdown.value = 0; orderDropdown.RefreshShownValue(); orderDropdown.onValueChanged.AddListener(HandleOrderChanged); suppressDropdownCallbacks = false; } private void HandleFilterChanged(int _) { if (!suppressDropdownCallbacks) { Rebuild(); } } private void HandleOrderChanged(int _) { if (!suppressDropdownCallbacks) { Rebuild(); } } private IEnumerator RebuildAsync(List equipments) { if (equipments == null || equipments.Count == 0) { rebuildCoroutine = null; yield break; } int batchSize = Mathf.Max(1, spawnBatchSize); for (int i = 0; i < equipments.Count; i++) { SpawnOne(equipments[i]); if ((i + 1) % batchSize == 0) { yield return null; } } rebuildCoroutine = null; } private void SpawnAllImmediate(List equipments) { if (equipments == null) { return; } for (int i = 0; i < equipments.Count; i++) { SpawnOne(equipments[i]); } } private void SpawnOne(equipmentSO equipment) { if (equipment == null || eqpmtItemPrefab == null || eqpmtItemParent == null) { return; } GameObject instance = Instantiate(eqpmtItemPrefab, eqpmtItemParent); string displayName = equipment.GetDisplayTierName(); instance.name = string.IsNullOrWhiteSpace(displayName) ? equipment.name : displayName; equipItemPrefab item = instance.GetComponent(); if (item != null) { item.Bind(equipment, HandleEquipmentClicked); } spawnedItems.Add(instance); } private equipmentSO[] LoadEquipments() { var results = new List(); var indexedByName = new Dictionary(StringComparer.Ordinal); #if UNITY_EDITOR if (!Application.isPlaying) { results.AddRange(LoadEditorEquipments()); } else #endif { results.AddRange(Resources.LoadAll(runtimeEquipmentFolder) .Where(equipment => equipment != null)); } for (int i = 0; i < results.Count; i++) { equipmentSO equipment = results[i]; if (equipment == null || string.IsNullOrWhiteSpace(equipment.name)) { continue; } indexedByName[equipment.name] = i; } IReadOnlyList runtimeGenerated = equipmentGenerator.GetRuntimeGeneratedEquipments(); if (runtimeGenerated != null) { for (int i = 0; i < runtimeGenerated.Count; i++) { equipmentSO equipment = runtimeGenerated[i]; if (equipment == null) { continue; } if (!string.IsNullOrWhiteSpace(equipment.name) && indexedByName.TryGetValue(equipment.name, out int existingIndex)) { results[existingIndex] = equipment; continue; } results.Add(equipment); if (!string.IsNullOrWhiteSpace(equipment.name)) { indexedByName[equipment.name] = results.Count - 1; } } } return results.Where(equipment => equipment != null).ToArray(); } #if UNITY_EDITOR private equipmentSO[] LoadEditorEquipments() { if (string.IsNullOrWhiteSpace(editorEquipmentFolder) || !AssetDatabase.IsValidFolder(editorEquipmentFolder)) { return Array.Empty(); } string[] guids = AssetDatabase.FindAssets("t:equipmentSO", new[] { editorEquipmentFolder }); var result = new List(guids.Length); for (int i = 0; i < guids.Length; i++) { string path = AssetDatabase.GUIDToAssetPath(guids[i]); equipmentSO equipment = AssetDatabase.LoadAssetAtPath(path); if (equipment != null) { result.Add(equipment); } } return result.ToArray(); } #endif private bool MatchesCurrentFilter(equipmentSO equipment) { if (equipment == null) { return false; } EquipFilterMode mode = GetSelectedFilterMode(); bool hasSpecialSkill = equipment.sa_skillID > 0; bool hasIllusionSkill = equipment.ia_skillID > 0; switch (mode) { case EquipFilterMode.All: return true; case EquipFilterMode.HasSpecialSkill: return hasSpecialSkill; case EquipFilterMode.HasIllusionSkill: return hasIllusionSkill; case EquipFilterMode.HasAnySkill: return hasSpecialSkill || hasIllusionSkill; case EquipFilterMode.HasNoSkill: return !hasSpecialSkill && !hasIllusionSkill; case EquipFilterMode.HasDualSkill: return hasSpecialSkill && hasIllusionSkill; case EquipFilterMode.Type0: return equipment.skillType == equipmentSO.EquipmentSkillType.题海战术; case EquipFilterMode.Type1: return equipment.skillType == equipmentSO.EquipmentSkillType.诛锄异己; case EquipFilterMode.Type2: return equipment.skillType == equipmentSO.EquipmentSkillType.逸乐共谋; case EquipFilterMode.Type3: return equipment.skillType == equipmentSO.EquipmentSkillType.完美至上; case EquipFilterMode.Type4: return equipment.skillType == equipmentSO.EquipmentSkillType.涵养心境; case EquipFilterMode.Type5: return equipment.skillType == equipmentSO.EquipmentSkillType.众志成城; case EquipFilterMode.Type6: return equipment.skillType == equipmentSO.EquipmentSkillType.过激行为; case EquipFilterMode.Type7: return equipment.skillType == equipmentSO.EquipmentSkillType.二次形变; default: return true; } } private void SortEquipments(List equipments) { if (equipments == null) { return; } EquipOrderMode mode = GetSelectedOrderMode(); equipments.Sort((left, right) => CompareEquipments(left, right, mode)); } private EquipFilterMode GetSelectedFilterMode() { int index = filterDropdown != null ? Mathf.Clamp(filterDropdown.value, 0, FilterOptions.Length - 1) : 0; return FilterOptions[index].mode; } private EquipOrderMode GetSelectedOrderMode() { int index = orderDropdown != null ? Mathf.Clamp(orderDropdown.value, 0, OrderOptions.Length - 1) : 0; return OrderOptions[index].mode; } private void HandleEquipmentClicked(equipmentSO equipment) { if (equipment == null) { return; } } private void ClearSpawnedItems() { if (eqpmtItemParent != null) { for (int i = eqpmtItemParent.childCount - 1; i >= 0; i--) { Transform child = eqpmtItemParent.GetChild(i); if (child == null) { continue; } #if UNITY_EDITOR if (!Application.isPlaying) { DestroyImmediate(child.gameObject); } else #endif { Destroy(child.gameObject); } } } spawnedItems.Clear(); } private static int CompareEquipments(equipmentSO left, equipmentSO right, EquipOrderMode mode) { if (left == right) { return 0; } if (left == null) { return 1; } if (right == null) { return -1; } switch (mode) { case EquipOrderMode.AcquireAsc: return CompareAcquire(left, right, false); case EquipOrderMode.AcquireDesc: return CompareAcquire(left, right, true); case EquipOrderMode.QualityAsc: return CompareQuality(left, right, false); case EquipOrderMode.QualityDesc: return CompareQuality(left, right, true); default: return CompareAcquire(left, right, false); } } private static int CompareAcquire(equipmentSO left, equipmentSO right, bool descending) { ParseEquipmentSortKey(left, out long leftDate, out long leftId); ParseEquipmentSortKey(right, out long rightDate, out long rightId); int dateCompare = leftDate.CompareTo(rightDate); if (dateCompare != 0) { return descending ? -dateCompare : dateCompare; } int idCompare = leftId.CompareTo(rightId); if (idCompare != 0) { return descending ? -idCompare : idCompare; } string leftName = left.GetDisplayTierName(); string rightName = right.GetDisplayTierName(); int nameCompare = string.Compare(leftName, rightName, StringComparison.Ordinal); return descending ? -nameCompare : nameCompare; } private static int CompareQuality(equipmentSO left, equipmentSO right, bool descending) { int qualityCompare = left.GetVisualQualityColorIndex().CompareTo(right.GetVisualQualityColorIndex()); if (qualityCompare != 0) { return descending ? -qualityCompare : qualityCompare; } return CompareAcquire(left, right, true); } private static void ParseEquipmentSortKey(equipmentSO equipment, out long datePart, out long idPart) { datePart = 0L; idPart = 0L; if (equipment == null || string.IsNullOrWhiteSpace(equipment.name)) { return; } string raw = equipment.name; if (raw.StartsWith("type", StringComparison.OrdinalIgnoreCase)) { int firstUnderscore = raw.IndexOf('_'); if (firstUnderscore >= 0 && firstUnderscore + 1 < raw.Length) { raw = raw.Substring(firstUnderscore + 1); } } string[] parts = raw.Split('_'); if (parts.Length >= 2) { long.TryParse(parts[0], out datePart); long.TryParse(parts[1], out idPart); } } }