CapersProject/Assets/02.Scripts/DDD/Ui/Tycoon/MealKitUi.cs
2025-02-18 06:47:56 +09:00

277 lines
9.4 KiB
C#

using System.Collections.Generic;
using System.Linq;
using DDD.ScriptableObjects;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.UI;
namespace DDD.Uis.Tycoon
{
public class MealKitUi : PopupUi
{
[Title("프리팹")]
[SerializeField]
private MealKitButton _mealKitButtonPrefab;
[Title("컴포넌트")]
[SerializeField]
private GameObject _panel;
[SerializeField]
private GameObject _mealKitsLocation;
[Title("클래스")]
[SerializeField]
private UiEventsController _uiEventsController;
[Title("데이터")]
[SerializeField]
private int _maxMealKitCount = 6;
[Title("실시간 데이터")]
[SerializeField]
private List<MealKitButton> _mealKitButtons;
private InputAction _interactionEAction;
private InputAction _cancelAction;
private InputAction _pressFAction;
private void Awake()
{
// 더미 데이터 삭제
foreach (Transform element in _mealKitsLocation.transform)
{
if (element)
{
Destroy(element.gameObject);
}
}
}
private void Start()
{
EventManager.OnAddedMealKit += SetTodayMenus;
_interactionEAction =
PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.InteractionE);
_cancelAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.Cancel);
_pressFAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.PressF);
_mealKitButtons = new List<MealKitButton>(_maxMealKitCount);
for (int i = 0; i < _maxMealKitCount; i++)
{
MealKitButton mealKitButton = Instantiate(_mealKitButtonPrefab, _mealKitsLocation.transform);
mealKitButton.RegisterButtonListener(() => OnClickedMealKit(mealKitButton));
_mealKitButtons.Add(mealKitButton);
}
_panel.SetActive(false);
}
private void OnDestroy()
{
EventManager.OnAddedMealKit -= SetTodayMenus;
}
private void OnClickedMealKit(MealKitButton mealKitButton)
{
if (mealKitButton.CanInteraction())
{
CraftRecipeData newCraftRecipeData = new CraftRecipeData(mealKitButton.CraftRecipeData);
EventManager.InvokePickupMealKit(newCraftRecipeData);
mealKitButton.PickupMealKit();
Close();
}
}
public bool CanOpen()
{
return _mealKitButtons.Any(mealKitButton => mealKitButton.CanInteraction());
}
public override void Open()
{
base.Open();
_panel.SetActive(true);
PlayerInputKeyManager.Instance.SwitchCurrentActionMap(InputActionMaps.TycoonUi);
SortMealKitButtons();
_uiEventsController.SetSelectObject(_mealKitButtons[0].gameObject);
EventSystem.current.SetSelectedGameObject(_uiEventsController.SelectObject);
}
public void OnClose(InputAction.CallbackContext context)
{
Close();
}
public override void Close()
{
_panel.SetActive(false);
base.Close();
if (PopupUiController.IsPopupListEmpty() || !PopupUiController.IsPausedPopupList())
{
PlayerInputKeyManager.Instance.SwitchCurrentActionMap(InputActionMaps.Tycoon);
}
}
public override void EnableInput()
{
_interactionEAction.performed += OnInteractionE;
_cancelAction.performed += OnClose;
_pressFAction.performed += OnClose;
_uiEventsController.EnableAutoNavigate();
}
public override void DisableInput()
{
_interactionEAction.performed -= OnInteractionE;
_cancelAction.performed -= OnClose;
_pressFAction.performed -= OnClose;
_uiEventsController.DisableAutoNavigate();
}
private void OnInteractionE(InputAction.CallbackContext context)
{
if (!EventSystem.current) return;
EventSystem.current.currentSelectedGameObject.GetComponent<Button>()?.onClick.Invoke();
}
private void SetTodayMenus(List<TodayMenu> todayMenus)
{
for (int i = 0; i < _maxMealKitCount; i++)
{
_mealKitButtons[i].SetMealKit(todayMenus[i].AddedCraftRecipeData, todayMenus[i].AddedCount);
if (todayMenus[i].AddedCraftRecipeData == null)
{
_mealKitButtons[i].HideUi();
}
else
{
_mealKitButtons[i].ShowUi();
}
}
}
private void SortMealKitButtons()
{
// 1) 임시 리스트에 인터랙션 가능한 버튼만 먼저 담는다(Stable).
List<MealKitButton> sortedList = new List<MealKitButton>(_mealKitButtons.Count);
foreach (var mealKitButton in _mealKitButtons)
{
if (mealKitButton.CanInteraction())
{
sortedList.Add(mealKitButton);
}
}
// 2) 그 다음 인터랙션 불가능한 버튼들을 뒤에 붙인다.
foreach (var mealKitButton in _mealKitButtons)
{
if (!mealKitButton.CanInteraction())
{
sortedList.Add(mealKitButton);
}
}
// 3) 재배치한 리스트를 원본 리스트에 반영
_mealKitButtons = sortedList;
// 4) 실제 UI 계층(트랜스폼) 순서도 변경하여 GridLayoutGroup이 의도한 순서로 그리도록 설정
for (int i = 0; i < _mealKitButtons.Count; i++)
{
// i번째 순서대로 형제 인덱스(Sibling Index)를 지정
_mealKitButtons[i].transform.SetSiblingIndex(i);
}
// 5) 정렬 이후, 내비게이션도 재설정 (정렬 순서가 바뀌었으므로)
SetNavigationMealKitButtons();
}
private bool IsButtonValid(MealKitButton mealKitButton)
{
return mealKitButton != null
&& mealKitButton.gameObject.activeInHierarchy
&& mealKitButton.Button != null
&& mealKitButton.Button.interactable;
}
private void SetNavigationMealKitButtons()
{
int columnCount = 3;
int count = _mealKitButtons.Count;
for (int i = 0; i < count; i++)
{
MealKitButton currentMealKit = _mealKitButtons[i];
Button currentButton = currentMealKit.Button;
// 새로운 Navigation 객체 생성 및 Explicit 모드 설정
Navigation nav = new Navigation { mode = Navigation.Mode.Explicit };
// 현재 버튼이 비활성(혹은 인터랙션 불가능)하면 내비게이션 항목은 모두 null 처리
if (!IsButtonValid(currentMealKit))
{
currentButton.navigation = nav; // 모든 방향 null
continue;
}
// 상(Up) 이웃 버튼: 인덱스 i - columnCount
int upIndex = i - columnCount;
if (upIndex >= 0 && IsButtonValid(_mealKitButtons[upIndex]))
{
nav.selectOnUp = _mealKitButtons[upIndex].Button;
}
else
{
nav.selectOnUp = null;
}
// 하(Down) 이웃 버튼: 인덱스 i + columnCount
int downIndex = i + columnCount;
if (downIndex < count && IsButtonValid(_mealKitButtons[downIndex]))
{
nav.selectOnDown = _mealKitButtons[downIndex].Button;
}
else
{
nav.selectOnDown = null;
}
// 좌(Left) 이웃 버튼: 인덱스 i - 1 (같은 행인지 체크)
int leftIndex = i - 1;
if (leftIndex >= 0
&& (i / columnCount == leftIndex / columnCount)
&& IsButtonValid(_mealKitButtons[leftIndex]))
{
nav.selectOnLeft = _mealKitButtons[leftIndex].Button;
}
else
{
nav.selectOnLeft = null;
}
// 우(Right) 이웃 버튼: 인덱스 i + 1 (같은 행인지 체크)
int rightIndex = i + 1;
if (rightIndex < count
&& (i / columnCount == rightIndex / columnCount)
&& IsButtonValid(_mealKitButtons[rightIndex]))
{
nav.selectOnRight = _mealKitButtons[rightIndex].Button;
}
else
{
nav.selectOnRight = null;
}
// 최종 Navigation 할당
currentButton.navigation = nav;
}
}
}
}