147 lines
4.1 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|