diff --git a/Monkeydo.mjs b/Monkeydo.mjs index 918319a..1255552 100644 --- a/Monkeydo.mjs +++ b/Monkeydo.mjs @@ -37,11 +37,7 @@ export default class Monkeydo extends MonkeyMaster { async play(manifest = null) { if(!this.ready && !manifest) throw new Error("Can not start playback without a manifest"); - if(manifest) { - const load = this.load(manifest) - load.then(() => this.start()); - return; - } + if(manifest) await this.load(manifest); return await this.start(); } } \ No newline at end of file diff --git a/monkey/Monkey.js b/monkey/Monkey.js index 3e9128b..5ae1df0 100644 --- a/monkey/Monkey.js +++ b/monkey/Monkey.js @@ -5,40 +5,39 @@ importScripts("https://unpkg.com/comlink/dist/umd/comlink.js"); class Monkey { constructor() { this.flags = new Uint8ClampedArray(3); - this.tasks = []; - this.tasksLength = 0; - this.i = 0; - // Runtime task queue - this.queue = { - thisTask: null, - nextTask: null + + this.tasks = { + tasks: [], + length: 0, + target: 0, + _i: 0, + set manifest(manifest) { + this.tasks = manifest; + this.length = this.tasks.length - 1; + }, + get task() { + return this.tasks[this._i]; + }, + step: () => { + this.tasks._i++; + const nextTask = this.tasks.task; + this.tasks.target = performance.now() + nextTask[0]; + } } } - // Task scheduler - next() { - const start = performance.now(); - const self = this; - let task = null; - - // Run task after delay - function frame() { - if(self.flags[0] === 0 || self.flags[2] === 0) return self.abort(); - postMessage(["TASK",task]); - self.i++; - scheduleFrame(); - } - - // Queue the next task - function scheduleFrame() { - task = self.tasks[self.i]; - //const elapsed = Math.round(performance.now() - start); - const wait = task[0] + start; - console.log(wait); - setTimeout(() => requestAnimationFrame(frame),wait); + // Main event loop, runs on every frame + tick() { + if(this === undefined) return false; + if(this.flags[0] === 0 || this.flags[2] === 0) return this.abort(); + + const frame = Math.min(performance.now(),this.tasks.target); + if(frame == this.tasks.target) { + postMessage(["TASK",this.tasks.task]); + this.tasks.step(); } - scheduleFrame(start); + requestAnimationFrame(this.tick.bind(this)); } abort() { @@ -73,9 +72,7 @@ class Monkey { reject("Failed to load manifest"); } } - this.tasks = manifest.tasks; - // Store length as property so we don't have to calculate the offset each iteration of next() - this.tasksLength = manifest.tasks.length - 1; + this.tasks.manifest = manifest.tasks; this.flags[0] = 1; // Manifest loaded: true resolve(); }); diff --git a/monkey/MonkeyMaster.mjs b/monkey/MonkeyMaster.mjs index da3ee63..fd7c35d 100644 --- a/monkey/MonkeyMaster.mjs +++ b/monkey/MonkeyMaster.mjs @@ -47,11 +47,12 @@ export default class MonkeyMaster { const Monkey = Comlink.wrap(worker); this.comlink = await new Monkey(); - // Wait for comlink to initialize proxy and send queued flags + // Wait for comlink to spin up return await new Promise((resolve,reject) => { - if(!this.comlink) reject("Failed to open proxy to worker"); + if(!this.comlink) reject("Failed to establish Comlink with worker"); this.ready = true; + // Send queued flags when worker is ready this.queue.sendAllFlags(); resolve(); }); @@ -132,6 +133,6 @@ export default class MonkeyMaster { if(playing > 0) return; await this.setFlag("playing",loop); - return await this.comlink.next(); + return await this.comlink.tick(); } } \ No newline at end of file