Files
aibis-dream/Assets/Scripts/FixSystemNew/Screen System/ScreenSystem.cs
T
2025-05-20 17:05:56 +08:00

198 lines
5.7 KiB
C#

using System;
using System.Collections;
using AibisDream.Framework;
using AibisDream.Kit;
using DG.Tweening;
using TMPro;
using UnityEngine;
namespace AibisDream.FixSystem
{
public class ScreenSystem : MonoBehaviour, IScreen, IDialogView
{
#region 效果参数
public float typeSpeed = 0.05f;
public int maxTextLine;
#endregion
#region 索引
[SerializeField] private TMP_Text title;
[SerializeField] private TMP_Text text;
private Action _nextStep;
private TextGenerator _generator;
private TextGenerationSettings _generationSettings;
private IUnRegister _plugOutRmv;
public TaskScreen TaskScreen { get; private set; }
#endregion
private void Awake()
{
InitComponentRefs();
Register();
}
private void InitComponentRefs()
{
_generator = new TextGenerator();
_generationSettings = new TextGenerationSettings
{
font = text.font.sourceFontFile,
fontSize = Mathf.RoundToInt(text.fontSize),
lineSpacing = text.lineSpacing,
horizontalOverflow = HorizontalWrapMode.Wrap,
verticalOverflow = VerticalWrapMode.Truncate,
generationExtents = new Vector2(text.rectTransform.rect.width, Mathf.Infinity),
resizeTextForBestFit = false
};
TaskScreen = GetComponentInChildren<TaskScreen>();
}
private void Register()
{
FixSystemCenter.SystemDic.Register(this);
DialogCanvasManager.Instance.RegisterDialogView(DialogViewType.Screen, this);
DialogCanvasManager.Instance.RegisterDialogView(DialogViewType.Task, TaskScreen);
}
private void OnDestroy()
{
FixSystemCenter.SystemDic.Unregister<ScreenSystem>();
DialogCanvasManager.Instance.UnregisterDialogView(DialogViewType.Screen);
DialogCanvasManager.Instance.UnregisterDialogView(DialogViewType.Task);
}
#region 基础功能
public void ShowTitle(string targetTitle)
{
title.text = targetTitle;
}
public IEnumerator ShowText(string targetText)
{
// 先换行
if (!string.IsNullOrEmpty(text.text))
{
text.text += "\n";
}
// 先估算新增行数
var targetLineNum = EstimateLineNum(targetText);
// 截断超出屏幕的部分
var oldText = "";
if (targetLineNum + text.textInfo.lineCount > maxTextLine)
{
var cutLineNum = targetLineNum + text.textInfo.lineCount - maxTextLine;
if (cutLineNum <= text.textInfo.lineCount)
{
var lastCharIndex = text.textInfo.lineInfo[cutLineNum - 1].lastCharacterIndex;
if (lastCharIndex + 1 < text.text.Length)
{
oldText = text.text.Substring(lastCharIndex + 1);
}
else
{
oldText = string.Empty;
}
}
}
else
{
oldText = text.text;
}
var targetLength = oldText.Length + targetText.Length;
// 逐个字符添加
yield return DOTween.To(() => oldText.Length, x => UpdateText(x, targetText, oldText), targetLength,
targetText.Length * typeSpeed).WaitForCompletion();
EnumEventSystem.Global.Send(DialogEventEnum.LineShown);
yield return new WaitForSeconds(0.5f);
EnumEventSystem.Global.Send(DialogEventEnum.LineEnd);
_nextStep.Invoke();
}
private int EstimateLineNum(string str)
{
var height = _generator.GetPreferredHeight(str, _generationSettings);
var lineHeight = text.fontSize * 1.2f; // 简单估算行高
return Mathf.CeilToInt(height / lineHeight);
}
private void UpdateText(int currentLength, string nextText, string oldText)
{
var appendLength = currentLength - oldText.Length;
text.text = oldText + nextText[..appendLength];
}
public void ClearTextScreen()
{
title.text = "";
text.SetText("");
}
#endregion
#region 对话框功能实现
public void ShowLine(string dialogLine, CharacterVo character, Action nextStep, string lineId, bool isAutoSkip = false)
{
ShowTitle(character.GetActorName());
StartCoroutine(ShowText(dialogLine));
// 每行自动跳过
_nextStep = nextStep;
}
public void ShowOptions(DialogOption[] dialogueOptions)
{
Debug.Log("不能在显示屏显示对话");
}
public void HideDialog()
{
// HideDialog应该由其他函数控制
}
public bool TrySkipLine(bool isAutoSkip)
{
// 这里不能跳过对话
return true;
}
public void NextStep()
{
// 这里不能手动跳到下一行
}
public void OnLocalizationChanged(string value)
{
// 屏幕不需要本地化
}
#endregion
}
/// <summary>
/// 屏幕接口
/// </summary>
public interface IScreen
{
// 显示标题文字
void ShowTitle(string title);
// 显示正文
IEnumerator ShowText(string text);
// 清空屏幕
void ClearTextScreen();
}
}