biography-of-lijie/Assets/GameMain/Scripts/UI/View/ChapterTitleForm.cs

376 lines
13 KiB
C#

using System.Collections;
using Event;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;
namespace UI
{
public class ChapterTitleForm : UGuiForm
{
[SerializeField] private CanvasGroup _contentGroup;
[SerializeField] private Image _dimImage;
[SerializeField] private TMP_Text _titleText;
[SerializeField] private TMP_Text _subtitleText;
[SerializeField] private float _dimFadeInDuration = 0.2f;
[SerializeField] private float _preBlackDuration = 0.25f;
[SerializeField] private float _titleFadeInDelay = 0f;
[SerializeField] private float _fadeInDuration = 0.3f;
[SerializeField] private float _holdDuration = 1.2f;
[SerializeField] private float _fadeOutDuration = 0.3f;
[SerializeField] private float _dimFadeOutDuration = 0.2f;
private Coroutine _playCoroutine;
private int _requestId;
private int _chapterId;
private bool _hasPublishedCompletion;
private float _runtimeDimFadeInDuration;
private float _runtimePreBlackDuration;
private float _runtimeTitleFadeInDelay;
private float _runtimeTitleFadeInDuration;
private float _runtimeHoldDuration;
private float _runtimeTitleFadeOutDuration;
private float _runtimeDimFadeOutDuration;
protected override void OnOpen(object userData)
{
base.OnOpen(userData);
EnsureView();
ApplyContext(userData as ChapterTitleFormContext);
StartPlay();
}
protected override void OnClose(bool isShutdown, object userData)
{
StopPlay();
SetDimAlpha(0f);
SetTitleAlpha(0f);
if (!isShutdown)
{
PublishCompletionIfNeeded();
}
base.OnClose(isShutdown, userData);
}
private void EnsureView()
{
RectTransform rootRect = transform as RectTransform;
if (rootRect == null)
{
return;
}
if (_contentGroup == null)
{
_contentGroup = CreateContentGroup(rootRect);
}
if (_contentGroup != null)
{
_contentGroup.alpha = 1f;
}
RectTransform contentRect = _contentGroup != null && _contentGroup.transform is RectTransform contentTransform
? contentTransform
: rootRect;
if (_dimImage == null)
{
_dimImage = CreateImage("Dim", contentRect, new Color(0f, 0f, 0f, 0.72f), true);
}
if (_titleText == null)
{
_titleText = CreateText("Title", contentRect, 108f, FontStyles.Bold, TextAlignmentOptions.Center);
RectTransform titleRect = _titleText.rectTransform;
titleRect.anchorMin = new Vector2(0.5f, 0.5f);
titleRect.anchorMax = new Vector2(0.5f, 0.5f);
titleRect.pivot = new Vector2(0.5f, 0.5f);
titleRect.sizeDelta = new Vector2(2200f, 220f);
titleRect.anchoredPosition = new Vector2(0f, 40f);
}
if (_subtitleText == null)
{
_subtitleText = CreateText("Subtitle", contentRect, 42f, FontStyles.Normal, TextAlignmentOptions.Center);
RectTransform subtitleRect = _subtitleText.rectTransform;
subtitleRect.anchorMin = new Vector2(0.5f, 0.5f);
subtitleRect.anchorMax = new Vector2(0.5f, 0.5f);
subtitleRect.pivot = new Vector2(0.5f, 0.5f);
subtitleRect.sizeDelta = new Vector2(2200f, 120f);
subtitleRect.anchoredPosition = new Vector2(0f, -60f);
}
if (_dimImage != null)
{
_dimImage.transform.SetAsFirstSibling();
}
if (_subtitleText != null)
{
_subtitleText.transform.SetAsLastSibling();
}
if (_titleText != null)
{
_titleText.transform.SetAsLastSibling();
}
}
private void ApplyContext(ChapterTitleFormContext context)
{
_hasPublishedCompletion = false;
ResetRuntimeTimings(context);
if (context == null)
{
_requestId = 0;
_chapterId = 0;
SetTitleText(string.Empty, string.Empty);
return;
}
_requestId = context.RequestId;
_chapterId = context.ChapterId;
string title = string.IsNullOrWhiteSpace(context.Title)
? BuildDefaultChapterTitle(_chapterId)
: context.Title.Trim();
string subtitle = string.IsNullOrWhiteSpace(context.Subtitle) ? string.Empty : context.Subtitle.Trim();
SetTitleText(title, subtitle);
}
private void SetTitleText(string title, string subtitle)
{
if (_titleText != null)
{
_titleText.text = title;
}
if (_subtitleText != null)
{
_subtitleText.text = subtitle;
_subtitleText.gameObject.SetActive(!string.IsNullOrEmpty(subtitle));
}
}
private void StartPlay()
{
StopPlay();
_playCoroutine = StartCoroutine(PlayRoutine());
}
private void StopPlay()
{
if (_playCoroutine == null)
{
return;
}
StopCoroutine(_playCoroutine);
_playCoroutine = null;
}
private IEnumerator PlayRoutine()
{
SetDimAlpha(0f);
SetTitleAlpha(0f);
yield return FadeDimAlpha(0f, 1f, _runtimeDimFadeInDuration);
yield return WaitUnscaled(_runtimePreBlackDuration);
yield return WaitUnscaled(_runtimeTitleFadeInDelay);
yield return FadeTitleAlpha(0f, 1f, _runtimeTitleFadeInDuration);
yield return WaitUnscaled(_runtimeHoldDuration);
yield return FadeTitleAlpha(1f, 0f, _runtimeTitleFadeOutDuration);
yield return FadeDimAlpha(1f, 0f, _runtimeDimFadeOutDuration);
_playCoroutine = null;
PublishCompletionIfNeeded();
if (GameEntry.UI != null && UIForm != null)
{
GameEntry.UI.CloseUIForm(UIForm);
}
}
private IEnumerator FadeDimAlpha(float from, float to, float duration)
{
float safeDuration = Mathf.Max(0f, duration);
if (safeDuration <= 0f)
{
SetDimAlpha(to);
yield break;
}
float elapsed = 0f;
while (elapsed < safeDuration)
{
elapsed += Time.unscaledDeltaTime;
float t = Mathf.Clamp01(elapsed / safeDuration);
SetDimAlpha(Mathf.Lerp(from, to, t));
yield return null;
}
SetDimAlpha(to);
}
private IEnumerator FadeTitleAlpha(float from, float to, float duration)
{
float safeDuration = Mathf.Max(0f, duration);
if (safeDuration <= 0f)
{
SetTitleAlpha(to);
yield break;
}
float elapsed = 0f;
while (elapsed < safeDuration)
{
elapsed += Time.unscaledDeltaTime;
float t = Mathf.Clamp01(elapsed / safeDuration);
SetTitleAlpha(Mathf.Lerp(from, to, t));
yield return null;
}
SetTitleAlpha(to);
}
private static IEnumerator WaitUnscaled(float duration)
{
float safeDuration = Mathf.Max(0f, duration);
if (safeDuration <= 0f)
{
yield break;
}
float elapsed = 0f;
while (elapsed < safeDuration)
{
elapsed += Time.unscaledDeltaTime;
yield return null;
}
}
private void SetDimAlpha(float alpha)
{
if (_dimImage == null)
{
return;
}
Color color = _dimImage.color;
color.a = Mathf.Clamp01(alpha);
_dimImage.color = color;
}
private void SetTitleAlpha(float alpha)
{
float clampedAlpha = Mathf.Clamp01(alpha);
SetTextAlpha(_titleText, clampedAlpha);
SetTextAlpha(_subtitleText, clampedAlpha);
}
private static void SetTextAlpha(TMP_Text text, float alpha)
{
if (text == null)
{
return;
}
Color color = text.color;
color.a = alpha;
text.color = color;
}
private void ResetRuntimeTimings(ChapterTitleFormContext context)
{
_runtimeDimFadeInDuration = ResolveDuration(context != null ? context.DimFadeInDuration : -1f,
_dimFadeInDuration);
_runtimePreBlackDuration = ResolveDuration(context != null ? context.PreBlackDuration : -1f,
_preBlackDuration);
_runtimeTitleFadeInDelay = ResolveDuration(context != null ? context.TitleFadeInDelay : -1f,
_titleFadeInDelay);
_runtimeTitleFadeInDuration = ResolveDuration(context != null ? context.TitleFadeInDuration : -1f,
_fadeInDuration);
_runtimeHoldDuration = ResolveDuration(context != null ? context.HoldDuration : -1f, _holdDuration);
_runtimeTitleFadeOutDuration = ResolveDuration(context != null ? context.TitleFadeOutDuration : -1f,
_fadeOutDuration);
_runtimeDimFadeOutDuration = ResolveDuration(context != null ? context.DimFadeOutDuration : -1f,
_dimFadeOutDuration);
}
private static float ResolveDuration(float overrideDuration, float fallbackDuration)
{
return overrideDuration >= 0f ? overrideDuration : Mathf.Max(0f, fallbackDuration);
}
private void PublishCompletionIfNeeded()
{
if (_hasPublishedCompletion || _requestId <= 0)
{
return;
}
_hasPublishedCompletion = true;
GameEntry.Event.Fire(this, ChapterTitleCompletedEventArgs.Create(_chapterId, _requestId));
}
private static string BuildDefaultChapterTitle(int chapterId)
{
return chapterId > 0 ? $"第{chapterId}章" : string.Empty;
}
private static CanvasGroup CreateContentGroup(RectTransform parent)
{
GameObject go = new GameObject("ContentRoot", typeof(RectTransform), typeof(CanvasGroup));
RectTransform rect = go.GetComponent<RectTransform>();
rect.SetParent(parent, false);
rect.anchorMin = Vector2.zero;
rect.anchorMax = Vector2.one;
rect.offsetMin = Vector2.zero;
rect.offsetMax = Vector2.zero;
return go.GetComponent<CanvasGroup>();
}
private static Image CreateImage(string name, RectTransform parent, Color color, bool raycastTarget)
{
GameObject go = new GameObject(name, typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
RectTransform rect = go.GetComponent<RectTransform>();
rect.SetParent(parent, false);
rect.anchorMin = Vector2.zero;
rect.anchorMax = Vector2.one;
rect.offsetMin = Vector2.zero;
rect.offsetMax = Vector2.zero;
Image image = go.GetComponent<Image>();
image.color = color;
image.raycastTarget = raycastTarget;
return image;
}
private static TMP_Text CreateText(string name, RectTransform parent, float fontSize, FontStyles style,
TextAlignmentOptions alignment)
{
GameObject go = new GameObject(name, typeof(RectTransform), typeof(CanvasRenderer), typeof(TextMeshProUGUI));
RectTransform rect = go.GetComponent<RectTransform>();
rect.SetParent(parent, false);
TextMeshProUGUI text = go.GetComponent<TextMeshProUGUI>();
if (TMP_Settings.defaultFontAsset != null)
{
text.font = TMP_Settings.defaultFontAsset;
}
text.text = string.Empty;
text.fontSize = fontSize;
text.fontStyle = style;
text.alignment = alignment;
text.color = new Color(0.96f, 0.94f, 0.88f, 1f);
text.raycastTarget = false;
return text;
}
}
}