TodayMenuView viewModel 로직 분리

This commit is contained in:
NTG 2025-08-21 18:15:51 +09:00
parent 4867427b8b
commit 5b0e6fd786
22 changed files with 332 additions and 268 deletions

View File

@ -173,10 +173,48 @@ PrefabInstance:
- targetCorrespondingSourceObject: {fileID: 8967231042952671610, guid: 4f2bf029cb06b084ba41defc8fc76731, type: 3} - targetCorrespondingSourceObject: {fileID: 8967231042952671610, guid: 4f2bf029cb06b084ba41defc8fc76731, type: 3}
insertIndex: -1 insertIndex: -1
addedObject: {fileID: 5701939276505918991} addedObject: {fileID: 5701939276505918991}
m_AddedComponents: [] m_AddedComponents:
- targetCorrespondingSourceObject: {fileID: 6952779389930089995, guid: 4f2bf029cb06b084ba41defc8fc76731, type: 3}
insertIndex: -1
addedObject: {fileID: 3558726899806659957}
- targetCorrespondingSourceObject: {fileID: 6952779389930089995, guid: 4f2bf029cb06b084ba41defc8fc76731, type: 3}
insertIndex: -1
addedObject: {fileID: 7215137460101227451}
m_SourcePrefab: {fileID: 100100000, guid: 4f2bf029cb06b084ba41defc8fc76731, type: 3} m_SourcePrefab: {fileID: 100100000, guid: 4f2bf029cb06b084ba41defc8fc76731, type: 3}
--- !u!224 &7368736952364656095 stripped --- !u!224 &7368736952364656095 stripped
RectTransform: RectTransform:
m_CorrespondingSourceObject: {fileID: 8967231042952671610, guid: 4f2bf029cb06b084ba41defc8fc76731, type: 3} m_CorrespondingSourceObject: {fileID: 8967231042952671610, guid: 4f2bf029cb06b084ba41defc8fc76731, type: 3}
m_PrefabInstance: {fileID: 1887292089917625509} m_PrefabInstance: {fileID: 1887292089917625509}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
--- !u!1 &8812486931779779246 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 6952779389930089995, guid: 4f2bf029cb06b084ba41defc8fc76731, type: 3}
m_PrefabInstance: {fileID: 1887292089917625509}
m_PrefabAsset: {fileID: 0}
--- !u!114 &3558726899806659957
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8812486931779779246}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7856cd3c67598cf41a31efc38bb512d9, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &7215137460101227451
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8812486931779779246}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fa01b8c8ff13d3241b943d0f12d3b767, type: 3}
m_Name:
m_EditorClassIdentifier:
<UiType>k__BackingField: 3
_enableBlockImage: 0
_uiActionsInputBinding: {fileID: 11400000, guid: 8dd5523e04e1abd4caff017469c49c58, type: 2}

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8dd5523e04e1abd4caff017469c49c58
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -16,7 +16,7 @@ public enum SmartVariablesDomain : uint
All = 0xFFFFFFFFu, All = 0xFFFFFFFFu,
} }
public enum smartStringKey public enum SmartStringKey
{ {
None = 0, None = 0,
Day, Day,
@ -30,17 +30,21 @@ public enum smartStringKey
public class SmartStringVariables : Singleton<SmartStringVariables>, IManager, IEventHandler<SmartVariablesDirtyEvent> public class SmartStringVariables : Singleton<SmartStringVariables>, IManager, IEventHandler<SmartVariablesDirtyEvent>
{ {
private Dictionary<smartStringKey, string> _smartStringKeys = new() private Dictionary<SmartStringKey, string> _smartStringKeys = new()
{ {
{smartStringKey.Day, "day"}, {SmartStringKey.Day, "day"},
{smartStringKey.AddedTodayFoodCount, "addedTodayFoodCount"}, {SmartStringKey.AddedTodayFoodCount, "addedTodayFoodCount"},
{smartStringKey.AddedTodayCookwareCount, "addedTodayCookwareCount"}, {SmartStringKey.AddedTodayCookwareCount, "addedTodayCookwareCount"},
{smartStringKey.MatchedTodayMenuWithCookwareCount, "matchedTodayMenuWithCookwareCount"}, {SmartStringKey.MatchedTodayMenuWithCookwareCount, "matchedTodayMenuWithCookwareCount"},
{smartStringKey.ChecklistFoodCount, "checklistFoodCount"}, {SmartStringKey.ChecklistFoodCount, "checklistFoodCount"},
{smartStringKey.ChecklistCookwareCount, "checklistCookwareCount"}, {SmartStringKey.ChecklistCookwareCount, "checklistCookwareCount"},
{smartStringKey.ChecklistMatchedMenuWithCookwareCount, "checklistMatchedMenuWithCookwareCount"}, {SmartStringKey.ChecklistMatchedMenuWithCookwareCount, "checklistMatchedMenuWithCookwareCount"},
}; };
private GameLevelState GetGameLevelState() => GameState.Instance.LevelState;
private RestaurantManagementData GetRestaurantManagementData() => RestaurantData.Instance.ManagementData;
private RestaurantManagementState GetRestaurantManagementState() => RestaurantState.Instance.ManagementState;
private void OnDestroy() private void OnDestroy()
{ {
EventBus.Unregister<SmartVariablesDirtyEvent>(this); EventBus.Unregister<SmartVariablesDirtyEvent>(this);
@ -50,17 +54,13 @@ public void PreInit() { }
public async Task Init() public async Task Init()
{ {
var gameLevelStateSo = GameState.Instance.LevelState; Set(_smartStringKeys[SmartStringKey.Day], GetGameLevelState().Level);
var restaurantStateSo = RestaurantState.Instance.ManagementState; Set(_smartStringKeys[SmartStringKey.ChecklistFoodCount], GetRestaurantManagementData().ChecklistFoodCount);
Set(_smartStringKeys[SmartStringKey.ChecklistCookwareCount], GetRestaurantManagementData().ChecklistCookwareCount);
// 예시: day 초기 세팅 (없으면 생성, 타입 다르면 교체) Set(_smartStringKeys[SmartStringKey.ChecklistMatchedMenuWithCookwareCount], GetRestaurantManagementData().ChecklistMatchedMenuWithCookwareCount);
Set(_smartStringKeys[smartStringKey.Day], gameLevelStateSo.Level); Set(_smartStringKeys[SmartStringKey.AddedTodayFoodCount], GetRestaurantManagementState().AddedTodayFoodCount);
Set(_smartStringKeys[smartStringKey.AddedTodayFoodCount], restaurantStateSo.AddedTodayFoodCount); Set(_smartStringKeys[SmartStringKey.AddedTodayCookwareCount], GetRestaurantManagementState().AddedTodayCookwareCount);
Set(_smartStringKeys[smartStringKey.AddedTodayCookwareCount], restaurantStateSo.AddedTodayCookwareCount); Set(_smartStringKeys[SmartStringKey.MatchedTodayMenuWithCookwareCount], GetRestaurantManagementState().MatchedTodayMenuWithCookwareCount);
Set(_smartStringKeys[smartStringKey.MatchedTodayMenuWithCookwareCount], restaurantStateSo.MatchedTodayMenuWithCookwareCount);
Set(_smartStringKeys[smartStringKey.ChecklistFoodCount], restaurantStateSo.ChecklistFoodCount);
Set(_smartStringKeys[smartStringKey.ChecklistCookwareCount], restaurantStateSo.ChecklistCookwareCount);
Set(_smartStringKeys[smartStringKey.ChecklistMatchedMenuWithCookwareCount], restaurantStateSo.ChecklistMatchedMenuWithCookwareCount);
await Task.CompletedTask; await Task.CompletedTask;
} }
@ -71,8 +71,6 @@ public void PostInit()
EventBus.Register<SmartVariablesDirtyEvent>(this); EventBus.Register<SmartVariablesDirtyEvent>(this);
} }
private RestaurantManagementState GetRestaurantState() => RestaurantState.Instance.ManagementState;
public void Invoke(SmartVariablesDirtyEvent evt) public void Invoke(SmartVariablesDirtyEvent evt)
{ {
var flags = evt.DomainFlags; var flags = evt.DomainFlags;
@ -97,24 +95,22 @@ public void Invoke(SmartVariablesDirtyEvent evt)
public void RefreshTodayMenuCounts() public void RefreshTodayMenuCounts()
{ {
var state = GetRestaurantState(); Set(_smartStringKeys[SmartStringKey.AddedTodayFoodCount], GetRestaurantManagementState().AddedTodayFoodCount);
Set(_smartStringKeys[smartStringKey.AddedTodayFoodCount], state.AddedTodayFoodCount); Set(_smartStringKeys[SmartStringKey.AddedTodayCookwareCount], GetRestaurantManagementState().AddedTodayCookwareCount);
Set(_smartStringKeys[smartStringKey.AddedTodayCookwareCount], state.AddedTodayCookwareCount); Set(_smartStringKeys[SmartStringKey.MatchedTodayMenuWithCookwareCount], GetRestaurantManagementState().MatchedTodayMenuWithCookwareCount);
Set(_smartStringKeys[smartStringKey.MatchedTodayMenuWithCookwareCount], state.MatchedTodayMenuWithCookwareCount);
} }
public void RefreshChecklistTargets() public void RefreshChecklistTargets()
{ {
var state = GetRestaurantState(); Set(_smartStringKeys[SmartStringKey.ChecklistFoodCount], GetRestaurantManagementData().ChecklistFoodCount);
Set(_smartStringKeys[smartStringKey.ChecklistFoodCount], state.ChecklistFoodCount); Set(_smartStringKeys[SmartStringKey.ChecklistCookwareCount], GetRestaurantManagementData().ChecklistCookwareCount);
Set(_smartStringKeys[smartStringKey.ChecklistCookwareCount], state.ChecklistCookwareCount); Set(_smartStringKeys[SmartStringKey.ChecklistMatchedMenuWithCookwareCount], GetRestaurantManagementData().ChecklistMatchedMenuWithCookwareCount);
Set(_smartStringKeys[smartStringKey.ChecklistMatchedMenuWithCookwareCount], state.ChecklistMatchedMenuWithCookwareCount);
} }
public void RefreshDay() public void RefreshDay()
{ {
var gameLevelStateSo = GameState.Instance.LevelState; var gameLevelStateSo = GameState.Instance.LevelState;
Set(_smartStringKeys[smartStringKey.Day], gameLevelStateSo.Level); Set(_smartStringKeys[SmartStringKey.Day], gameLevelStateSo.Level);
} }
public void RefreshAll() public void RefreshAll()

View File

@ -6,7 +6,7 @@ namespace DDD
public abstract class BasePopupUi : BaseUi public abstract class BasePopupUi : BaseUi
{ {
public bool IsTopPopup => UiManager.Instance.UiState.IsTopPopup(this); public bool IsTopPopup => UiManager.Instance.UiState.IsTopPopup(this);
public InputActionMaps InputActionMaps; public InputActionMaps InputActionMaps { get; protected set; }
protected override void Awake() protected override void Awake()
{ {

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2c5267df54c97474fa824451f969b41b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,13 @@
using UnityEngine;
namespace DDD
{
[RequireComponent(typeof(CookViewModel))]
public class CookUi : PopupUi<RestaurantUiActions, CookViewModel>
{
protected override GameObject GetInitialSelected()
{
return null;
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: fa01b8c8ff13d3241b943d0f12d3b767

View File

@ -0,0 +1,9 @@
using UnityEngine;
namespace DDD
{
public class CookViewModel : SimpleViewModel
{
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7856cd3c67598cf41a31efc38bb512d9

View File

@ -35,30 +35,15 @@ protected override void Awake()
_viewModel = GetComponent<TViewModel>(); _viewModel = GetComponent<TViewModel>();
} }
protected override void OnEnable() protected override void TryRegister()
{ {
base.OnEnable(); base.TryRegister();
if (_viewModel && _bindingContext != null) if (_viewModel && _bindingContext != null)
{ {
_bindingContext.SetDataContext(_viewModel); _bindingContext.SetDataContext(_viewModel);
_viewModel.PropertyChanged += OnViewModelPropertyChanged; _viewModel.PropertyChanged += OnViewModelPropertyChanged;
} }
}
protected override void OnDisable()
{
base.OnDisable();
if (_viewModel != null)
{
_viewModel.PropertyChanged -= OnViewModelPropertyChanged;
}
}
protected override void TryRegister()
{
base.TryRegister();
// PopupUi의 입력 바인딩 등록 // PopupUi의 입력 바인딩 등록
foreach (var actionEnum in _uiActionsInputBinding.BindingActions.GetFlags()) foreach (var actionEnum in _uiActionsInputBinding.BindingActions.GetFlags())
@ -99,6 +84,11 @@ protected override void TryUnregister()
{ {
base.TryUnregister(); base.TryUnregister();
if (_viewModel != null)
{
_viewModel.PropertyChanged -= OnViewModelPropertyChanged;
}
// 입력 핸들러 해제 // 입력 핸들러 해제
foreach (var (action, handler) in _registeredHandlers) foreach (var (action, handler) in _registeredHandlers)
{ {

View File

@ -92,7 +92,7 @@ private void UpdateTasteHashTags(ItemViewModel model)
var backgroundMaterial = model.RecipeType switch var backgroundMaterial = model.RecipeType switch
{ {
RecipeType.FoodRecipe => restaurantManagementDataSo.FoodTasteMaterial, RecipeType.FoodRecipe => restaurantManagementDataSo.FoodTasteMaterial,
RecipeType.DrinkRecipe => restaurantManagementDataSo.DrinkTasteMateria, RecipeType.DrinkRecipe => restaurantManagementDataSo.DrinkTasteMaterial,
_ => throw new ArgumentOutOfRangeException() _ => throw new ArgumentOutOfRangeException()
}; };

View File

@ -103,7 +103,7 @@ private void InitializeViews()
_checklistView.Initalize(); _checklistView.Initalize();
_inventoryView.Initialize(); _inventoryView.Initialize();
_itemDetailView.Initialize(); _itemDetailView.Initialize();
_todayMenuView.Initialize(); _todayMenuView.Initialize(_viewModel);
_todayRestaurantStateView.Initialize(); _todayRestaurantStateView.Initialize();
} }

View File

@ -1,62 +1,27 @@
using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
namespace DDD namespace DDD
{ {
/// <summary>
/// 레스토랑 관리 UI의 ViewModel
/// 기존 RestaurantManagementUi의 상태 관리와 비즈니스 로직을 담당
/// </summary>
public class RestaurantManagementViewModel : SimpleViewModel, IEventHandler<TodayMenuRemovedEvent> public class RestaurantManagementViewModel : SimpleViewModel, IEventHandler<TodayMenuRemovedEvent>
{ {
// 홀드 진행 상태 관리 private List<ItemSlotUi> _foodSlots;
[SerializeField] private float _holdCompleteTime = 1f; private List<ItemSlotUi> _drinkSlots;
private bool _isHolding;
private float _holdProgress; // View에서 구독할 이벤트들
public float HoldProgress public System.Action OnBatchCompleted;
{ public System.Action OnChecklistFailed;
get => _holdProgress; public System.Action OnMenuSectionSelected;
private set public System.Action OnCookwareSectionSelected;
{ public System.Action<InventoryCategoryType> OnCategoryChanged;
if (SetField(ref _holdProgress, value)) public System.Action<int> OnTabMoved;
{ public System.Action OnInteractRequested;
OnPropertyChanged(nameof(NormalizedHoldProgress)); public System.Action OnCloseRequested;
} public System.Action<InventoryCategoryType> OnMenuCategorySelected;
}
}
/// <summary> private RestaurantManagementData GetRestaurantManagementData() => RestaurantData.Instance.ManagementData;
/// 홀드 진행률을 0~1 범위로 변환한 값 private RestaurantManagementState GetRestaurantManagementState() => RestaurantState.Instance.ManagementState;
/// </summary>
public float NormalizedHoldProgress => _holdCompleteTime <= 0f ? 0f : Mathf.Clamp01(_holdProgress / _holdCompleteTime);
// 탭 상태 관리
private SectionButtonType _currentSection = SectionButtonType.Menu;
private InventoryCategoryType _currentCategory = InventoryCategoryType.Food;
/// <summary>
/// 현재 선택된 섹션
/// </summary>
public SectionButtonType CurrentSection
{
get => _currentSection;
set => SetField(ref _currentSection, value);
}
/// <summary>
/// 현재 선택된 카테고리
/// </summary>
public InventoryCategoryType CurrentCategory
{
get => _currentCategory;
set => SetField(ref _currentCategory, value);
}
/// <summary>
/// 배치 완료 가능 여부 (체크리스트 완료 상태)
/// </summary>
public bool CanCompleteBatch => RestaurantState.Instance.ManagementState.GetChecklistStates().All(state => state);
public override void Initialize() public override void Initialize()
{ {
@ -81,14 +46,47 @@ private void UnregisterEvents()
EventBus.Unregister<TodayMenuRemovedEvent>(this); EventBus.Unregister<TodayMenuRemovedEvent>(this);
} }
/// <summary> public void InteractWithSelected()
/// 홀드 진행 업데이트 (View에서 Update마다 호출) {
/// </summary> OnInteractRequested?.Invoke();
}
public void CloseUi()
{
OnCloseRequested?.Invoke();
}
public void Invoke(TodayMenuRemovedEvent evt)
{
SetCategory(evt.InventoryCategoryType);
OnMenuCategorySelected?.Invoke(evt.InventoryCategoryType);
}
#region RestaurantManagementView
private bool _isHolding;
private float _holdProgress;
public float HoldProgress
{
get => _holdProgress;
private set
{
if (SetField(ref _holdProgress, value))
{
OnPropertyChanged(nameof(NormalizedHoldProgress));
}
}
}
public float NormalizedHoldProgress => GetRestaurantManagementData().HoldCompleteTime <= 0f ? 0f : Mathf.Clamp01(_holdProgress / GetRestaurantManagementData().HoldCompleteTime);
public bool CanCompleteBatch => GetRestaurantManagementState().GetChecklistStates().All(state => state);
public void UpdateHoldProgress() public void UpdateHoldProgress()
{ {
if (_isHolding == false) return; if (_isHolding == false) return;
if (_holdCompleteTime <= 0f) if (GetRestaurantManagementData().HoldCompleteTime <= 0f)
{ {
ProcessCompleteBatch(); ProcessCompleteBatch();
return; return;
@ -97,24 +95,18 @@ public void UpdateHoldProgress()
var deltaTime = Time.deltaTime; var deltaTime = Time.deltaTime;
HoldProgress += deltaTime; HoldProgress += deltaTime;
if (HoldProgress >= _holdCompleteTime) if (HoldProgress >= GetRestaurantManagementData().HoldCompleteTime)
{ {
ProcessCompleteBatch(); ProcessCompleteBatch();
} }
} }
/// <summary>
/// 홀드 시작
/// </summary>
public void StartHold() public void StartHold()
{ {
_isHolding = true; _isHolding = true;
HoldProgress = 0f; HoldProgress = 0f;
} }
/// <summary>
/// 홀드 취소
/// </summary>
public void CancelHold() public void CancelHold()
{ {
ResetHoldState(); ResetHoldState();
@ -126,9 +118,7 @@ private void ResetHoldState()
HoldProgress = 0f; HoldProgress = 0f;
} }
/// <summary>
/// 배치 완료 처리
/// </summary>
private void ProcessCompleteBatch() private void ProcessCompleteBatch()
{ {
ResetHoldState(); ResetHoldState();
@ -145,9 +135,25 @@ private void ProcessCompleteBatch()
} }
} }
/// <summary> #endregion
/// 섹션 탭 선택 처리
/// </summary> #region TabGroup
// 탭 상태 관리
private SectionButtonType _currentSection = SectionButtonType.Menu;
public SectionButtonType CurrentSection
{
get => _currentSection;
set => SetField(ref _currentSection, value);
}
private InventoryCategoryType _currentCategory = InventoryCategoryType.Food;
public InventoryCategoryType CurrentCategory
{
get => _currentCategory;
set => SetField(ref _currentCategory, value);
}
public void SetSection(SectionButtonType section) public void SetSection(SectionButtonType section)
{ {
CurrentSection = section; CurrentSection = section;
@ -164,56 +170,90 @@ public void SetSection(SectionButtonType section)
} }
} }
/// <summary>
/// 카테고리 탭 선택 처리
/// </summary>
public void SetCategory(InventoryCategoryType category) public void SetCategory(InventoryCategoryType category)
{ {
CurrentCategory = category; CurrentCategory = category;
OnCategoryChanged?.Invoke(category); OnCategoryChanged?.Invoke(category);
} }
/// <summary>
/// 탭 이동 (이전/다음)
/// </summary>
public void MoveTab(int direction) public void MoveTab(int direction)
{ {
OnTabMoved?.Invoke(direction); OnTabMoved?.Invoke(direction);
} }
/// <summary> #endregion
/// 현재 선택된 UI 요소와 상호작용
/// </summary> #region TodayMenuView
public void InteractWithSelected()
public void CreateFoodSlot(Transform parent)
{ {
OnInteractRequested?.Invoke(); var foodMaxCount = GetRestaurantManagementData().MaxFoodCount;
_foodSlots = new List<ItemSlotUi>(foodMaxCount);
for (int i = 0; i < foodMaxCount; i++)
{
var instance = Instantiate(GetRestaurantManagementData().ItemSlotUiPrefab, parent);
var slot = instance.GetComponent<ItemSlotUi>();
slot.Initialize(null, new TodayMenuSlotUiStrategy(RecipeType.FoodRecipe));
var itemSlotInteractor = instance.GetComponent<ItemSlotInteractor>();
itemSlotInteractor.Initialize(TodayMenuEventType.Remove, new TodayMenuInteractorStrategy());
_foodSlots.Add(slot);
}
} }
/// <summary> public void CreateDrinkSlot(Transform parent)
/// UI 닫기
/// </summary>
public void CloseUi()
{ {
OnCloseRequested?.Invoke(); var drinkMaxCount = GetRestaurantManagementData().MaxDrinkCount;
_drinkSlots = new List<ItemSlotUi>(drinkMaxCount);
for (int i = 0; i < drinkMaxCount; i++)
{
var instance = Instantiate(GetRestaurantManagementData().ItemSlotUiPrefab, parent);
var slot = instance.GetComponent<ItemSlotUi>();
slot.Initialize(null, new TodayMenuSlotUiStrategy(RecipeType.FoodRecipe));
var itemSlotInteractor = instance.GetComponent<ItemSlotInteractor>();
itemSlotInteractor.Initialize(TodayMenuEventType.Remove, new TodayMenuInteractorStrategy());
_drinkSlots.Add(slot);
}
} }
// View에서 구독할 이벤트들 public void UpdateTodayMenuItems()
public System.Action OnBatchCompleted;
public System.Action OnChecklistFailed;
public System.Action OnMenuSectionSelected;
public System.Action OnCookwareSectionSelected;
public System.Action<InventoryCategoryType> OnCategoryChanged;
public System.Action<int> OnTabMoved;
public System.Action OnInteractRequested;
public System.Action OnCloseRequested;
// 이벤트 핸들러
public void Invoke(TodayMenuRemovedEvent evt)
{ {
SetCategory(evt.InventoryCategoryType); int foodIndex = 0;
OnMenuCategorySelected?.Invoke(evt.InventoryCategoryType); foreach (var foodRecipeIdCountPair in GetRestaurantManagementState().TodayFoodRecipeIds)
{
if (foodIndex >= _foodSlots.Count) break;
var model = ItemViewModelFactory.CreateByItemId(foodRecipeIdCountPair.Key);
var foodSlot = _foodSlots[foodIndex];
foodSlot.Initialize(model, new TodayMenuSlotUiStrategy(RecipeType.FoodRecipe));
foodSlot.Model.SetCount(foodRecipeIdCountPair.Value);
foodIndex++;
}
for (int i = foodIndex; i < _foodSlots.Count; i++)
{
_foodSlots[i].Initialize(null, new TodayMenuSlotUiStrategy(RecipeType.FoodRecipe));
}
int drinkIndex = 0;
foreach (var drinkRecipeIdCountPair in GetRestaurantManagementState().TodayDrinkRecipeIds)
{
if (drinkIndex >= _drinkSlots.Count) break;
var model = ItemViewModelFactory.CreateByItemId(drinkRecipeIdCountPair.Key);
var drinkSlot = _drinkSlots[drinkIndex];
drinkSlot.Initialize(model, new TodayMenuSlotUiStrategy(RecipeType.DrinkRecipe));
drinkSlot.Model.SetCount(drinkRecipeIdCountPair.Value);
drinkIndex++;
}
for (int i = drinkIndex; i < _drinkSlots.Count; i++)
{
_drinkSlots[i].Initialize(null, new TodayMenuSlotUiStrategy(RecipeType.DrinkRecipe));
}
} }
public System.Action<InventoryCategoryType> OnMenuCategorySelected; #endregion
} }
} }

View File

@ -1,5 +1,3 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine; using UnityEngine;
namespace DDD namespace DDD
@ -9,11 +7,7 @@ public class TodayMenuView : MonoBehaviour, IEventHandler<TodayMenuAddedEvent>,
[SerializeField] private Transform _todayFoodContent; [SerializeField] private Transform _todayFoodContent;
[SerializeField] private Transform _todayDrinkContent; [SerializeField] private Transform _todayDrinkContent;
private List<ItemSlotUi> _foodSlots; private RestaurantManagementViewModel _viewModel;
private List<ItemSlotUi> _drinkSlots;
private RestaurantManagementState restaurantManagementStateSo;
private RestaurantManagementData restaurantManagementDataSo;
private void OnDestroy() private void OnDestroy()
{ {
@ -21,46 +15,15 @@ private void OnDestroy()
EventBus.Unregister<TodayMenuRemovedEvent>(this); EventBus.Unregister<TodayMenuRemovedEvent>(this);
} }
public void Initialize() public void Initialize(RestaurantManagementViewModel viewModel)
{ {
restaurantManagementStateSo = RestaurantState.Instance.ManagementState; _viewModel = viewModel;
restaurantManagementDataSo = RestaurantData.Instance.ManagementData;
foreach (Transform child in _todayFoodContent) ClearObject(_todayFoodContent);
{ ClearObject(_todayDrinkContent);
Destroy(child.gameObject);
}
int maxFoodCount = restaurantManagementStateSo!.MaxFoodCount; _viewModel.CreateFoodSlot(_todayFoodContent);
_foodSlots = new List<ItemSlotUi>(maxFoodCount); _viewModel.CreateDrinkSlot(_todayDrinkContent);
for (int i = 0; i < restaurantManagementStateSo.MaxFoodCount; i++)
{
var go = Instantiate(restaurantManagementDataSo.ItemSlotUiPrefab, _todayFoodContent);
var slot = go.GetComponent<ItemSlotUi>();
slot.Initialize(null, new TodayMenuSlotUiStrategy(RecipeType.FoodRecipe));
var itemSlotInteractor = go.GetComponent<ItemSlotInteractor>();
itemSlotInteractor.Initialize(TodayMenuEventType.Remove, new TodayMenuInteractorStrategy());
_foodSlots.Add(slot);
}
foreach (Transform child in _todayDrinkContent)
{
Destroy(child.gameObject);
}
int maxDrinkCount = restaurantManagementStateSo.MaxDrinkCount;
_drinkSlots = new List<ItemSlotUi>(maxDrinkCount);
for (int i = 0; i < restaurantManagementStateSo.MaxDrinkCount; i++)
{
var go = Instantiate(restaurantManagementDataSo.ItemSlotUiPrefab, _todayDrinkContent);
var slot = go.GetComponent<ItemSlotUi>();
slot.Initialize(null, new TodayMenuSlotUiStrategy(RecipeType.DrinkRecipe));
var itemSlotInteractor = go.GetComponent<ItemSlotInteractor>();
itemSlotInteractor.Initialize(TodayMenuEventType.Remove, new TodayMenuInteractorStrategy());
_drinkSlots.Add(slot);
}
UpdateView(); UpdateView();
@ -68,6 +31,14 @@ public void Initialize()
EventBus.Register<TodayMenuRemovedEvent>(this); EventBus.Register<TodayMenuRemovedEvent>(this);
} }
private void ClearObject(Transform root)
{
foreach (Transform child in root)
{
Destroy(child.gameObject);
}
}
public void Invoke(TodayMenuAddedEvent evt) public void Invoke(TodayMenuAddedEvent evt)
{ {
UpdateView(); UpdateView();
@ -80,39 +51,7 @@ public void Invoke(TodayMenuRemovedEvent evt)
private void UpdateView() private void UpdateView()
{ {
int foodIndex = 0; _viewModel.UpdateTodayMenuItems();
foreach (var foodRecipeIdCountPair in restaurantManagementStateSo.TodayFoodRecipeIds)
{
if (foodIndex >= _foodSlots.Count) break;
var model = ItemViewModelFactory.CreateByItemId(foodRecipeIdCountPair.Key);
var foodSlot = _foodSlots[foodIndex];
foodSlot.Initialize(model, new TodayMenuSlotUiStrategy(RecipeType.FoodRecipe));
foodSlot.Model.SetCount(foodRecipeIdCountPair.Value);
foodIndex++;
}
for (int i = foodIndex; i < _foodSlots.Count; i++)
{
_foodSlots[i].Initialize(null, new TodayMenuSlotUiStrategy(RecipeType.FoodRecipe));
}
int drinkIndex = 0;
foreach (var drinkRecipeIdCountPair in restaurantManagementStateSo.TodayDrinkRecipeIds)
{
if (drinkIndex >= _drinkSlots.Count) break;
var model = ItemViewModelFactory.CreateByItemId(drinkRecipeIdCountPair.Key);
var drinkSlot = _drinkSlots[drinkIndex];
drinkSlot.Initialize(model, new TodayMenuSlotUiStrategy(RecipeType.DrinkRecipe));
drinkSlot.Model.SetCount(drinkRecipeIdCountPair.Value);
drinkIndex++;
}
for (int i = drinkIndex; i < _drinkSlots.Count; i++)
{
_drinkSlots[i].Initialize(null, new TodayMenuSlotUiStrategy(RecipeType.DrinkRecipe));
}
} }
} }
} }

View File

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine; using UnityEngine;
namespace DDD namespace DDD
@ -31,9 +30,9 @@ public void Initialize()
Destroy(child.gameObject); Destroy(child.gameObject);
} }
int maxCookwareCount = restaurantManagementStateSo!.MaxCookwareCount; int maxCookwareCount = restaurantManagementDataSo!.MaxCookwareCount;
_workerSlots = new List<ItemSlotUi>(maxCookwareCount); _workerSlots = new List<ItemSlotUi>(maxCookwareCount);
for (int i = 0; i < restaurantManagementStateSo.MaxCookwareCount; i++) for (int i = 0; i < restaurantManagementDataSo.MaxCookwareCount; i++)
{ {
var go = Instantiate(restaurantManagementDataSo.ItemSlotUiPrefab, _todayWorkerContent); var go = Instantiate(restaurantManagementDataSo.ItemSlotUiPrefab, _todayWorkerContent);
var slot = go.GetComponent<ItemSlotUi>(); var slot = go.GetComponent<ItemSlotUi>();
@ -50,7 +49,7 @@ public void Initialize()
} }
_cookwareSlots = new List<ItemSlotUi>(maxCookwareCount); _cookwareSlots = new List<ItemSlotUi>(maxCookwareCount);
for (int i = 0; i < restaurantManagementStateSo.MaxCookwareCount; i++) for (int i = 0; i < restaurantManagementDataSo.MaxCookwareCount; i++)
{ {
var go = Instantiate(restaurantManagementDataSo.ItemSlotUiPrefab, _todayCookwareContent); var go = Instantiate(restaurantManagementDataSo.ItemSlotUiPrefab, _todayCookwareContent);
var slot = go.GetComponent<ItemSlotUi>(); var slot = go.GetComponent<ItemSlotUi>();

View File

@ -6,6 +6,7 @@ namespace DDD
{ {
public class BaseUiActionsInputBinding<T> : ScriptableObject where T : Enum public class BaseUiActionsInputBinding<T> : ScriptableObject where T : Enum
{ {
[ReadOnly]
public InputActionMaps InputActionMaps; public InputActionMaps InputActionMaps;
[EnumToggleButtons] [EnumToggleButtons]

View File

@ -3,5 +3,11 @@
namespace DDD namespace DDD
{ {
[CreateAssetMenu(fileName = "_UiActionsInputBinding", menuName = "Ui/RestaurantActions_InputBindingSo")] [CreateAssetMenu(fileName = "_UiActionsInputBinding", menuName = "Ui/RestaurantActions_InputBindingSo")]
public class RestaurantActionsInputBinding : BaseUiActionsInputBinding<RestaurantActions> { } public class RestaurantActionsInputBinding : BaseUiActionsInputBinding<RestaurantActions>
{
private void OnEnable()
{
InputActionMaps = InputActionMaps.Restaurant;
}
}
} }

View File

@ -3,5 +3,11 @@
namespace DDD namespace DDD
{ {
[CreateAssetMenu(fileName = "_UiActionsInputBinding", menuName = "Ui/RestaurantUiActions_InputBindingSo")] [CreateAssetMenu(fileName = "_UiActionsInputBinding", menuName = "Ui/RestaurantUiActions_InputBindingSo")]
public class RestaurantUiActionsInputBinding : BaseUiActionsInputBinding<RestaurantUiActions> { } public class RestaurantUiActionsInputBinding : BaseUiActionsInputBinding<RestaurantUiActions>
{
private void OnEnable()
{
InputActionMaps = InputActionMaps.RestaurantUi;
}
}
} }

View File

@ -1,3 +1,4 @@
using Sirenix.OdinInspector;
using UnityEngine; using UnityEngine;
namespace DDD namespace DDD
@ -5,11 +6,24 @@ namespace DDD
[CreateAssetMenu(fileName = "RestaurantManagementData", menuName = "RestaurantData/RestaurantManagementData")] [CreateAssetMenu(fileName = "RestaurantManagementData", menuName = "RestaurantData/RestaurantManagementData")]
public class RestaurantManagementData : ScriptableObject public class RestaurantManagementData : ScriptableObject
{ {
public float HoldCompleteTime = 1f;
[Title("오늘의 레스토랑 상태")]
public int MaxFoodCount = 8;
public int MaxDrinkCount = 6;
public int MaxCookwareCount = 6;
[Title("체크리스트 조건")]
public int ChecklistFoodCount = 1;
public int ChecklistCookwareCount = 1;
public int ChecklistMatchedMenuWithCookwareCount = 1;
[Title("컴포넌트")]
public ItemSlotUi ItemSlotUiPrefab; public ItemSlotUi ItemSlotUiPrefab;
public TasteHashTagSlotUi TasteHashTagSlotUiPrefab; public TasteHashTagSlotUi TasteHashTagSlotUiPrefab;
public Material FoodTasteMaterial; public Material FoodTasteMaterial;
public Material DrinkTasteMateria; public Material DrinkTasteMaterial;
public RuntimeAnimatorController TodayMenuSlotUiAnimatorController; public RuntimeAnimatorController TodayMenuSlotUiAnimatorController;
public RuntimeAnimatorController InventorySlotUiAnimatorController; public RuntimeAnimatorController InventorySlotUiAnimatorController;

View File

@ -7,23 +7,11 @@ namespace DDD
{ {
public class RestaurantManagementState : ScriptableObject public class RestaurantManagementState : ScriptableObject
{ {
// TODO : 데이터에서 초기화하고, 동적으로 변경 private bool _isOpenable;
[Title("오늘의 레스토랑 상태")] private Dictionary<string, int> _todayFoodRecipeIds = new();
public int MaxFoodCount = 8; private Dictionary<string, int> _todayDrinkRecipeIds = new();
public int MaxDrinkCount = 6; private List<string> _todayWorkerIds = new();
public int MaxCookwareCount = 6; private Dictionary<string, HashSet<string>> _cookwareToRecipeIds = new();
[Title("체크리스트 조건")]
public int ChecklistFoodCount = 1;
public int ChecklistCookwareCount = 1;
public int ChecklistMatchedMenuWithCookwareCount = 1;
[Title("실시간 데이터")]
[ReadOnly, SerializeField] private bool _isOpenable;
[ReadOnly, ShowInInspector] private Dictionary<string, int> _todayFoodRecipeIds = new();
[ReadOnly, ShowInInspector] private Dictionary<string, int> _todayDrinkRecipeIds = new();
[ReadOnly, ShowInInspector] private List<string> _todayWorkerIds = 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;
@ -37,6 +25,8 @@ public class RestaurantManagementState : ScriptableObject
public int AddedTodayCookwareCount => _cookwareToRecipeIds.Count; public int AddedTodayCookwareCount => _cookwareToRecipeIds.Count;
public int MatchedTodayMenuWithCookwareCount => _cookwareToRecipeIds.Values.Count(recipeSet => recipeSet.Count > 0); public int MatchedTodayMenuWithCookwareCount => _cookwareToRecipeIds.Values.Count(recipeSet => recipeSet.Count > 0);
private RestaurantManagementData GetRestaurantManagementData() => RestaurantData.Instance.ManagementData;
public void InitializeReadyForRestaurant() public void InitializeReadyForRestaurant()
{ {
// TODO : Load from disk if possible (save data) // TODO : Load from disk if possible (save data)
@ -101,7 +91,7 @@ public bool TryAddTodayMenu(ItemViewModel model)
if (recipeData.RecipeType == RecipeType.FoodRecipe) if (recipeData.RecipeType == RecipeType.FoodRecipe)
{ {
if (_todayFoodRecipeIds.Count >= MaxFoodCount || _todayFoodRecipeIds.ContainsKey(recipeId)) return false; if (_todayFoodRecipeIds.Count >= GetRestaurantManagementData().MaxFoodCount || _todayFoodRecipeIds.ContainsKey(recipeId)) return false;
var foodData = DataManager.Instance.GetDataSo<FoodDataSo>().GetDataById(recipeData.RecipeResult); var foodData = DataManager.Instance.GetDataSo<FoodDataSo>().GetDataById(recipeData.RecipeResult);
var craftableCount = foodData.GetCraftableCount(); var craftableCount = foodData.GetCraftableCount();
@ -112,7 +102,7 @@ public bool TryAddTodayMenu(ItemViewModel model)
} }
else if (recipeData.RecipeType == RecipeType.DrinkRecipe) else if (recipeData.RecipeType == RecipeType.DrinkRecipe)
{ {
if (_todayDrinkRecipeIds.Count >= MaxDrinkCount || _todayDrinkRecipeIds.ContainsKey(recipeId)) return false; if (_todayDrinkRecipeIds.Count >= GetRestaurantManagementData().MaxDrinkCount || _todayDrinkRecipeIds.ContainsKey(recipeId)) return false;
var drinkData = DataManager.Instance.GetDataSo<DrinkDataSo>().GetDataById(recipeData.RecipeResult); var drinkData = DataManager.Instance.GetDataSo<DrinkDataSo>().GetDataById(recipeData.RecipeResult);
var craftableCount = drinkData.GetCraftableCount(); var craftableCount = drinkData.GetCraftableCount();
@ -201,7 +191,7 @@ public bool TryAddTodayCookware(ItemViewModel model)
if (model.HasItem == false || DataManager.Instance.GetDataSo<CookwareDataSo>().ContainsData(cookwareId) == false) return false; if (model.HasItem == false || DataManager.Instance.GetDataSo<CookwareDataSo>().ContainsData(cookwareId) == false) return false;
if (_cookwareToRecipeIds.Count >= MaxCookwareCount || _cookwareToRecipeIds.ContainsKey(cookwareId)) return false; if (_cookwareToRecipeIds.Count >= GetRestaurantManagementData().MaxCookwareCount || _cookwareToRecipeIds.ContainsKey(cookwareId)) return false;
_cookwareToRecipeIds[cookwareId] = new HashSet<string>(); _cookwareToRecipeIds[cookwareId] = new HashSet<string>();