iFactory.Godot/BITKit/Scripts/Data/DataPlayer.cs

237 lines
5.7 KiB
C#

using Godot;
using System;
using System.Timers;
using Cysharp.Threading.Tasks;
namespace BITKit;
/// <summary>
/// 默认的String数据播放器,主要应用于播放json
/// </summary>
public partial class DataPlayer : Node
{
//参数
/// <summary>
/// 当前帧
/// </summary>
[Export]
public int CurrentFrame
{
get => _currentFrame;
set => _currentFrame = Math.Clamp(value, 0, Values?.Length-1 ?? 0);
}
/// <summary>
/// 播放帧率
/// </summary>
[Export] private int frameRate = 60;
[Export] private string timeFormat="mm:ss:fff";
/// <summary>
/// 基于帧率的每帧播放数据
/// </summary>
[Signal]
public delegate void OnProcessPlayEventHandler(string value);
/// <summary>
/// 开始播放回调
/// </summary>
[Signal]
public delegate void OnPlayEventHandler();
/// <summary>
/// 停止播放回调
/// </summary>
[Signal]
public delegate void OnStopEventHandler();
/// <summary>
/// 暂停回调
/// </summary>
[Signal]
public delegate void OnPauseEventHandler();
/// <summary>
/// 播放和暂停回调
/// </summary>
[Signal]
public delegate void OnPlayOrPauseEventHandler(bool isPlaying);
/// <summary>
/// 设置总播放时间的回调
/// </summary>
[Signal]
public delegate void OnSetTotalTimeEventHandler(string dateTimeString);
/// <summary>
/// 设置当前播放时间的回调
/// </summary>
[Signal]
public delegate void OnSetPlaybackTimeEventHandler(string dateTimeString);
/// <summary>
/// 设置标准化播放时间的回调
/// </summary>
[Signal]
public delegate void OnSetNormalizeTimeEventHandler(double normalizeTime);
/// <summary>
/// 是否正在播放
/// </summary>
public bool IsPlaying { get; protected set; }
/// <summary>
/// 是否已暂停播放
/// </summary>
public bool IsPaused { get; protected set; }
/// <summary>
/// 内部计时器
/// </summary>
private readonly System.Timers.Timer timer = new();
/// <summary>
/// 内部数组
/// </summary>
private string[] Values;
//内部当前帧
private int _currentFrame;
public override void _Ready()
{
timer.Elapsed += Play;
EmitSignal(nameof(OnStop));
}
/// <summary>
/// 播放
/// </summary>
/// <param name="values">播放数据的数组</param>
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;
}
/// <summary>
/// 播放(在暂停时)
/// </summary>
/// <returns></returns>
public bool Play()
{
IsPaused = false;
IsPlaying = true;
return true;
}
/// <summary>
/// 停止播放
/// </summary>
/// <returns></returns>
public bool Stop()
{
if (!IsPlaying) return false;
timer.Stop();
IsPlaying = IsPaused = false;
EmitSignal(nameof(OnStop));
return true;
}
/// <summary>
/// 暂停播放
/// </summary>
/// <returns></returns>
public bool Pause()
{
if (!IsPlaying) return false;
IsPaused = true;
return true;
}
/// <summary>
/// 继续播放或暂停播放
/// </summary>
/// <returns></returns>
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();
}
/// <summary>
/// 内部调用方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}