Files
Ultimate-Fishing-Simulator-…/Assets/Scripts/Assembly-CSharp/Michsky/UI/Heat/ChapterManager.cs
2026-03-04 09:37:33 +08:00

448 lines
13 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace Michsky.UI.Heat
{
public class ChapterManager : MonoBehaviour
{
[Serializable]
public class ChapterChangeCallback : UnityEvent<int>
{
}
public enum ChapterState
{
Locked = 0,
Unlocked = 1,
Completed = 2,
Current = 3
}
[Serializable]
public class ChapterItem
{
public string chapterID;
public string title;
public Sprite background;
[TextArea]
public string description;
public ChapterState defaultState;
[Header("Localization")]
public string titleKey = "TitleKey";
public string descriptionKey = "DescriptionKey";
[Header("Events")]
public UnityEvent onContinue;
public UnityEvent onPlay;
public UnityEvent onReplay;
}
public List<ChapterItem> chapters = new List<ChapterItem>();
private List<ChapterIdentifier> identifiers = new List<ChapterIdentifier>();
public int currentChapterIndex;
[SerializeField]
private GameObject chapterPreset;
[SerializeField]
private Transform chapterParent;
[SerializeField]
private ButtonManager previousButton;
[SerializeField]
private ButtonManager nextButton;
[SerializeField]
private Image progressFill;
[SerializeField]
private bool showLockedChapters = true;
[SerializeField]
private bool setPanelAuto = true;
[SerializeField]
private bool checkChapterData = true;
[SerializeField]
private bool useLocalization = true;
[SerializeField]
[Range(0.5f, 10f)]
private float barCurveSpeed = 2f;
[SerializeField]
private AnimationCurve barCurve = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f));
[SerializeField]
[Range(0.75f, 2f)]
private float animationSpeed = 1f;
[SerializeField]
private bool backgroundStretch = true;
[SerializeField]
[Range(0f, 100f)]
private float maxStretch = 75f;
[SerializeField]
[Range(0.02f, 0.5f)]
private float stretchCurveSpeed = 0.1f;
[SerializeField]
private AnimationCurve stretchCurve = new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(1f, 1f));
public ChapterChangeCallback onChapterPanelChanged = new ChapterChangeCallback();
[HideInInspector]
public RectTransform currentBackgroundRect;
private LocalizedObject localizedObject;
private string animSpeedKey = "AnimSpeed";
private void Awake()
{
InitializeChapters();
}
private void OnEnable()
{
OpenCurrentPanel();
}
private void OnDisable()
{
if (backgroundStretch)
{
StopCoroutine("StretchPhaseOne");
StopCoroutine("StretchPhaseTwo");
}
}
public void DoStretch()
{
if (backgroundStretch && !(currentBackgroundRect == null) && base.gameObject.activeInHierarchy)
{
float num = 1f + maxStretch / 960f;
currentBackgroundRect.localScale = new Vector3(num, num, num);
currentBackgroundRect.offsetMin = new Vector2(0f, 0f);
currentBackgroundRect.offsetMax = new Vector2(0f, 0f);
StopCoroutine("StretchPhaseOne");
StopCoroutine("StretchPhaseTwo");
StartCoroutine("StretchPhaseOne");
}
}
public void InitializeChapters()
{
if (useLocalization)
{
localizedObject = base.gameObject.GetComponent<LocalizedObject>();
if (localizedObject == null || !localizedObject.CheckLocalizationStatus())
{
useLocalization = false;
}
}
identifiers.Clear();
foreach (Transform item in chapterParent)
{
UnityEngine.Object.Destroy(item.gameObject);
}
for (int i = 0; i < chapters.Count; i++)
{
int index = i;
GameObject obj = UnityEngine.Object.Instantiate(chapterPreset, new Vector3(0f, 0f, 0f), Quaternion.identity);
obj.transform.SetParent(chapterParent, worldPositionStays: false);
obj.gameObject.name = chapters[i].chapterID;
ChapterIdentifier component = obj.GetComponent<ChapterIdentifier>();
component.chapterManager = this;
identifiers.Add(component);
component.backgroundImage.sprite = chapters[i].background;
component.UpdateBackgroundRect();
if (!useLocalization || string.IsNullOrEmpty(chapters[i].titleKey))
{
component.titleObject.text = chapters[i].title;
}
else
{
LocalizedObject component2 = component.titleObject.GetComponent<LocalizedObject>();
if (component2 != null)
{
component2.tableIndex = localizedObject.tableIndex;
component2.localizationKey = chapters[i].titleKey;
component2.UpdateItem();
}
}
if (!useLocalization || string.IsNullOrEmpty(chapters[i].descriptionKey))
{
component.descriptionObject.text = chapters[i].description;
}
else
{
LocalizedObject component3 = component.descriptionObject.GetComponent<LocalizedObject>();
if (component3 != null)
{
component3.tableIndex = localizedObject.tableIndex;
component3.localizationKey = chapters[i].descriptionKey;
component3.UpdateItem();
}
}
component.continueButton.onClick.RemoveAllListeners();
component.continueButton.onClick.AddListener(chapters[index].onContinue.Invoke);
component.playButton.onClick.RemoveAllListeners();
component.playButton.onClick.AddListener(chapters[index].onPlay.Invoke);
component.replayButton.onClick.RemoveAllListeners();
component.replayButton.onClick.AddListener(chapters[index].onReplay.Invoke);
if (checkChapterData)
{
if (!PlayerPrefs.HasKey("ChapterState_" + chapters[i].chapterID))
{
if (chapters[i].defaultState == ChapterState.Unlocked)
{
component.SetUnlocked();
}
else if (chapters[i].defaultState == ChapterState.Locked)
{
component.SetLocked();
}
else if (chapters[i].defaultState == ChapterState.Completed)
{
component.SetCompleted();
}
else
{
component.SetCurrent();
}
}
else if (PlayerPrefs.HasKey("ChapterState_" + chapters[i].chapterID) && PlayerPrefs.GetString("ChapterState_" + chapters[i].chapterID) == "unlocked")
{
component.SetUnlocked();
}
else if (PlayerPrefs.HasKey("ChapterState_" + chapters[i].chapterID) && PlayerPrefs.GetString("ChapterState_" + chapters[i].chapterID) == "current")
{
component.SetCurrent();
}
else if (PlayerPrefs.HasKey("ChapterState_" + chapters[i].chapterID) && PlayerPrefs.GetString("ChapterState_" + chapters[i].chapterID) == "completed")
{
component.SetCompleted();
}
else
{
component.SetLocked();
}
}
else if (chapters[i].defaultState == ChapterState.Unlocked)
{
component.SetUnlocked();
}
else if (chapters[i].defaultState == ChapterState.Locked)
{
component.SetLocked();
}
else if (chapters[i].defaultState == ChapterState.Completed)
{
component.SetCompleted();
}
else
{
component.SetCurrent();
}
obj.SetActive(value: false);
if (setPanelAuto && component.isCurrent)
{
currentChapterIndex = i;
}
}
identifiers[currentChapterIndex].gameObject.SetActive(value: true);
previousButton.onClick.RemoveAllListeners();
previousButton.onClick.AddListener(PrevChapter);
nextButton.onClick.RemoveAllListeners();
nextButton.onClick.AddListener(NextChapter);
UpdateButtonState();
if (progressFill != null)
{
progressFill.fillAmount = 1f / (float)chapters.Count * (float)(currentChapterIndex + 1);
}
}
public void NextChapter()
{
if (currentChapterIndex + 1 <= identifiers.Count - 1 && (showLockedChapters || !identifiers[currentChapterIndex + 1].isLocked))
{
identifiers[currentChapterIndex].animator.enabled = true;
identifiers[currentChapterIndex].animator.SetFloat(animSpeedKey, animationSpeed);
identifiers[currentChapterIndex].animator.Play("Next Out");
currentChapterIndex++;
identifiers[currentChapterIndex].gameObject.SetActive(value: true);
identifiers[currentChapterIndex].animator.enabled = true;
identifiers[currentChapterIndex].animator.SetFloat(animSpeedKey, animationSpeed);
identifiers[currentChapterIndex].animator.Play("Next In");
identifiers[currentChapterIndex].UpdateBackgroundRect();
UpdateButtonState();
StopCoroutine("DisablePanels");
StartCoroutine("DisablePanels");
}
}
public void PrevChapter()
{
if (currentChapterIndex > 0 && (showLockedChapters || !identifiers[currentChapterIndex - 1].isLocked))
{
identifiers[currentChapterIndex].animator.enabled = true;
identifiers[currentChapterIndex].animator.SetFloat(animSpeedKey, animationSpeed);
identifiers[currentChapterIndex].animator.Play("Prev Out");
currentChapterIndex--;
identifiers[currentChapterIndex].gameObject.SetActive(value: true);
identifiers[currentChapterIndex].animator.enabled = true;
identifiers[currentChapterIndex].animator.SetFloat(animSpeedKey, animationSpeed);
identifiers[currentChapterIndex].animator.Play("Prev In");
identifiers[currentChapterIndex].UpdateBackgroundRect();
UpdateButtonState();
StopCoroutine("DisablePanels");
StartCoroutine("DisablePanels");
}
}
private void OpenCurrentPanel()
{
if (!(identifiers[currentChapterIndex] == null))
{
identifiers[currentChapterIndex].gameObject.SetActive(value: true);
identifiers[currentChapterIndex].animator.enabled = true;
identifiers[currentChapterIndex].animator.SetFloat(animSpeedKey, animationSpeed);
identifiers[currentChapterIndex].animator.Play("Start");
identifiers[currentChapterIndex].UpdateBackgroundRect();
}
}
private void UpdateButtonState()
{
if (currentChapterIndex >= identifiers.Count - 1 && nextButton != null)
{
nextButton.isInteractable = false;
nextButton.UpdateUI();
}
else if (nextButton != null)
{
nextButton.isInteractable = true;
nextButton.UpdateUI();
}
if (currentChapterIndex < 1 && previousButton != null)
{
previousButton.isInteractable = false;
previousButton.UpdateUI();
}
else if (previousButton != null)
{
previousButton.isInteractable = true;
previousButton.UpdateUI();
}
if (!showLockedChapters && currentChapterIndex <= identifiers.Count - 1 && identifiers[currentChapterIndex + 1].isLocked)
{
nextButton.isInteractable = false;
nextButton.UpdateUI();
}
if (progressFill != null && base.gameObject.activeInHierarchy)
{
StopCoroutine("PlayProgressFill");
StartCoroutine("PlayProgressFill");
}
onChapterPanelChanged.Invoke(currentChapterIndex);
}
public static void SetLocked(string chapterID)
{
PlayerPrefs.SetString("ChapterState_" + chapterID, "locked");
}
public static void SetUnlocked(string chapterID)
{
PlayerPrefs.SetString("ChapterState_" + chapterID, "unlocked");
}
public static void SetCurrent(string chapterID)
{
PlayerPrefs.SetString("ChapterState_" + chapterID, "current");
}
public static void SetCompleted(string chapterID)
{
PlayerPrefs.SetString("ChapterState_" + chapterID, "completed");
}
private IEnumerator StretchPhaseOne()
{
float elapsedTime = 0f;
Vector2 startPos = currentBackgroundRect.offsetMin;
Vector2 endPos = new Vector2(0f - maxStretch, 0f);
while (currentBackgroundRect.offsetMin.x > 0f - maxStretch + 0.1f)
{
elapsedTime += Time.unscaledDeltaTime;
currentBackgroundRect.offsetMin = Vector2.Lerp(startPos, endPos, stretchCurve.Evaluate(elapsedTime * stretchCurveSpeed));
currentBackgroundRect.offsetMax = Vector2.Lerp(startPos, endPos, stretchCurve.Evaluate(elapsedTime * stretchCurveSpeed));
yield return null;
}
StartCoroutine("StretchPhaseTwo");
}
private IEnumerator StretchPhaseTwo()
{
float elapsedTime = 0f;
Vector2 startPos = currentBackgroundRect.offsetMin;
Vector2 endPos = new Vector2(maxStretch, 0f);
while (currentBackgroundRect.offsetMin.x < maxStretch - 0.1f)
{
elapsedTime += Time.unscaledDeltaTime;
currentBackgroundRect.offsetMin = Vector2.Lerp(startPos, endPos, stretchCurve.Evaluate(elapsedTime * stretchCurveSpeed));
currentBackgroundRect.offsetMax = Vector2.Lerp(startPos, endPos, stretchCurve.Evaluate(elapsedTime * stretchCurveSpeed));
yield return null;
}
StartCoroutine("StretchPhaseOne");
}
private IEnumerator DisablePanels()
{
yield return new WaitForSecondsRealtime(0.5f);
for (int i = 0; i < identifiers.Count; i++)
{
identifiers[i].animator.enabled = false;
if (i != currentChapterIndex)
{
identifiers[i].gameObject.SetActive(value: false);
}
}
}
private IEnumerator PlayProgressFill()
{
float startingPoint = progressFill.fillAmount;
float num = 1f / (float)chapters.Count;
float toBeFilled = num * (float)(currentChapterIndex + 1);
float elapsedTime = 0f;
while (progressFill.fillAmount.ToString("F2") != toBeFilled.ToString("F2"))
{
elapsedTime += Time.unscaledDeltaTime;
progressFill.fillAmount = Mathf.Lerp(startingPoint, toBeFilled, barCurve.Evaluate(elapsedTime * barCurveSpeed));
yield return null;
}
progressFill.fillAmount = toBeFilled;
}
}
}