using System.Collections.Generic; using System.Threading.Tasks; using DDD.ScriptableObjects; using DDD.Utility; using DG.Tweening; using Sirenix.OdinInspector; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; using UnityEngine.UI; namespace DDD.Uis.Tycoon { public class AddMenuUi : PopupUi { [Title("프리팹")] [SerializeField] private MenuHashTag _menuHashTagPrefab; [SerializeField] private SelectedCraftRecipeIngredient _selectedCraftRecipeIngredientPrefab; [Title("컴포넌트")] [SerializeField] private GameObject _panel; [SerializeField] private RectTransform _panelRect; [SerializeField] private Image _menuButtonImage; [SerializeField] private Button _menuButton; [SerializeField] private GameObject _emptyPanel; [SerializeField] private GameObject _addedPanel; [SerializeField] private Button _decreaseButton; [SerializeField] private TMP_Text _countText; [SerializeField] private Button _increaseButton; [SerializeField] private TMP_Text _nameText; [SerializeField] private TMP_Text _descriptionText; [SerializeField] private GameObject _menuHashTagsPanel; [SerializeField] private GameObject _selectedCraftRecipeIngredientsPanel; [Title("클래스")] [SerializeField] private CraftRecipeUi _craftRecipeUi; [Title("데이터")] [SerializeField] private int _maxHashTagCount = 3; [SerializeField] private int _maxIngredientCount = 3; [Title("연출")] [SerializeField] private Vector2 _panelScale = new(0f, 1f); [SerializeField] private float _duration = 0.3f; [SerializeField] private Ease _ease = Ease.InQuint; [Title("데이터")] [SerializeField] private Sprite _emptySprite; [Title("실시간 데이터")] [SerializeField, DisableIf("@true")] private bool _isAddedMenu; public bool IsAddedMenu { get => _isAddedMenu; private set { _isAddedMenu = value; if (_isAddedMenu) { _emptyPanel.SetActive(false); _addedPanel.SetActive(true); for (int i = 0; i < 3; i++) { if (i < AddedCraftRecipeData.ValidIngredients.Count) { _selectedCraftRecipeIngredients[i].UpdateIngredients(AddedCraftRecipeData.ValidIngredients[i]); _selectedCraftRecipeIngredients[i].ShowUi(); if (!_selectedCraftRecipeIngredients[i].IsCraftable) { IsCraftable = false; } } else { _selectedCraftRecipeIngredients[i].HideUi(); } } } else { _menuButtonImage.sprite = _emptySprite; _emptyPanel.SetActive(true); _addedPanel.SetActive(false); for (int i = 0; i < 3; i++) { _selectedCraftRecipeIngredients[i].HideUi(); } } } } [field: SerializeField] public bool IsCraftable { get; private set; } [SerializeField] private List _menuHashTags; [SerializeField] private List _selectedCraftRecipeIngredients; public CraftRecipeData AddedCraftRecipeData { get; private set; } public int AddedCount { get; private set; } public Tween OpenTween { get; private set; } public Tween CloseTween { get; private set; } private TodayMenu _currentTodayMenu; private Sequence _closeSequence; private InputAction _interactionEAction; private InputAction _cancelAction; private InputAction _pressFAction; private InputAction _pressQAction; private InputAction _pressRAction; private int _maxCraftingCount; private void Awake() { foreach (Transform element in _menuHashTagsPanel.transform) { if (element) { Destroy(element.gameObject); } } foreach (Transform element in _selectedCraftRecipeIngredientsPanel.transform) { if (element) { Destroy(element.gameObject); } } _craftRecipeUi = FindAnyObjectByType(); OpenTween = _panelRect.DOScaleY(_panelScale.y, _duration) .From(_panelScale.x) .SetEase(_ease) .SetAutoKill(false) .Pause(); CloseTween = _panelRect.DOScaleY(_panelScale.x, _duration) .From(_panelScale.y) .SetEase(_ease) .OnComplete(() => { _panel.SetActive(false); base.Close(); _currentTodayMenu = null; }) .SetAutoKill(false) .Pause(); } private void Start() { _interactionEAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.InteractionE); _cancelAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.Cancel); _pressFAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.PressF); _pressQAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.PressQ); _pressRAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.PressR); _menuHashTags = new List(_maxHashTagCount); for (int i = 0; i < _maxHashTagCount; i++) { MenuHashTag menuHashTag = Instantiate(_menuHashTagPrefab, _menuHashTagsPanel.transform); menuHashTag.HideUi(); _menuHashTags.Add(menuHashTag); } _selectedCraftRecipeIngredients = new List(_maxIngredientCount); for (int i = 0; i < _maxHashTagCount; i++) { SelectedCraftRecipeIngredient selectedCraftRecipeIngredient = Instantiate(_selectedCraftRecipeIngredientPrefab, _selectedCraftRecipeIngredientsPanel.transform); selectedCraftRecipeIngredient.HideUi(); _selectedCraftRecipeIngredients.Add(selectedCraftRecipeIngredient); } _menuButton.onClick.AddListener(OnClickEmptyButton); _decreaseButton.onClick.AddListener(DecreaseButton); _increaseButton.onClick.AddListener(IncreaseButton); _craftRecipeUi.SetSelectRecipeAction(SelectCraftRecipe); _panel.transform.localScale = new Vector3(1f, 0f, 1f); _panel.SetActive(false); } private void OnDestroy() { OpenTween?.Kill(); CloseTween?.Kill(); _closeSequence?.Kill(); _interactionEAction = null; _cancelAction = null; _pressFAction = null; _pressQAction = null; _pressRAction = null; } public override void Open() { AddedCount = 1; if (_currentTodayMenu.IsAddedMenu) { AddedCraftRecipeData = _currentTodayMenu.AddedCraftRecipeData; SelectCraftRecipe(); } else { AddedCraftRecipeData = null; } IsAddedMenu = _currentTodayMenu.IsAddedMenu; base.Open(); _panel.SetActive(true); } public void OnClose(InputAction.CallbackContext context) { Close(); } public override void Close() { _closeSequence?.Restart(); } public override void EnableInput() { _interactionEAction.performed += OnInteractionE; _cancelAction.performed += OnClose; _pressFAction.performed += OnClose; _pressQAction.performed += OnDecreaseButton; _pressRAction.performed += OnIncreaseButton; } public override void DisableInput() { _interactionEAction.performed -= OnInteractionE; _cancelAction.performed -= OnClose; _pressFAction.performed -= OnClose; _pressQAction.performed -= OnDecreaseButton; _pressRAction.performed -= OnIncreaseButton; } private void OnInteractionE(InputAction.CallbackContext context) { if (IsAddedMenu) { // 메뉴 등록 if (IsCraftable) { UseIngredients(); _currentTodayMenu.AddMenu(AddedCraftRecipeData, AddedCount); Close(); } } else { // 레시피 선택 _menuButton.onClick.Invoke(); } } public void OnClickEmptyButton() { _craftRecipeUi.Open(); } public void SelectCraftRecipe() { if (AddedCraftRecipeData == null) { AddedCraftRecipeData = _craftRecipeUi.CurrentCraftRecipeButton.CraftRecipeData; } IsCraftable = true; for (int i = 0; i < 3; i++) { if (i < AddedCraftRecipeData.ValidIngredients.Count) { _selectedCraftRecipeIngredients[i].UpdateIngredients(AddedCraftRecipeData.ValidIngredients[i]); _selectedCraftRecipeIngredients[i].ShowUi(); if (!_selectedCraftRecipeIngredients[i].IsCraftable) { IsCraftable = false; } } else { _selectedCraftRecipeIngredients[i].HideUi(); } } _maxCraftingCount = int.MaxValue; foreach (CraftingIngredient craftingIngredient in AddedCraftRecipeData.ValidIngredients) { string ingredientIdx = craftingIngredient.Idx; int requiredCount = craftingIngredient.Count; int inventoryCount = DataManager.Instance.Inventory.GetItemByIdx(ingredientIdx)?.Count ?? 0; int craftingCount = inventoryCount / requiredCount; if (_maxCraftingCount > craftingCount) { _maxCraftingCount = craftingCount; } } _menuButtonImage.sprite = AddedCraftRecipeData.Sprite; _nameText.text = AddedCraftRecipeData.Name; _descriptionText.text = Utils.GetLocalizedString(AddedCraftRecipeData.Description); _countText.text = $"{AddedCount}/{_maxCraftingCount}"; int validHashTagCount = AddedCraftRecipeData.ValidHashTags.Count; for (int i = 0; i < _maxHashTagCount; i++) { if (i >= validHashTagCount) { _menuHashTags[i].HideUi(); continue; } _menuHashTags[i].SetTag(AddedCraftRecipeData.ValidHashTags[i]); _menuHashTags[i].ShowUi(); } IsAddedMenu = true; } private void OnDecreaseButton(InputAction.CallbackContext context) { if (!IsAddedMenu) return; DecreaseButton(); } public async void DecreaseButton() { PointerEventData pointerData = new PointerEventData(EventSystem.current); ExecuteEvents.Execute(_decreaseButton.gameObject, pointerData, ExecuteEvents.pointerDownHandler); await Task.Delay(100); ExecuteEvents.Execute(_decreaseButton.gameObject, pointerData, ExecuteEvents.pointerUpHandler); if (AddedCount <= 1) return; AddedCount--; _countText.text = $"{AddedCount}/{_maxCraftingCount}"; for (int i = 0; i < AddedCraftRecipeData.ValidIngredients.Count; i++) { _selectedCraftRecipeIngredients[i].UpdateCraftableCount(AddedCount); } } private void OnIncreaseButton(InputAction.CallbackContext context) { if (!IsAddedMenu) return; IncreaseButton(); } public async void IncreaseButton() { PointerEventData pointerData = new PointerEventData(EventSystem.current); ExecuteEvents.Execute(_increaseButton.gameObject, pointerData, ExecuteEvents.pointerDownHandler); await Task.Delay(100); ExecuteEvents.Execute(_increaseButton.gameObject, pointerData, ExecuteEvents.pointerUpHandler); if (AddedCraftRecipeData == null) return; int newCount = AddedCount + 1; foreach (var ingredient in AddedCraftRecipeData.ValidIngredients) { var slot = DataManager.Instance.Inventory.GetItemByIdx(ingredient.Idx); int available = slot != null ? slot.Count : 0; if (available < newCount * ingredient.Count) return; } AddedCount = newCount; _countText.text = $"{AddedCount}/{_maxCraftingCount}"; for (int i = 0; i < AddedCraftRecipeData.ValidIngredients.Count; i++) { _selectedCraftRecipeIngredients[i].UpdateCraftableCount(AddedCount); } } public void UseIngredients() { if (AddedCraftRecipeData == null) { Debug.LogWarning("현재 선택된 레시피가 없습니다."); return; } foreach (var ingredient in AddedCraftRecipeData.ValidIngredients) { var slot = DataManager.Instance.Inventory.GetItemByIdx(ingredient.Idx); DataManager.Instance.Inventory.RemoveItem(slot, AddedCount * ingredient.Count); } Close(); } public void RestoreIngredients() { foreach (CraftingIngredient craftingIngredient in AddedCraftRecipeData.ValidIngredients) { InventoryItemSlot newSlot = new InventoryItemSlot(craftingIngredient.Idx, AddedCount * craftingIngredient.Count); DataManager.Instance.Inventory.AddItem(newSlot); } } public void SetCloseSequence(Sequence closeSequence) => _closeSequence = closeSequence; public void SetCurrentTodayMenu(TodayMenu todayMenu) => _currentTodayMenu = todayMenu; } }