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

147 lines
4.1 KiB
C#

using System.Collections;
using Definition.Enum;
using Event;
using TMPro;
using UnityEngine;
namespace UI
{
public abstract class DialogFormBase : UGuiForm
{
protected DialogFormContext _context;
private Coroutine _typingCoroutine;
private TMP_Text _typingTargetText;
private bool _isTypewriting;
public abstract DialogFormMode UIMode { get; }
public abstract void StartDialog(DialogFormContext context);
protected override void OnOpen(object userData)
{
base.OnOpen(userData);
if (!(userData is DialogFormContext context))
{
return;
}
_context = context;
StartDialog(context);
}
protected override void OnClose(bool isShutdown, object userData)
{
StopTypewriter();
_context = null;
base.OnClose(isShutdown, userData);
}
public void OnClickNextLine()
{
if (CompleteTypewriterIfRunning())
{
return;
}
GameEntry.Event.Fire(this, DialogNextLineRequestEventArgs.Create());
}
public void OnClickSkipDialog()
{
GameEntry.Event.Fire(this, DialogSkipRequestEventArgs.Create());
}
public void OnClickStopDialog()
{
GameEntry.Event.Fire(this, DialogStopRequestEventArgs.Create());
}
protected void PlayTypewriter(TMP_Text targetText, string text, float charsPerSecond)
{
StopTypewriter();
if (targetText == null)
{
return;
}
string finalText = text ?? string.Empty;
_typingTargetText = targetText;
if (charsPerSecond <= 0f || string.IsNullOrEmpty(finalText))
{
targetText.text = finalText;
targetText.maxVisibleCharacters = int.MaxValue;
_isTypewriting = false;
return;
}
_isTypewriting = true;
_typingCoroutine = StartCoroutine(TypewriterRoutine(targetText, finalText, charsPerSecond));
}
protected void StopTypewriter()
{
if (_typingCoroutine != null)
{
StopCoroutine(_typingCoroutine);
_typingCoroutine = null;
}
_typingTargetText = null;
_isTypewriting = false;
}
private bool CompleteTypewriterIfRunning()
{
if (!_isTypewriting || _typingTargetText == null)
{
return false;
}
_typingTargetText.maxVisibleCharacters = int.MaxValue;
StopTypewriter();
return true;
}
private IEnumerator TypewriterRoutine(TMP_Text targetText, string finalText, float charsPerSecond)
{
targetText.text = finalText;
targetText.ForceMeshUpdate();
int totalCharacters = targetText.textInfo.characterCount;
if (totalCharacters <= 0)
{
targetText.maxVisibleCharacters = int.MaxValue;
_typingCoroutine = null;
_typingTargetText = null;
_isTypewriting = false;
yield break;
}
targetText.maxVisibleCharacters = 0;
float elapsed = 0f;
int visibleCharacters = 0;
while (visibleCharacters < totalCharacters)
{
elapsed += Time.unscaledDeltaTime;
int nextVisible = Mathf.Min(totalCharacters, Mathf.FloorToInt(elapsed * charsPerSecond));
if (nextVisible != visibleCharacters)
{
visibleCharacters = nextVisible;
targetText.maxVisibleCharacters = visibleCharacters;
}
yield return null;
}
targetText.maxVisibleCharacters = int.MaxValue;
_typingCoroutine = null;
_typingTargetText = null;
_isTypewriting = false;
}
}
}