CapersProject/Assets/02.Scripts/Ui/Tycoon/TycoonTutorial.cs
2024-12-17 20:25:53 +09:00

321 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
namespace BlueWater
{
public static class TutorialName
{
public const string TutorialA = "TutorialA";
public const string TutorialB = "TutorialB";
public const string TutorialC = "TutorialC";
public const string TutorialD = "TutorialD";
public const string TutorialE = "TutorialE";
public const string TutorialF = "TutorialF";
public const string TutorialG = "TutorialG";
public const string TutorialH = "TutorialH";
public const string TutorialI = "TutorialI";
public const string TutorialJ = "TutorialJ";
}
public class TycoonTutorial : MonoBehaviour
{
[SerializeField, Required]
private GameObject _tutorialPanel;
[SerializeField, Required]
private GameObject _togglePanel;
[SerializeField, Required]
private ScrollRect _scrollRect;
[SerializeField, Required]
private RectTransform _buttonContents;
[SerializeField, Required]
private Transform _tutorialPopupUiContents;
[SerializeField]
private GameObject _keyAPanel;
[SerializeField]
private GameObject _keyDPanel;
[SerializeField]
private GameObject _keyEPanel;
[Title("프리팹")]
[SerializeField, Required]
private TutorialPageToggle _tutorialPageToggle;
[SerializeField, Required]
private TycoonTutorialPopupUi _tutorialPopupUi;
[Title("So")]
[SerializeField, Required]
private TutorialSo _tutorialSo;
[Title("실시간 데이터")]
[SerializeField]
private List<TutorialLink> _tutorialLinks;
[SerializeField]
private TutorialLink _currentTutorialLink;
private InputAction _pressQAction;
private InputAction _pressRAction;
private InputAction _pressAAction;
private InputAction _pressDAction;
private InputAction _interactionEAction;
private InputAction _closeAction;
private bool _isInMenu;
private bool _isUpdatingToggle;
public Action<bool> CloseAction;
private void Start()
{
_pressQAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.PressQ);
_pressRAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.PressR);
_pressAAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.PressA);
_pressDAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.PressD);
_interactionEAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.InteractionE);
_closeAction = PlayerInputKeyManager.Instance.GetAction(InputActionMaps.TycoonUi, TycoonUiActions.Cancel);
HideUi();
foreach (Transform element in _buttonContents.transform)
{
Destroy(element.gameObject);
}
foreach (Transform element in _tutorialPopupUiContents)
{
Destroy(element.gameObject);
}
_tutorialLinks = new List<TutorialLink>(_tutorialSo.GetDataCount());
foreach (TutorialInfo tutorialInfo in _tutorialSo.GetData().Values)
{
TutorialPageToggle tutorialPageToggle = Instantiate(this._tutorialPageToggle, _buttonContents);
List<TycoonTutorialPopupUi> tycoonTutorialPopupUis = new List<TycoonTutorialPopupUi>();
tutorialPageToggle.Initialize(tutorialInfo);
for (int i = 0; i < tutorialInfo.TutorialPages.Count; i++)
{
TycoonTutorialPopupUi tycoonTutorialPopupUi = Instantiate(_tutorialPopupUi, _tutorialPopupUiContents);
TutorialPageType tutorialPageType = tutorialInfo.TutorialPages[i].TutorialPageType;
Sprite popupSprite = null;
switch (tutorialPageType)
{
case TutorialPageType.First:
popupSprite = _tutorialSo.FirstPopup;
break;
case TutorialPageType.Middle:
popupSprite = _tutorialSo.MiddlePopup;
break;
case TutorialPageType.Last:
popupSprite = _tutorialSo.LastPopup;
break;
case TutorialPageType.Solo:
popupSprite = _tutorialSo.SoloPopup;
break;
default:
throw new ArgumentOutOfRangeException();
}
tycoonTutorialPopupUi.Initialize(tutorialInfo, i, popupSprite);
tycoonTutorialPopupUis.Add(tycoonTutorialPopupUi);
}
TutorialLink tutorialLink = new TutorialLink(tutorialInfo.TutorialName, tutorialPageToggle, tycoonTutorialPopupUis);
tutorialPageToggle.OnToggleEvent += isOn =>
{
if (_isUpdatingToggle) return; // 이벤트 중복 방지
if (isOn)
{
_isUpdatingToggle = true;
CloseKeyPanels();
_currentTutorialLink?.OnToggle(false);
_currentTutorialLink = tutorialLink;
_currentTutorialLink.OnToggle(true);
UpdateKeyPanels();
FocusOnToggle(_currentTutorialLink.TutorialPageToggle);
_isUpdatingToggle = false;
}
};
_tutorialLinks.Add(tutorialLink);
}
_currentTutorialLink = _tutorialLinks[0];
}
private void OnDestroy()
{
_pressQAction = null;
_pressRAction = null;
_pressAAction = null;
_pressDAction = null;
_interactionEAction = null;
_closeAction = null;
}
public void SetCurrentTutorialLink(string tutorialName = null)
{
if (tutorialName == null)
{
_currentTutorialLink = _tutorialLinks[0];
}
else
{
_currentTutorialLink = _tutorialLinks.Find(link => link.TutorialName == tutorialName);
}
_currentTutorialLink?.OnToggle(true);
_tutorialPanel.SetActive(true);
}
public void ShowUi(bool isInMenu)
{
_isInMenu = isInMenu;
if (_isInMenu)
{
SetCurrentTutorialLink();
_togglePanel.SetActive(true);
UpdateKeyPanels();
_pressQAction.performed += OnMovePreviousToggle;
_pressRAction.performed += OnMovNextToggle;
_closeAction.performed += OnClose;
}
_pressAAction.performed += OnMovePreviousPage;
_pressDAction.performed += OnMoveNextPage;
}
public void ShowUiByName(string tutorialName = null)
{
SetCurrentTutorialLink(tutorialName);
_togglePanel.SetActive(false);
UpdateKeyPanels();
ShowUi(false);
}
public void HideUi()
{
_pressQAction.performed -= OnMovePreviousToggle;
_pressRAction.performed -= OnMovNextToggle;
_pressAAction.performed -= OnMovePreviousPage;
_pressDAction.performed -= OnMoveNextPage;
_interactionEAction.performed -= OnClose;
_closeAction.performed -= OnClose;
_togglePanel.SetActive(false);
_tutorialPanel.SetActive(false);
_currentTutorialLink?.OnToggle(false);
CloseKeyPanels();
CloseAction?.Invoke(_isInMenu);
_isInMenu = false;
}
private void OnMovePreviousToggle(InputAction.CallbackContext context)
{
MoveToggle(-1);
}
private void OnMovNextToggle(InputAction.CallbackContext context)
{
MoveToggle(1);
}
private void MoveToggle(int direction)
{
CloseKeyPanels();
int currentIndex = _tutorialLinks.IndexOf(_currentTutorialLink);
int nextIndex = Mathf.Clamp(currentIndex + direction, 0, _tutorialLinks.Count - 1);
_currentTutorialLink.OnToggle(false);
_currentTutorialLink = _tutorialLinks[nextIndex];
_currentTutorialLink.OnToggle(true);
UpdateKeyPanels();
FocusOnToggle(_currentTutorialLink.TutorialPageToggle);
}
private void FocusOnToggle(TutorialPageToggle selectedToggle)
{
if (!selectedToggle.gameObject.activeInHierarchy) return;
// Viewport와 Content의 너비를 가져오기
float contentWidth = _buttonContents.rect.width; // Content 전체 너비
float viewportWidth = _scrollRect.viewport.rect.width; // Viewport 너비
// 선택된 토글의 x 위치를 Content 기준으로 가져오기
float targetX = selectedToggle.Rect.anchoredPosition.x;
// Normalized Position 계산
// (Content 기준 위치 - 뷰포트 절반) / (Content 너비 - 뷰포트 너비)
float normalizedPosition = Mathf.Clamp01((targetX - (viewportWidth / 2)) / (contentWidth - viewportWidth));
// ScrollRect에 반영
_scrollRect.horizontalNormalizedPosition = normalizedPosition;
}
private void OnMovePreviousPage(InputAction.CallbackContext context)
{
MovePage(false);
}
private void OnMoveNextPage(InputAction.CallbackContext context)
{
MovePage(true);
}
private void MovePage(bool moveNext)
{
if (_currentTutorialLink == null) return;
_currentTutorialLink.MovePage(moveNext);
UpdateKeyPanels();
}
private void CloseKeyPanels()
{
_interactionEAction.performed -= OnClose;
_keyAPanel.SetActive(false);
_keyDPanel.SetActive(false);
_keyEPanel.SetActive(false);
}
private void UpdateKeyPanels()
{
if (_currentTutorialLink == null) return;
int currentPageIndex = _currentTutorialLink.CurrentPageIndex;
int lastPage = _currentTutorialLink.TycoonTutorialPopupUis.Count;
_keyAPanel.SetActive(currentPageIndex > 0);
_keyDPanel.SetActive(currentPageIndex < lastPage - 1);
if (currentPageIndex == lastPage - 1)
{
_keyEPanel.SetActive(true);
_interactionEAction.performed += OnClose;
}
}
private void OnClose(InputAction.CallbackContext context)
{
HideUi();
}
}
}