FunGame-Godot/scripts/AnimatedRichTextLabel.cs
2025-04-14 21:54:29 +08:00

92 lines
2.5 KiB
C#

using System;
using Godot;
namespace Milimoe.GodotGame;
public partial class AnimatedRichTextLabel : RichTextLabel
{
[Export]
public float CharactersPerSecond { get; set; } = 20; // 每秒显示的字符数
public NovelController NovelController { get; set; } = null; // 是否在小说控制器中
public bool IsAnimationRunning = false; // 动画是否正在运行
private string _fullText; // 完整的文本内容
private float _elapsedTime = 0; // 经过的时间
private int _visibleCharacters = 0; // 当前显示的字符数
private Timer _timer;
public override void _Ready()
{
_timer = GetNode<Timer>("Timer");
_timer.Timeout += OnTimerTimeout;
_fullText = Text; // 保存完整的文本内容
Text = ""; // 清空 RichTextLabel 的初始文本
VisibleCharacters = 0; // 确保初始状态下不显示任何字符
}
public void StartAnimation()
{
_elapsedTime = 0;
_visibleCharacters = 0;
Text = _fullText; // 恢复完整的文本内容
VisibleCharacters = 0; // 确保从头开始显示
IsAnimationRunning = true;
_timer.Start(); // 启动 Timer
}
public void SkipAnimation()
{
if (IsAnimationRunning)
{
VisibleCharacters = _fullText.Length; // 直接显示所有字符
StopAnimation();
}
}
private void StopAnimation()
{
if (IsAnimationRunning)
{
_timer.Stop();
IsAnimationRunning = false;
NovelController.TextAnimationHasFinished();
}
}
public override void _Process(double delta)
{
if (!IsAnimationRunning) return;
if (_timer.IsStopped()) return;
_elapsedTime += (float)delta;
int targetVisibleCharacters = (int)(_elapsedTime * CharactersPerSecond);
if (targetVisibleCharacters > _visibleCharacters)
{
_visibleCharacters = Math.Min(targetVisibleCharacters, _fullText.Length);
VisibleCharacters = _visibleCharacters;
}
if (_visibleCharacters >= _fullText.Length)
{
StopAnimation();
}
}
private void OnTimerTimeout()
{
// 这里可以添加一些逻辑,例如在动画结束后触发一个信号
// 或者执行其他操作
}
public new void SetText(string text)
{
_fullText = text;
Text = "";
VisibleCharacters = 0;
IsAnimationRunning = false;
}
}