RestaurantManagementUi 상호작용 오류 수정 및 로직 변경

This commit is contained in:
NTG_Lenovo 2025-08-07 17:52:45 +09:00
parent f02fe591dc
commit 26cd093313
13 changed files with 128 additions and 58 deletions

View File

@ -98,7 +98,7 @@ public class TodayMenuAddedEvent : IEvent {}
public class TodayMenuRemovedEvent : IEvent public class TodayMenuRemovedEvent : IEvent
{ {
public RecipeType RecipeType; public InventoryCategoryType InventoryCategoryType;
} }
#endregion #endregion

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Sirenix.OdinInspector; using Sirenix.OdinInspector;
using UnityEngine; using UnityEngine;
@ -26,12 +27,12 @@ public class RestaurantManagementSo : GameFlowTask
[ReadOnly, ShowInInspector] private Dictionary<string, int> _todayFoodRecipeIds = new(); [ReadOnly, ShowInInspector] private Dictionary<string, int> _todayFoodRecipeIds = new();
[ReadOnly, ShowInInspector] private Dictionary<string, int> _todayDrinkRecipeIds = new(); [ReadOnly, ShowInInspector] private Dictionary<string, int> _todayDrinkRecipeIds = new();
[ReadOnly, ShowInInspector] private List<string> _todayWorkerIds = new(); [ReadOnly, ShowInInspector] private List<string> _todayWorkerIds = new();
[ReadOnly, ShowInInspector] private List<string> _todayCookwareIds = new(); [ReadOnly, ShowInInspector] private Dictionary<string, HashSet<string>> _cookwareToRecipeIds = new();
public IReadOnlyDictionary<string, int> TodayFoodRecipeIds => _todayFoodRecipeIds; public IReadOnlyDictionary<string, int> TodayFoodRecipeIds => _todayFoodRecipeIds;
public IReadOnlyDictionary<string, int> TodayDrinkRecipeIds => _todayDrinkRecipeIds; public IReadOnlyDictionary<string, int> TodayDrinkRecipeIds => _todayDrinkRecipeIds;
public IReadOnlyList<string> TodayWorkerIds => _todayWorkerIds; public IReadOnlyList<string> TodayWorkerIds => _todayWorkerIds;
public IReadOnlyList<string> TodayCookwareIds => _todayCookwareIds; public IReadOnlyDictionary<string, HashSet<string>> CookwareToRecipeIds => _cookwareToRecipeIds;
public override Task OnReadyNewFlow(GameFlowState newFlowState) public override Task OnReadyNewFlow(GameFlowState newFlowState)
{ {
@ -48,16 +49,25 @@ private void InitializeReadyForRestaurant()
_todayFoodRecipeIds.Clear(); _todayFoodRecipeIds.Clear();
_todayDrinkRecipeIds.Clear(); _todayDrinkRecipeIds.Clear();
_todayWorkerIds.Clear(); _todayWorkerIds.Clear();
_todayCookwareIds.Clear(); _cookwareToRecipeIds.Clear();
} }
public bool TryAddTodayMenu(ItemSlotUi itemSlotUi) public bool IsOpenable()
{ {
string recipeId = itemSlotUi.Model.Id; // TODO : 영업 가능한 상태인지 조건 추가 (최소 요리, 요리도구 배치 등)
bool isExistedCookware = CookwareToRecipeIds.Count > 0;
bool isExistedMatchedMenu = _cookwareToRecipeIds.Values.Any(recipeSet => recipeSet is { Count: > 0 });
if (itemSlotUi.Model.ItemType != ItemType.Recipe) return false; return isExistedCookware && isExistedMatchedMenu;
}
if (!DataManager.Instance.GetDataSo<RecipeDataSo>().TryGetDataById(recipeId, out RecipeData recipeData)) return false; public bool TryAddTodayMenu(ItemViewModel model)
{
string recipeId = model.Id;
if (model.ItemType != ItemType.Recipe) return false;
if (DataManager.Instance.GetDataSo<RecipeDataSo>().TryGetDataById(recipeId, out RecipeData recipeData) == false) return false;
bool added = false; bool added = false;
@ -86,18 +96,24 @@ public bool TryAddTodayMenu(ItemSlotUi itemSlotUi)
if (added) if (added)
{ {
var cookwareKey = GetRequiredCookwareKey(recipeId);
if (string.IsNullOrWhiteSpace(cookwareKey) == false && _cookwareToRecipeIds.TryGetValue(cookwareKey, out var recipeSet))
{
recipeSet.Add(recipeId);
}
EventBus.Broadcast(RestaurantEvents.TodayMenuAddedEvent); EventBus.Broadcast(RestaurantEvents.TodayMenuAddedEvent);
} }
return added; return added;
} }
public bool TryRemoveTodayMenu(ItemSlotUi itemSlotUi) public bool TryRemoveTodayMenu(ItemViewModel model)
{ {
string recipeId = itemSlotUi.Model.Id; string recipeId = model.Id;
var evt = RestaurantEvents.TodayMenuRemovedEvent; var evt = RestaurantEvents.TodayMenuRemovedEvent;
if (!DataManager.Instance.GetDataSo<RecipeDataSo>().TryGetDataById(recipeId, out RecipeData recipeData)) return false; if (DataManager.Instance.GetDataSo<RecipeDataSo>().TryGetDataById(recipeId, out RecipeData recipeData) == false) return false;
bool removed = false; bool removed = false;
int refundCount = 0; int refundCount = 0;
@ -107,7 +123,7 @@ public bool TryRemoveTodayMenu(ItemSlotUi itemSlotUi)
if (_todayFoodRecipeIds.TryGetValue(recipeId, out refundCount)) if (_todayFoodRecipeIds.TryGetValue(recipeId, out refundCount))
{ {
removed = _todayFoodRecipeIds.Remove(recipeId); removed = _todayFoodRecipeIds.Remove(recipeId);
evt.RecipeType = RecipeType.FoodRecipe; evt.InventoryCategoryType = InventoryCategoryType.Food;
if (removed) if (removed)
{ {
@ -121,7 +137,7 @@ public bool TryRemoveTodayMenu(ItemSlotUi itemSlotUi)
if (_todayDrinkRecipeIds.TryGetValue(recipeId, out refundCount)) if (_todayDrinkRecipeIds.TryGetValue(recipeId, out refundCount))
{ {
removed = _todayDrinkRecipeIds.Remove(recipeId); removed = _todayDrinkRecipeIds.Remove(recipeId);
evt.RecipeType = RecipeType.DrinkRecipe; evt.InventoryCategoryType = InventoryCategoryType.Drink;
if (removed) if (removed)
{ {
@ -131,39 +147,78 @@ public bool TryRemoveTodayMenu(ItemSlotUi itemSlotUi)
} }
} }
if (!removed) return false; if (removed)
{
EventBus.Broadcast(evt); var cookwareKey = GetRequiredCookwareKey(recipeId);
return true; if (string.IsNullOrWhiteSpace(cookwareKey) == false && _cookwareToRecipeIds.TryGetValue(cookwareKey, out var recipeSet))
{
recipeSet.Remove(recipeId);
} }
public bool TryAddTodayCookware(ItemSlotUi itemSlotUi) EventBus.Broadcast(evt);
}
return removed;
}
public bool TryAddTodayCookware(ItemViewModel model)
{ {
var itemId = itemSlotUi.Model.Id; var cookwareId = model.Id;
if (itemSlotUi.Model.Count <= 0 || DataManager.Instance.GetDataSo<CookwareDataSo>().TryGetDataById(itemId, out CookwareData cookwareData) == false) return false; if (model.HasItem == false || DataManager.Instance.GetDataSo<CookwareDataSo>().ContainsData(cookwareId) == false) return false;
if (_todayCookwareIds.Count >= MaxCookwareCount || _todayCookwareIds.Contains(itemId)) return false; if (_cookwareToRecipeIds.Count >= MaxCookwareCount || _cookwareToRecipeIds.ContainsKey(cookwareId)) return false;
_cookwareToRecipeIds[cookwareId] = new HashSet<string>();
foreach (var recipeId in _todayFoodRecipeIds.Keys.Concat(_todayDrinkRecipeIds.Keys))
{
var required = GetRequiredCookwareKey(recipeId);
if (required == cookwareId)
{
_cookwareToRecipeIds[cookwareId].Add(recipeId);
}
}
_todayCookwareIds.Add(itemId);
EventBus.Broadcast(RestaurantEvents.TodayMenuAddedEvent); EventBus.Broadcast(RestaurantEvents.TodayMenuAddedEvent);
return true; return true;
} }
public bool TryRemoveTodayCookware(ItemSlotUi itemSlotUi) public bool IsContainTodayMenu(string recipeId)=> _todayFoodRecipeIds.ContainsKey(recipeId) || _todayDrinkRecipeIds.ContainsKey(recipeId);
public bool TryRemoveTodayCookware(ItemViewModel model)
{ {
var itemId = itemSlotUi.Model.Id; var cookwareId = model.Id;
if (DataManager.Instance.GetDataSo<CookwareDataSo>().TryGetDataById(itemId, out CookwareData cookwareData) == false) return false; if (DataManager.Instance.GetDataSo<CookwareDataSo>().ContainsData(cookwareId) == false) return false;
if (_todayCookwareIds.Remove(itemId) == false) return false; if (_cookwareToRecipeIds.Remove(cookwareId) == false) return false;
EventBus.Broadcast( RestaurantEvents.TodayMenuRemovedEvent); var evt = RestaurantEvents.TodayMenuRemovedEvent;
evt.InventoryCategoryType = InventoryCategoryType.Cookware;
EventBus.Broadcast(evt);
return true; return true;
} }
public bool IsContainTodayMenu(string recipeId)=> _todayFoodRecipeIds.ContainsKey(recipeId) || _todayDrinkRecipeIds.ContainsKey(recipeId); private string GetRequiredCookwareKey(string recipeId)
{
if (DataManager.Instance.GetDataSo<RecipeDataSo>().TryGetDataById(recipeId, out var recipeData) == false) return null;
var resultKey = recipeData.RecipeResult;
return recipeData.RecipeType switch
{
RecipeType.FoodRecipe => DataManager.Instance.GetDataSo<FoodDataSo>().GetDataById(resultKey).CookwareKey,
RecipeType.DrinkRecipe => DataManager.Instance.GetDataSo<DrinkDataSo>().GetDataById(resultKey).CookwareKey,
_ => null
};
}
public bool IsCookwareMatched(string recipeId)
{
return _cookwareToRecipeIds.Values.Any(recipeHashSets => recipeHashSets.Contains(recipeId));
}
} }
} }

View File

@ -7,7 +7,7 @@ public class InventorySlotUiStrategy : IItemSlotUiStrategy
{ {
public string AnimatorControllerKey => "InventorySlotUi"; public string AnimatorControllerKey => "InventorySlotUi";
public void Setup(ItemSlotUi ui, ItemViewModel model) public Task Setup(ItemSlotUi ui, ItemViewModel model)
{ {
if (InventoryManager.Instance.ContainInventoryItem(model.Id)) if (InventoryManager.Instance.ContainInventoryItem(model.Id))
{ {
@ -15,7 +15,8 @@ public void Setup(ItemSlotUi ui, ItemViewModel model)
ui.ShowCountText(); ui.ShowCountText();
ui.HideMark(); ui.HideMark();
ui.SetButtonInteractable(true); ui.SetButtonInteractable(true);
return;
return Task.CompletedTask;
} }
// TODO : 임시 초기화 값 // TODO : 임시 초기화 값
@ -36,6 +37,8 @@ public void Setup(ItemSlotUi ui, ItemViewModel model)
ui.HideCountText(); ui.HideCountText();
ui.HideMark(); ui.HideMark();
ui.SetButtonInteractable(false); ui.SetButtonInteractable(false);
return Task.CompletedTask;
} }
public async Task<RuntimeAnimatorController> GetAnimatorController() public async Task<RuntimeAnimatorController> GetAnimatorController()

View File

@ -19,6 +19,8 @@ public class InventoryView : MonoBehaviour, IEventHandler<InventoryChangedEvent>
private const string ItemSlotUiName = "ItemSlotUi_"; private const string ItemSlotUiName = "ItemSlotUi_";
public GameObject GetInitialSelected() => _firstSlot;
private void OnEnable() private void OnEnable()
{ {
EventBus.Register<InventoryChangedEvent>(this); EventBus.Register<InventoryChangedEvent>(this);
@ -33,8 +35,6 @@ private void OnDisable()
EventBus.Unregister<TodayMenuRemovedEvent>(this); EventBus.Unregister<TodayMenuRemovedEvent>(this);
} }
public GameObject GetInitialSelected() => _firstSlot;
public async Task Initialize() public async Task Initialize()
{ {
_restaurantManagementSo = _restaurantManagementSo =
@ -92,7 +92,7 @@ private IEnumerable<ItemSlotUi> SortSlots(IEnumerable<ItemSlotUi> slots)
public void UpdateCategoryView(InventoryCategoryType category) public void UpdateCategoryView(InventoryCategoryType category)
{ {
_currenInventoryCategoryType = category; _currenInventoryCategoryType = category;
_firstSlot = null; GameObject firstValidSlot = null;
var filteredSlots = _slotLookup.Values; var filteredSlots = _slotLookup.Values;
var sortedSlots = SortSlots(filteredSlots); var sortedSlots = SortSlots(filteredSlots);
@ -114,12 +114,14 @@ public void UpdateCategoryView(InventoryCategoryType category)
{ {
slot.transform.SetSiblingIndex(siblingIndex++); slot.transform.SetSiblingIndex(siblingIndex++);
if (_firstSlot == null) if (firstValidSlot == null)
{ {
_firstSlot = slot.gameObject; firstValidSlot = slot.gameObject;
} }
} }
} }
_firstSlot = firstValidSlot;
} }
private bool MatchesCategory(ItemViewModel model, InventoryCategoryType category) private bool MatchesCategory(ItemViewModel model, InventoryCategoryType category)

View File

@ -6,7 +6,7 @@ namespace DDD
public interface IItemSlotUiStrategy public interface IItemSlotUiStrategy
{ {
string AnimatorControllerKey { get; } string AnimatorControllerKey { get; }
void Setup(ItemSlotUi ui, ItemViewModel model); Task Setup(ItemSlotUi ui, ItemViewModel model);
Task<RuntimeAnimatorController> GetAnimatorController(); Task<RuntimeAnimatorController> GetAnimatorController();
} }
} }

View File

@ -26,7 +26,7 @@ public async Task Initialize(ItemViewModel model, IItemSlotUiStrategy strategy)
var controller = await strategy.GetAnimatorController(); var controller = await strategy.GetAnimatorController();
_animator.runtimeAnimatorController = controller; _animator.runtimeAnimatorController = controller;
Strategy.Setup(this, model); _ = Strategy.Setup(this, model);
} }
public void SetIcon(Sprite sprite) => _icon.sprite = sprite; public void SetIcon(Sprite sprite) => _icon.sprite = sprite;

View File

@ -172,16 +172,7 @@ private void OnCategoryTabSelected(InventoryCategoryType category)
public void Invoke(TodayMenuRemovedEvent evt) public void Invoke(TodayMenuRemovedEvent evt)
{ {
InventoryCategoryType newInventoryCategoryType = evt.RecipeType switch _menuCategoryTabs.SelectTab(evt.InventoryCategoryType);
{
RecipeType.FoodRecipe => InventoryCategoryType.Food,
RecipeType.DrinkRecipe => InventoryCategoryType.Drink,
_ => InventoryCategoryType.None
};
if (newInventoryCategoryType == InventoryCategoryType.None) return;
_menuCategoryTabs.SelectTab(newInventoryCategoryType);
} }
} }
} }

View File

@ -8,7 +8,7 @@ public void OnAdded(ItemSlotUi itemSlotUi, RestaurantManagementSo restaurantMana
if (inventorySlotUiStrategy.CanCrafting(itemSlotUi)) if (inventorySlotUiStrategy.CanCrafting(itemSlotUi))
{ {
restaurantManagementSo.TryAddTodayMenu(itemSlotUi); restaurantManagementSo.TryAddTodayMenu(itemSlotUi.Model);
} }
else else
{ {
@ -25,7 +25,7 @@ public void OnRemoved(ItemSlotUi itemSlotUi, RestaurantManagementSo restaurantMa
{ {
if (itemSlotUi.Strategy is InventorySlotUiStrategy) return; if (itemSlotUi.Strategy is InventorySlotUiStrategy) return;
restaurantManagementSo.TryRemoveTodayMenu(itemSlotUi); restaurantManagementSo.TryRemoveTodayMenu(itemSlotUi.Model);
} }
} }
} }

View File

@ -6,6 +6,7 @@ namespace DDD
public class TodayMenuSlotUiStrategy : IItemSlotUiStrategy public class TodayMenuSlotUiStrategy : IItemSlotUiStrategy
{ {
private readonly RecipeType _recipeType; private readonly RecipeType _recipeType;
private RestaurantManagementSo _restaurantManagementSo;
public string AnimatorControllerKey => "TodayMenuSlotUi"; public string AnimatorControllerKey => "TodayMenuSlotUi";
@ -14,8 +15,10 @@ public TodayMenuSlotUiStrategy(RecipeType recipeType)
_recipeType = recipeType; _recipeType = recipeType;
} }
public void Setup(ItemSlotUi ui, ItemViewModel model) public async Task Setup(ItemSlotUi ui, ItemViewModel model)
{ {
_restaurantManagementSo = await AssetManager.LoadAsset<RestaurantManagementSo>(DataConstants.RestaurantManagementSo);
if (model == null) if (model == null)
{ {
string emptySpriteKey = null; string emptySpriteKey = null;
@ -32,12 +35,22 @@ public void Setup(ItemSlotUi ui, ItemViewModel model)
ui.HideCountText(); ui.HideCountText();
ui.HideMark(); ui.HideMark();
ui.SetButtonInteractable(false); ui.SetButtonInteractable(false);
return; return;
} }
string markSpriteKey = null;
if (_restaurantManagementSo.IsCookwareMatched(ui.Model.Id))
{
markSpriteKey = SpriteConstants.CheckYesSpriteKey;
}
else
{
markSpriteKey = SpriteConstants.CheckNoSpriteKey;
}
ui.SetIcon(model.ItemSprite); ui.SetIcon(model.ItemSprite);
ui.HideCountText(); ui.HideCountText();
ui.ShowMark(DataManager.Instance.GetSprite(SpriteConstants.CheckNoSpriteKey)); // TODO : 추후에 장비와 매칭 ui.ShowMark(DataManager.Instance.GetSprite(markSpriteKey));
ui.SetButtonInteractable(true); ui.SetButtonInteractable(true);
} }

View File

@ -8,7 +8,7 @@ public void OnAdded(ItemSlotUi itemSlotUi, RestaurantManagementSo restaurantMana
if (inventorySlotUiStrategy.CanCrafting(itemSlotUi)) if (inventorySlotUiStrategy.CanCrafting(itemSlotUi))
{ {
restaurantManagementSo.TryAddTodayCookware(itemSlotUi); restaurantManagementSo.TryAddTodayCookware(itemSlotUi.Model);
} }
else else
{ {
@ -25,7 +25,7 @@ public void OnRemoved(ItemSlotUi itemSlotUi, RestaurantManagementSo restaurantMa
{ {
if (itemSlotUi.Strategy is InventorySlotUiStrategy) return; if (itemSlotUi.Strategy is InventorySlotUiStrategy) return;
restaurantManagementSo.TryRemoveTodayCookware(itemSlotUi); restaurantManagementSo.TryRemoveTodayCookware(itemSlotUi.Model);
} }
} }
} }

View File

@ -9,7 +9,7 @@ public class TodayCookwareSlotUiStrategy : IItemSlotUiStrategy
public string AnimatorControllerKey => "TodayMenuSlotUi"; public string AnimatorControllerKey => "TodayMenuSlotUi";
public void Setup(ItemSlotUi ui, ItemViewModel model) public Task Setup(ItemSlotUi ui, ItemViewModel model)
{ {
if (model == null) if (model == null)
{ {
@ -17,13 +17,16 @@ public void Setup(ItemSlotUi ui, ItemViewModel model)
ui.HideCountText(); ui.HideCountText();
ui.HideMark(); ui.HideMark();
ui.SetButtonInteractable(false); ui.SetButtonInteractable(false);
return;
return Task.CompletedTask;
} }
ui.SetIcon(model.ItemSprite); ui.SetIcon(model.ItemSprite);
ui.HideCountText(); ui.HideCountText();
ui.ShowMark(DataManager.Instance.GetSprite(SpriteConstants.CheckNoSpriteKey)); // TODO : 추후에 장비와 매칭 ui.ShowMark(DataManager.Instance.GetSprite(SpriteConstants.CheckNoSpriteKey)); // TODO : 추후에 장비와 매칭
ui.SetButtonInteractable(true); ui.SetButtonInteractable(true);
return Task.CompletedTask;
} }
public async Task<RuntimeAnimatorController> GetAnimatorController() public async Task<RuntimeAnimatorController> GetAnimatorController()

View File

@ -101,7 +101,7 @@ private void UpdateView()
} }
int cookwareIndex = 0; int cookwareIndex = 0;
foreach (var cookwareKey in _restaurantManagementSo.TodayCookwareIds) foreach (var cookwareKey in _restaurantManagementSo.CookwareToRecipeIds.Keys)
{ {
if (cookwareIndex >= _cookwareSlots.Count) break; if (cookwareIndex >= _cookwareSlots.Count) break;

View File

@ -9,7 +9,7 @@ public class TodayWorkerSlotUiStrategy : IItemSlotUiStrategy
public string AnimatorControllerKey => "TodayMenuSlotUi"; public string AnimatorControllerKey => "TodayMenuSlotUi";
public void Setup(ItemSlotUi ui, ItemViewModel model) public Task Setup(ItemSlotUi ui, ItemViewModel model)
{ {
if (model == null) if (model == null)
{ {
@ -17,13 +17,16 @@ public void Setup(ItemSlotUi ui, ItemViewModel model)
ui.HideCountText(); ui.HideCountText();
ui.HideMark(); ui.HideMark();
ui.SetButtonInteractable(false); ui.SetButtonInteractable(false);
return;
return Task.CompletedTask;
} }
ui.SetIcon(model.ItemSprite); ui.SetIcon(model.ItemSprite);
ui.HideCountText(); ui.HideCountText();
ui.ShowMark(DataManager.Instance.GetSprite(SpriteConstants.CheckNoSpriteKey)); // TODO : 추후에 장비와 매칭 ui.ShowMark(DataManager.Instance.GetSprite(SpriteConstants.CheckNoSpriteKey)); // TODO : 추후에 장비와 매칭
ui.SetButtonInteractable(true); ui.SetButtonInteractable(true);
return Task.CompletedTask;
} }
public async Task<RuntimeAnimatorController> GetAnimatorController() public async Task<RuntimeAnimatorController> GetAnimatorController()