Add clip player logic

This commit is contained in:
2022-05-01 12:34:03 +08:00
parent a0a1b52b3f
commit a0547095e2
6 changed files with 237 additions and 18 deletions
+144 -1
View File
@@ -1,6 +1,6 @@
import { Model } from "@Model/Model";
import { Emitter } from "@Model/Emitter";
import { Clip } from "@Model/Clip";
import { Clip, IFrame } from "@Model/Clip";
enum ActuatorModel {
Play = 1,
@@ -45,6 +45,21 @@ class Actuator extends Emitter<IActuatorEvent> {
*/
public recordClip?: Clip;
/**
* 播放剪辑
*/
public playClip?: Clip;
/**
* 播放帧
*/
public playFrame?: IFrame;
/**
* 播放帧数
*/
public playFrameId: number = 0;
/**
* 开始录制
*/
@@ -76,6 +91,98 @@ class Actuator extends Emitter<IActuatorEvent> {
this.mod = ActuatorModel.View;
}
public startPlay(clip: Clip) {
// 如果仿真正在进行,停止仿真
if (this.start()) this.start(false);
// 如果正在录制,阻止播放
if (this.mod === ActuatorModel.Record) {
return;
}
// 如果正在播放,暂停播放
if (this.mod === ActuatorModel.Play) {
this.pausePlay();
}
// 设置播放对象
this.playClip = clip;
// 设置播放帧数
this.playFrameId = 0;
this.playFrame = clip.frames[this.playFrameId];
// 播放第一帧
clip.play(this.playFrame);
// 激发时钟状态事件
this.emit("startChange", true);
}
public endPlay() {
// 如果正在播放,暂停播放
if (this.mod === ActuatorModel.Play) {
this.pausePlay();
}
// 更新模式
this.mod = ActuatorModel.View;
// 清除状态
this.playClip = undefined;
this.playFrameId = 0;
this.playFrame = undefined;
// 渲染模型
this.model.draw();
// 激发时钟状态事件
this.emit("startChange", false);
}
/**
* 是否播放完毕
*/
public isPlayEnd() {
if (this.playClip && this.playFrame) {
if (this.playFrameId >= (this.playClip.frames.length - 1)) {
return true;
} else {
return false;
}
} else {
return true;
}
}
public playing() {
// 如果播放完毕了,从头开始播放
if (this.isPlayEnd() && this.playClip) {
this.startPlay(this.playClip);
}
// 更新模式
this.mod = ActuatorModel.Play;
// 启动播放时钟
this.playTicker();
// 激发时钟状态事件
this.emit("startChange", false);
}
public pausePlay() {
// 更新模式
this.mod = ActuatorModel.View;
// 激发时钟状态事件
this.emit("startChange", false);
}
/**
* 主时钟状态控制
*/
@@ -108,6 +215,42 @@ class Actuator extends Emitter<IActuatorEvent> {
public tickerType: 1 | 2 = 2;
private playTickerTimer?: number;
/**
* 播放时钟
*/
private playTicker() {
if (this.playClip && this.playFrame && this.mod === ActuatorModel.Play) {
// 播放当前帧
this.playClip.play(this.playFrame);
// 没有完成播放,继续播放
if (!this.isPlayEnd()) {
// 跳转值下一帧
this.playFrameId ++;
this.playFrame = this.playClip.frames[this.playFrameId];
this.emit("record", this.playFrame.duration);
// 清除计时器,保证时钟唯一性
clearTimeout(this.playTickerTimer);
// 延时
this.playTickerTimer = setTimeout(() => {
this.playTicker();
}, this.playFrame.duration * 1000) as any;
} else {
this.pausePlay();
}
} else {
this.pausePlay();
}
}
private ticker(t: number) {
if (this.startFlag && t !== 0) {
if (this.lastTime === 0) {
+30 -5
View File
@@ -15,6 +15,7 @@ interface IDrawCommand {
interface IFrame {
commands: IDrawCommand[];
duration: number;
process: number;
}
/**
@@ -81,17 +82,41 @@ class Clip {
}
}
const dt = this.frames.length <= 0 ? 0 : t;
this.time += dt;
const frame: IFrame = {
commands: commands,
duration: t
duration: dt,
process: this.time
};
this.time += t;
this.frames.push(frame);
return frame;
}
/**
* 播放一帧
*/
public play(frame: IFrame) {
// 清除全部渲染状态
this.model.renderer.clean();
// 执行全部渲染指令
for (let i = 0; i < frame.commands.length; i++) {
const command: IDrawCommand = frame.commands[i];
if (command.type === "cube") {
this.model.renderer.cube(command.id, command.position, command.radius, command.parameter);
}
else if (frame.commands[i].type === "points") {
this.model.renderer.points(command.id, command.data, command.parameter);
}
}
}
public equal(clip?: Clip) {
return clip === this || clip?.id === this.id;
}
@@ -102,4 +127,4 @@ class Clip {
}
}
export { Clip };
export { Clip, IFrame };