diff --git a/source/Model/Actuator.ts b/source/Model/Actuator.ts index 0417357..47dfd04 100644 --- a/source/Model/Actuator.ts +++ b/source/Model/Actuator.ts @@ -1,5 +1,13 @@ import { Model } from "@Model/Model"; import { Emitter } from "@Model/Emitter"; +import { Clip } from "@Model/Clip"; + +enum ActuatorModel { + Play = 1, + Record = 2, + View = 3, + Offline = 4 +} interface IActuatorEvent { startChange: boolean; @@ -26,6 +34,43 @@ class Actuator extends Emitter { */ private startFlag: boolean = false; + /** + * 模式 + */ + public mod: ActuatorModel = ActuatorModel.View; + + /** + * 录制剪辑 + */ + public recordClip?: Clip; + + /** + * 开始录制 + */ + public startRecord(clip: Clip) { + + // 记录录制片段 + this.recordClip = clip; + + // 如果仿真未开启,开启仿真 + if (!this.start()) this.start(true); + + // 设置状态 + this.mod = ActuatorModel.Record; + } + + /** + * 结束录制 + */ + public endRecord() { + + // 如果仿真未停止,停止仿真 + if (this.start()) this.start(false); + + // 设置状态 + this.mod = ActuatorModel.View; + } + /** * 主时钟状态控制 */ @@ -72,13 +117,29 @@ class Actuator extends Emitter { } else { this.alignTimer += durTime; if (this.alignTimer > (1 / this.fps)) { + + // 更新模型 this.model.update(this.alignTimer * this.speed); + + // 绘制模型 + this.model.draw(); + + // 录制模型 + if ( + this.mod === ActuatorModel.Record || + this.mod === ActuatorModel.Offline + ) { + this.recordClip?.record(this.alignTimer * this.speed); + } + this.emit("loop", this.alignTimer); this.alignTimer = 0; } } } - } else { + } + + else { this.emit("loop", Infinity); } } @@ -122,4 +183,4 @@ class Actuator extends Emitter { } } -export { Actuator } \ No newline at end of file +export { Actuator, ActuatorModel } \ No newline at end of file diff --git a/source/Model/Clip.ts b/source/Model/Clip.ts index 3c4df89..df8dfcf 100644 --- a/source/Model/Clip.ts +++ b/source/Model/Clip.ts @@ -1,4 +1,5 @@ import { IAnyObject, Model } from "@Model/Model"; +import { v4 as uuid } from "uuid"; import { Group } from "@Model/Group"; import { Range } from "@Model/Range"; @@ -21,6 +22,8 @@ interface IFrame { */ class Clip { + public id: string; + /** * 用户自定义名称 */ @@ -78,10 +81,13 @@ class Clip { return frame; } - + public equal(clip?: Clip) { + return clip === this || clip?.id === this.id; + } public constructor(model: Model) { this.model = model; + this.id = uuid(); } } diff --git a/source/Model/Model.ts b/source/Model/Model.ts index 281aea0..83012fa 100644 --- a/source/Model/Model.ts +++ b/source/Model/Model.ts @@ -23,6 +23,7 @@ type ModelEvent = { objectChange: CtrlObject[]; individualChange: Group; behaviorChange: IAnyBehavior; + clipChange: Clip[]; }; /** @@ -331,8 +332,51 @@ class Model extends Emitter { } } + /** + * 剪辑数据 + */ public clipPool: Clip[] = []; + /** + * 新建剪辑片段 + */ + public addClip(name?: string): Clip { + let newClip = new Clip(this); + newClip.name = name ?? ""; + this.clipPool.push(newClip); + console.log(`Model: Create clip ${name ?? newClip.id}`); + this.emit("clipChange", this.clipPool); + return newClip; + } + + /** + * 删除一个剪辑片段 + */ + public deleteClip(name: ObjectID | Clip) { + let deletedClip: Clip | undefined; + let index = 0; + + for (let i = 0; i < this.clipPool.length; i++) { + if (name instanceof Clip) { + if (this.clipPool[i].equal(name)) { + deletedClip = this.clipPool[i]; + index = i; + } + } + + else if (name === this.clipPool[i].id) { + deletedClip = this.clipPool[i]; + index = i; + } + } + + if (deletedClip) { + this.behaviorPool.splice(index, 1); + console.log(`Model: Delete clip ${deletedClip.name ?? deletedClip.id}`); + this.emit("clipChange", this.clipPool); + } + } + /** * 渲染器 */ @@ -350,7 +394,7 @@ class Model extends Emitter { /** * 更新渲染数据 */ - public update(t: number, skipDraw: boolean = false) { + public update(t: number) { // 第一轮更新 for (let i = 0; i < this.objectPool.length; i++) { @@ -375,10 +419,6 @@ class Model extends Emitter { object.runner(t, "finalEffect"); } } - - if (!skipDraw) { - this.draw(); - } } public draw() {