diff --git a/Assets/_DDD/_Scripts/GameState/InventoryManager.cs b/Assets/_DDD/_Scripts/GameState/InventoryManager.cs index 789ecab53..006d58597 100644 --- a/Assets/_DDD/_Scripts/GameState/InventoryManager.cs +++ b/Assets/_DDD/_Scripts/GameState/InventoryManager.cs @@ -6,11 +6,20 @@ namespace DDD { + public enum InventorySortType + { + None = 0, + NameAscending, + NameDescending, + QuantityAscending, + QuantityDescending + } + public class InventoryManager : Singleton, IManager { [Title("아이템 전체 목록")] [ShowInInspector, ReadOnly] - private Dictionary _itemDataLookup; + private Dictionary _allItemDataLookup; [Title("아이템 보유 목록")] [ShowInInspector, ReadOnly] @@ -41,7 +50,7 @@ private void InitializeItemData() var itemDataSo = DataManager.Instance.GetDataSo(); Debug.Assert(itemDataSo != null, "itemDataSo != null"); - _itemDataLookup = itemDataSo.GetDataList() + _allItemDataLookup = itemDataSo.GetDataList() .Where(item => !string.IsNullOrEmpty(item.Id)) .ToDictionary(item => item.Id, item => item); @@ -72,7 +81,7 @@ private async void ApplyEditorTestData() public bool AddItem(string id, int quantity = 1) { - if (!_itemDataLookup.ContainsKey(id)) + if (!_allItemDataLookup.ContainsKey(id)) { Debug.LogError($"[Inventory] 등록되지 않은 아이템 ID: {id}"); return false; @@ -123,12 +132,14 @@ public bool RemoveItem(string id, int quantity = 1) return true; } + public IReadOnlyDictionary AllItemDataLookup => _allItemDataLookup; public IReadOnlyDictionary InventoryItems => _inventoryItemDatas; - public bool TryGetItemData(string id, out ItemData itemData) => _itemDataLookup.TryGetValue(id, out itemData); + public bool ContainInventoryItem(string id) => _inventoryItemDatas.ContainsKey(id); + public bool TryGetInventoryItemData(string id, out InventoryItemData inventoryItemData) => _inventoryItemDatas.TryGetValue(id, out inventoryItemData); public int GetItemCount(string id) => _inventoryItemDatas.TryGetValue(id, out var itemData) ? itemData.Quantity : 0; public ItemData GetItemDataByIdOrNull(string id) { - _itemDataLookup.TryGetValue(id, out var itemData); + _allItemDataLookup.TryGetValue(id, out var itemData); return itemData; } } diff --git a/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/InventoryUi/InventorySlotUiStrategy.cs b/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/InventoryUi/InventorySlotUiStrategy.cs index 41872e1d0..b9b9cc6ec 100644 --- a/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/InventoryUi/InventorySlotUiStrategy.cs +++ b/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/InventoryUi/InventorySlotUiStrategy.cs @@ -9,10 +9,33 @@ public class InventorySlotUiStrategy : IItemSlotUiStrategy public void Setup(ItemSlotUi ui, ItemViewModel model) { - ui.SetIcon(model.ItemSprite); - ui.ShowCountText(); + if (InventoryManager.Instance.ContainInventoryItem(model.Id)) + { + ui.SetIcon(model.ItemSprite); + ui.ShowCountText(); + ui.HideMark(); + ui.SetButtonInteractable(true); + return; + } + + // TODO : 임시 초기화 값 + string emptySpriteKey = SpriteConstants.EmptyFoodSpriteKey; + if (model.ItemType == ItemType.Recipe) + { + if (model.RecipeType == RecipeType.FoodRecipe) + { + emptySpriteKey = SpriteConstants.EmptyFoodSpriteKey; + } + else if (model.RecipeType == RecipeType.DrinkRecipe) + { + emptySpriteKey = SpriteConstants.EmptyDrinkSpriteKey; + } + } + + ui.SetIcon(DataManager.Instance.GetSprite(emptySpriteKey)); + ui.HideCountText(); ui.HideMark(); - ui.SetButtonInteractable(true); + ui.SetButtonInteractable(false); } public async Task GetAnimatorController() @@ -22,10 +45,12 @@ public async Task GetAnimatorController() public void OnInventoryChanged(ItemSlotUi ui) { - if (ui.Model == null) return; - - ui.Model.UpdateCount(); - ui.ShowCountText(); + var model = ui.Model; + if (InventoryManager.Instance.ContainInventoryItem(model.Id)) + { + ui.Model.UpdateCount(); + ui.ShowCountText(); + } } public bool CanCrafting(ItemSlotUi ui) diff --git a/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/InventoryUi/InventoryView.cs b/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/InventoryUi/InventoryView.cs index b20ed9504..2e7a0090c 100644 --- a/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/InventoryUi/InventoryView.cs +++ b/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/InventoryUi/InventoryView.cs @@ -1,23 +1,24 @@ -using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using UnityEngine; -using UnityEngine.AddressableAssets; namespace DDD { - public class InventoryView : MonoBehaviour, IEventHandler, IEventHandler, IEventHandler + public class InventoryView : MonoBehaviour, IEventHandler, + IEventHandler, IEventHandler { [SerializeField] private Transform _slotParent; - + private RestaurantManagementSo _restaurantManagementSo; private InventoryCategoryType _currenInventoryCategoryType = InventoryCategoryType.Food; - + private readonly Dictionary _slotLookup = new(); private GameObject _firstSlot; - + private InventorySortType _currentSortType = InventorySortType.None; + private const string ItemSlotUiName = "ItemSlotUi_"; - + private void OnEnable() { EventBus.Register(this); @@ -31,13 +32,15 @@ private void OnDisable() EventBus.Unregister(this); EventBus.Unregister(this); } - + public GameObject GetInitialSelected() => _firstSlot; + public async Task Initialize() { - _restaurantManagementSo = await AssetManager.LoadAsset(DataConstants.RestaurantManagementSo); + _restaurantManagementSo = + await AssetManager.LoadAsset(DataConstants.RestaurantManagementSo); Debug.Assert(_restaurantManagementSo != null, "_todayMenuDataSo != null"); - + Clear(); var models = ItemViewModelFactory.CreateRestaurantManagementInventoryItem(); @@ -66,51 +69,79 @@ public async Task Initialize() _slotLookup[model.Id] = slot; } } - + + public void SetSortType(InventorySortType sortType) + { + _currentSortType = sortType; + UpdateView(); + } + + private IEnumerable SortSlots(IEnumerable slots) + { + return _currentSortType switch + { + InventorySortType.NameAscending => slots.OrderByDescending(slot => slot.Model.HasItem).ThenBy(slot => slot.Model.DisplayName), + InventorySortType.NameDescending => slots.OrderByDescending(slot => slot.Model.HasItem).ThenByDescending(slot => slot.Model.DisplayName), + InventorySortType.QuantityAscending => slots.OrderByDescending(slot => slot.Model.HasItem).ThenBy(slot => slot.Model.Count), + InventorySortType.QuantityDescending => slots.OrderByDescending(slot => slot.Model.HasItem).ThenByDescending(slot => slot.Model.Count), + InventorySortType.None => slots.OrderBy(slot => slot.Model.Id), + _ => slots + }; + } + public void UpdateCategoryView(InventoryCategoryType category) { _currenInventoryCategoryType = category; - _firstSlot = null; - foreach (var kvp in _slotLookup) + + var filteredSlots = _slotLookup.Values; + var sortedSlots = SortSlots(filteredSlots); + + int siblingIndex = 0; + + foreach (var slot in sortedSlots) { - var id = kvp.Key; - var slot = kvp.Value; var model = slot.Model; + string id = model.Id; - // 1. 오늘의 메뉴에 등록된 경우 필터링 bool isRegisteredTodayMenu = model.ItemType == ItemType.Recipe && _restaurantManagementSo.IsContainTodayMenu(id); - - // 2. 현재 선택된 카테고리에 맞는지 필터링 bool matchCategory = MatchesCategory(model, _currenInventoryCategoryType); - - // 3. 조건을 모두 만족할 경우만 활성화 bool shouldShow = !isRegisteredTodayMenu && matchCategory; + slot.SetActive(shouldShow); - if (shouldShow && _firstSlot == null) + if (shouldShow && model.HasItem) { - _firstSlot = slot.gameObject; + slot.transform.SetSiblingIndex(siblingIndex++); + + if (_firstSlot == null) + { + _firstSlot = slot.gameObject; + } } } } - + private bool MatchesCategory(ItemViewModel model, InventoryCategoryType category) { switch (category) { case InventoryCategoryType.Food: if (model.ItemType != ItemType.Recipe) return false; - - return DataManager.Instance.GetDataSo().TryGetDataById(model.Id, out var foodRecipe) && foodRecipe.RecipeType == RecipeType.FoodRecipe; + + return DataManager.Instance.GetDataSo() + .TryGetDataById(model.Id, out var foodRecipe) && foodRecipe.RecipeType == RecipeType.FoodRecipe; case InventoryCategoryType.Drink: if (model.ItemType != ItemType.Recipe) return false; - - return DataManager.Instance.GetDataSo().TryGetDataById(model.Id, out var drinkRecipe) && drinkRecipe.RecipeType == RecipeType.DrinkRecipe; + + return DataManager.Instance.GetDataSo() + .TryGetDataById(model.Id, out var drinkRecipe) && + drinkRecipe.RecipeType == RecipeType.DrinkRecipe; case InventoryCategoryType.Ingredient: return model.ItemType == ItemType.Ingredient; case InventoryCategoryType.Cookware: - return DataManager.Instance.GetDataSo().TryGetDataById(model.Id, out var cookwareData); + return DataManager.Instance.GetDataSo() + .TryGetDataById(model.Id, out var cookwareData); case InventoryCategoryType.Special: return false; default: diff --git a/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/ItemUi/ItemViewModel.cs b/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/ItemUi/ItemViewModel.cs index 66318bc00..b5b4938f0 100644 --- a/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/ItemUi/ItemViewModel.cs +++ b/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/ItemUi/ItemViewModel.cs @@ -25,6 +25,8 @@ public ItemViewModel(string id, ItemType itemType) Count = 0; } + public bool HasItem => Count > 0; + public string DisplayName => LocalizationManager.Instance.GetName(Id); public RecipeType RecipeType => ItemType == ItemType.Recipe ? DataManager.Instance.GetDataSo().GetDataById(Id).RecipeType : RecipeType.None; public Sprite ItemSprite { diff --git a/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/ItemUi/ItemViewModelFactory.cs b/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/ItemUi/ItemViewModelFactory.cs index 4fca1b3d4..98699ec43 100644 --- a/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/ItemUi/ItemViewModelFactory.cs +++ b/Assets/_DDD/_Scripts/GameUi/RestaurantManagementUi/ItemUi/ItemViewModelFactory.cs @@ -7,18 +7,23 @@ public static class ItemViewModelFactory public static List CreateRestaurantManagementInventoryItem() { var result = new List(); - foreach (var kvp in InventoryManager.Instance.InventoryItems) + var allItemDataLookup = InventoryManager.Instance.AllItemDataLookup; + foreach (var keyItemDataPair in allItemDataLookup) { - var id = kvp.Key; - var item = InventoryManager.Instance.GetItemDataByIdOrNull(id); - if (item == null) continue; + var id = keyItemDataPair.Key; + var itemData = keyItemDataPair.Value; - var modelCount = item.ItemType switch + int modelCount = 0; + if (InventoryManager.Instance.ContainInventoryItem(id)) { - ItemType.Recipe => CalculateCraftableCount(item.Id), - _ => InventoryManager.Instance.GetItemCount(id) - }; - var model = new ItemViewModel(item.Id, item.ItemType, modelCount); + modelCount = itemData.ItemType switch + { + ItemType.Recipe => CalculateCraftableCount(itemData.Id), + _ => InventoryManager.Instance.GetItemCount(id) + }; + } + + var model = new ItemViewModel(id, itemData.ItemType, modelCount); result.Add(model); }