Files
aibis-dream/Assets/Scripts/UI/DialogUI/Bubbles/Bubble.cs
T
dingyuntian 24d23b29d1 问题修复
1. CenterText效果异常修复
2. 部分气泡宽度不合预期修复
3. 删除切割日志
2026-01-03 17:40:11 +08:00

223 lines
6.9 KiB
C#

using System;
using System.Globalization;
using AibisDream.Framework;
using AibisDream.Kit;
using AibisDream.Utility;
using Febucci.UI.Core;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
namespace AibisDream
{
public class Bubble : MonoBehaviour, IBubble
{
private BubbleGroup _bubbleGroup;
private TypewriterCore _typewriter;
private TMP_Text _actorName;
private TMP_Text _lineText;
private LayoutElement _layoutElement;
private LayoutGroup _layoutGroup;
private RectTransform _rect;
private Image _bubbleImage;
#region 参数
[Header("参数")]
[SerializeField] private ActorRole role;
[SerializeField] private int idx;
[SerializeField] private int maxWidth;
[SerializeField] private int minWidth;
public ActorRole Role => role;
public int Idx => idx;
#endregion
public event Action<Bubble> OnDisposed;
public event Action OnLineShown;
public void LoadConfig(BubbleSlotData data, BubbleGroup bubbleGroup = null)
{
_bubbleGroup = bubbleGroup;
InitRefs();
role = data.actorRole;
idx = data.idx;
maxWidth = data.maxWidth;
minWidth = data.minWidth;
var rect = transform as RectTransform;
rect.localPosition = UIManager.GetDialogUIPos(data.slotPosition);
// 设置style
SetStyle(data.bubbleStyle, data.pivotType);
// 注册事件
_typewriter.onTextShowed.AddListener(InvokeLineShown);
EnumEventSystem.Global.Register<SettingChangeEvent, string>(SettingChangeEvent.TextSpeed, OnTextSpeedChanged);
}
private void InvokeLineShown()
{
OnLineShown?.Invoke();
OnLineShown = null;
}
private void SetStyle(BubbleStyle bubbleStyle, PivotType pivotType)
{
_bubbleImage.color = bubbleStyle.imageColor;
// padding内容
_layoutGroup.padding = bubbleStyle.BubblePadding;
_lineText.margin = bubbleStyle.linePadding;
_lineText.fontSize = bubbleStyle.lineFontSize;
_actorName.margin = bubbleStyle.actorPadding;
_actorName.fontSize = bubbleStyle.actorFontSize;
// 是否展示名称
_actorName.gameObject.SetActive(bubbleStyle.hasActorName);
// 锚点相关
_rect.pivot = CommonUtil.GetPivotByType(pivotType);
var spritePath = bubbleStyle.bubbleSpriteAddress.EndsWith("]")
? $"{bubbleStyle.bubbleSpriteAddress}"
: $"{bubbleStyle.bubbleSpriteAddress}[{pivotType}]";
_bubbleImage.sprite = ResourceKit.LoadAssetSync<Sprite>(spritePath);
// 初始化文字速度
var speedStr = SettingLoader.Instance.TryRead("TextSpeed", out string textSpeed) ? textSpeed : "1";
OnTextSpeedChanged(speedStr);
}
private void OnTextSpeedChanged(string value)
{
float speed = float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out float result) ? result : 1f;
_typewriter.SetTypewriterSpeed(speed);
}
private void InitRefs()
{
_typewriter = GetComponentInChildren<TypewriterCore>();
_actorName = transform.Find("名称").GetComponent<TMP_Text>();
_typewriter.onTextShowed.RemoveAllListeners();
_typewriter.onTextShowed.AddListener(() => EnumEventSystem.Global.Send(DialogEventEnum.LineShown));
// 获取内容文字
_lineText = _typewriter.GetComponent<TMP_Text>();
_layoutElement = _typewriter.GetComponent<LayoutElement>();
// 气泡自身
_layoutGroup = GetComponent<LayoutGroup>();
_bubbleImage = GetComponent<Image>();
_rect = _bubbleImage.rectTransform;
}
public void ShowActorName(CharacterVo characterVo)
{
if (_actorName == null) return;
_actorName.text = string.IsNullOrEmpty(characterVo.GetActorName())
? string.Empty
: characterVo.GetActorName();
}
public void ShowLine(string line)
{
_typewriter.TextAnimator.SetText("");
gameObject.SetActive(true);
HandleLayout(line);
_typewriter.ShowText(line);
}
public bool SkipLine()
{
if (_typewriter.isShowingText)
{
_typewriter.SkipTypewriter();
return true;
}
else
{
return false;
}
}
public void Hide()
{
gameObject.SetActive(false);
}
public void Dispose()
{
Hide();
_typewriter.onTextShowed.RemoveAllListeners();
OnDisposed?.Invoke(this);
OnDisposed = null;
}
private void HandleLayout(string line)
{
if (_bubbleGroup == null)
{
Debug.LogWarning("BubbleGroup为空");
return;
}
// 先去除富文本标签
var width = _bubbleGroup.EstimateTextWidth(line.RemoveRichTextTags(), _lineText.fontSize);
if (width > maxWidth)
{
_layoutElement.preferredWidth = maxWidth;
}
else
{
_layoutElement.preferredWidth = -1;
}
_layoutElement.minWidth = minWidth;
LayoutRebuilder.ForceRebuildLayoutImmediate(_rect);
}
#if UNITY_EDITOR
[Header("测试参数")] public int testMinWidth;
public int testMaxWidth;
public BubbleStyle testBubbleStyle;
public PivotType testPivotType;
public void LoadStyle()
{
InitRefs();
SetStyle(testBubbleStyle, testPivotType);
_layoutElement.minWidth = testMinWidth;
_layoutElement.preferredWidth = testMaxWidth;
}
public void SaveStyle()
{
if (!testBubbleStyle) return;
InitRefs();
testBubbleStyle.linePadding = _lineText.margin;
testBubbleStyle.lineFontSize = _lineText.fontSize;
testBubbleStyle.actorPadding = _actorName.margin;
testBubbleStyle.actorFontSize = _actorName.fontSize;
testBubbleStyle.BubblePadding = _layoutGroup.padding;
testBubbleStyle.hasActorName = _actorName.gameObject.activeSelf;
}
#endif
}
public interface IBubble
{
public ActorRole Role { get; }
public int Idx { get; }
public event Action OnLineShown;
public void ShowActorName(CharacterVo characterVo);
public void ShowLine(string line);
public bool SkipLine();
public void Hide();
}
}