using Godot; using System; using System.Timers; using Cysharp.Threading.Tasks; namespace BITKit; /// /// 默认的String数据播放器,主要应用于播放json /// public partial class DataPlayer : Node { //参数 /// /// 当前帧 /// [Export] public int CurrentFrame { get => _currentFrame; set => _currentFrame = Math.Clamp(value, 0, Values?.Length-1 ?? 0); } /// /// 播放帧率 /// [Export] private int frameRate = 60; [Export] private string timeFormat="mm:ss:fff"; /// /// 基于帧率的每帧播放数据 /// [Signal] public delegate void OnProcessPlayEventHandler(string value); /// /// 开始播放回调 /// [Signal] public delegate void OnPlayEventHandler(); /// /// 停止播放回调 /// [Signal] public delegate void OnStopEventHandler(); /// /// 暂停回调 /// [Signal] public delegate void OnPauseEventHandler(); /// /// 播放和暂停回调 /// [Signal] public delegate void OnPlayOrPauseEventHandler(bool isPlaying); /// /// 设置总播放时间的回调 /// [Signal] public delegate void OnSetTotalTimeEventHandler(string dateTimeString); /// /// 设置当前播放时间的回调 /// [Signal] public delegate void OnSetPlaybackTimeEventHandler(string dateTimeString); /// /// 设置标准化播放时间的回调 /// [Signal] public delegate void OnSetNormalizeTimeEventHandler(double normalizeTime); /// /// 是否正在播放 /// public bool IsPlaying { get; protected set; } /// /// 是否已暂停播放 /// public bool IsPaused { get; protected set; } /// /// 内部计时器 /// private readonly System.Timers.Timer timer = new(); /// /// 内部数组 /// private string[] Values; //内部当前帧 private int _currentFrame; public override void _Ready() { timer.Elapsed += Play; EmitSignal(nameof(OnStop)); } /// /// 播放 /// /// 播放数据的数组 public bool Play(string[] values) { if (values?.Length is 0) return false; if (values?.Length != Values?.Length) { CurrentFrame = 0; } Values = values; timer.Interval = TimeSpan.FromSeconds(1f / frameRate).Milliseconds; Play(); timer.Start(); var totalTime = new DateTime().AddSeconds((float)Values!.Length / frameRate); EmitSignal(nameof(OnSetTotalTime), totalTime.ToString(timeFormat)); return true; } /// /// 播放(在暂停时) /// /// public bool Play() { IsPaused = false; IsPlaying = true; return true; } /// /// 停止播放 /// /// public bool Stop() { if (!IsPlaying) return false; timer.Stop(); IsPlaying = IsPaused = false; EmitSignal(nameof(OnStop)); return true; } /// /// 暂停播放 /// /// public bool Pause() { if (!IsPlaying) return false; IsPaused = true; return true; } /// /// 继续播放或暂停播放 /// /// public void PlayOrPause() { PlayOrPause(!IsPaused); } public void PlayOrPause(bool play) { IsPaused = !play; EmitSignal(nameof(OnPlayOrPause), play); } //设置标准化播放时间(0-1进度) public void SetNormalizeTime(float normalizeTime) { CurrentFrame = (int)(Values.Length * normalizeTime); Process(CurrentFrame); } public void SetNormalizeTimeThen(float normalizeTime, bool play) { SetNormalizeTime(normalizeTime); PlayOrPause(play); } protected override void Dispose(bool disposing) { timer.Stop(); timer.Dispose(); } /// /// 内部调用方法 /// /// /// protected virtual async void Play(object sender, ElapsedEventArgs e) { //等待返回主线程 await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext); if (IsPaused) return; //如果超过了播放长度,停止播放 if (CurrentFrame >= Values?.Length-1) { Stop(); return; } EmitSignal(nameof(OnPlay)); Process(CurrentFrame++); } private void Process(int currentFrame) { //获取当前播放信息 var current = Values?[currentFrame]; var currentNormalizeTime = (float)CurrentFrame / Values!.Length; var currentTime = new DateTime().AddSeconds((float)CurrentFrame / frameRate); //调用信号 EmitSignal(nameof(OnProcessPlay), current); EmitSignal(nameof(OnSetPlaybackTime), currentTime.ToString(timeFormat)); EmitSignal(nameof(OnSetNormalizeTime), currentNormalizeTime); //设置Meta SetMeta(nameof(OnProcessPlay),current); SetMeta(nameof(OnSetNormalizeTime),currentNormalizeTime); } }