386 lines
13 KiB
C#
386 lines
13 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using BlueWater.Uis;
|
|
using DG.Tweening;
|
|
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 : PausePopupUi
|
|
{
|
|
[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 Vector3 _startScale = new(2.5f, 2.5f, 2.5f);
|
|
|
|
[SerializeField]
|
|
private Vector3 _endScale = new(2f, 2f, 2f);
|
|
|
|
[SerializeField]
|
|
private float _startAlpha = 0f;
|
|
|
|
[SerializeField]
|
|
private float _endAlpha = 1f;
|
|
|
|
[SerializeField]
|
|
private float _duration = 0.5f;
|
|
|
|
[Title("실시간 데이터")]
|
|
[SerializeField]
|
|
private List<TutorialLink> _tutorialLinks;
|
|
|
|
[SerializeField]
|
|
private TutorialLink _currentTutorialLink;
|
|
|
|
private Sequence _openSequence;
|
|
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;
|
|
}
|
|
};
|
|
|
|
foreach (var element in tutorialLink.TycoonTutorialPopupUis)
|
|
{
|
|
element.SetupButtons(tutorialLink, OnMovePreviousPageButton, OnMoveNextPageButton);
|
|
}
|
|
|
|
_tutorialLinks.Add(tutorialLink);
|
|
}
|
|
|
|
_currentTutorialLink = _tutorialLinks[0];
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
_openSequence?.Kill();
|
|
_pressQAction = null;
|
|
_pressRAction = null;
|
|
_pressAAction = null;
|
|
_pressDAction = null;
|
|
_interactionEAction = null;
|
|
_closeAction = null;
|
|
}
|
|
|
|
public override void Open()
|
|
{
|
|
OpenSwitch(InputActionMaps.TycoonUi);
|
|
|
|
if (_isInMenu)
|
|
{
|
|
SetCurrentTutorialLink();
|
|
_togglePanel.SetActive(true);
|
|
UpdateKeyPanels();
|
|
|
|
_pressQAction.performed += OnMovePreviousToggle;
|
|
_pressRAction.performed += OnMovNextToggle;
|
|
_closeAction.performed += OnClose;
|
|
}
|
|
|
|
_pressAAction.performed += OnMovePreviousPage;
|
|
_pressDAction.performed += OnMoveNextPage;
|
|
}
|
|
|
|
public override void Close()
|
|
{
|
|
_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;
|
|
|
|
CloseSwitch(InputActionMaps.Tycoon);
|
|
}
|
|
|
|
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);
|
|
if (!_isInMenu)
|
|
{
|
|
_openSequence = DOTween.Sequence()
|
|
.Append(_currentTutorialLink?.TycoonTutorialPopupUis[0].PopupImage.transform
|
|
.DOScale(_endScale, _duration).From(_startScale).SetEase(Ease.Linear))
|
|
.Join(_currentTutorialLink?.TycoonTutorialPopupUis[0].CanvasGroup.DOFade(_endAlpha, _duration)
|
|
.From(_startAlpha).SetEase(Ease.InQuart))
|
|
.SetUpdate(true)
|
|
.SetAutoKill(false);
|
|
}
|
|
}
|
|
|
|
public void ShowUi(bool isInMenu)
|
|
{
|
|
_isInMenu = isInMenu;
|
|
|
|
Open();
|
|
}
|
|
|
|
public void ShowUiByName(string tutorialName = null)
|
|
{
|
|
SetCurrentTutorialLink(tutorialName);
|
|
_togglePanel.SetActive(false);
|
|
UpdateKeyPanels();
|
|
|
|
ShowUi(false);
|
|
}
|
|
|
|
public void HideUi()
|
|
{
|
|
Close();
|
|
_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();
|
|
}
|
|
|
|
public void OnMovePreviousPageButton(TutorialLink tutorialLink)
|
|
{
|
|
_currentTutorialLink = tutorialLink;
|
|
|
|
MovePage(false);
|
|
}
|
|
|
|
public void OnMoveNextPageButton(TutorialLink tutorialLink)
|
|
{
|
|
_currentTutorialLink = tutorialLink;
|
|
|
|
MovePage(true);
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|