using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; using AibisDream.Framework; using AibisDream.Utility; using DG.Tweening; using Febucci.UI; using Febucci.UI.Core; using Newtonsoft.Json; using TMPro; using UnityEngine; using UnityEngine.UI; namespace AibisDream.FixSystem { public class ScreenSystem : MonoBehaviour, ILineView { #region 索引 [SerializeField] private TMP_Text title; [SerializeField] private RectTransform textRoot; [SerializeField] private TMP_Text textForEstimation; [SerializeField] private int maxLineNum = 10; private ScreenData _screenData; private GameObject _textItemPrefab; private Queue _lineQueue; public BubbleSlotGroup BubbleSlotGroup { get; private set; } public TaskScreen TaskScreen { get; private set; } #endregion private void Awake() { InitComponentRefs(); Register(); } private void InitComponentRefs() { TaskScreen = GetComponentInChildren(); _lineQueue = new Queue(); _textItemPrefab = ResourceKit.LoadAssetSync(ConstRef.ScreenTextName); BubbleSlotGroup = GetComponentInChildren(); } private void Register() { _screenData = new ScreenData { screenSystem = this }; StorageSystem.Instance.RegisterData(_screenData); FixSystemCenter.SystemDic.Register(this); DialogUIManager.Instance.RegisterScreenView(DialogViewType.Screen, this); DialogUIManager.Instance.RegisterScreenView(DialogViewType.Task, TaskScreen); } private void OnDestroy() { StorageSystem.Instance.UnregisterData(); FixSystemCenter.SystemDic.Unregister(); DialogUIManager.Instance.UnRegisterScreenView(DialogViewType.Screen); DialogUIManager.Instance.UnRegisterScreenView(DialogViewType.Task); } #region 基础功能 private void ShowTitle(string targetTitle) { title.text = targetTitle; } public void ClearTextScreen() { while (_lineQueue.Count > 0) { var text = _lineQueue.Dequeue(); Destroy(text.gameObject); } ShowTitle(string.Empty); } public void ShowTaskPanel(float duration = 1f) { TaskScreen.transform.DOLocalMoveX(-7.12f, duration); _screenData.isTaskPanelShown = true; } #endregion public void RunLine(LineSyncToken token) { // 空格延长一点避免报错 if (string.IsNullOrWhiteSpace(token.lineInfo.lineText)) { token.lineInfo.lineText = " "; } // 显示标题 ShowTitle(token.lineInfo.character.GetActorName()); // 显示文本 TypewriterCore textItemTypewriter = AddText(token); token.TextStart(); // 强制更新布局 LayoutRebuilder.ForceRebuildLayoutImmediate(textRoot); } private float GetTextSpeedValue() { var textSpeedStr = SettingLoader.Instance.TryRead("TextSpeed", out string textSpeed) ? textSpeed : "1"; return float.TryParse(textSpeedStr, NumberStyles.Float, CultureInfo.InvariantCulture, out float result) ? result : 1f; } private void OnTextShown(LineSyncToken syncToken, TypewriterCore typewriter) { typewriter.onTextShowed.RemoveAllListeners(); syncToken.TextShown(); } private TypewriterByCharacter AddText(LineSyncToken token) { // 生成新文本组件 var textItem = Instantiate(_textItemPrefab, textRoot); var textItemTypewriter = textItem.GetComponent(); // 估算文本高度 var newLineNum = EstimateLineNum(token.lineInfo.lineText); var oldLineNum = CalcTotalLineNum(); if (newLineNum + oldLineNum > maxLineNum) { Destroy(_lineQueue.Dequeue().gameObject); } _lineQueue.Enqueue(textItemTypewriter); textItemTypewriter.SetTypewriterSpeed(GetTextSpeedValue()); textItemTypewriter.onTextShowed.AddListener(() => OnTextShown(token, textItemTypewriter)); textItemTypewriter.ShowText(token.lineInfo.lineText); return textItemTypewriter; } private int EstimateLineNum(string text) { textForEstimation.text = text; textForEstimation.ForceMeshUpdate(); return textForEstimation.textInfo.lineCount; } private int CalcTotalLineNum() { return _lineQueue.Select(x => x.GetComponent().textInfo.lineCount).Sum(); } } public class ScreenData : IData { [JsonIgnore] public ScreenSystem screenSystem; public bool isTaskPanelShown = false; public IEnumerator Load() { if (isTaskPanelShown) { screenSystem.ShowTaskPanel(0); } yield break; } } }