-
Notifications
You must be signed in to change notification settings - Fork 2
/
scene.ts
50 lines (39 loc) · 1.23 KB
/
scene.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// A scene runner for Motion.
import type { Action, ActionIterator } from "./action.js"
import { signal, untrack } from "./signal.js"
import { View } from "./view.js"
export class Scene {
private readonly view = new View(this)
private action: ActionIterator
readonly frame = signal(0)
constructor(private readonly initializer: (view: View) => Action) {
this.action = initializer(this.view)[Symbol.iterator]()
}
/** Renders the current state of the scene onto a canvas. */
async render(context: CanvasRenderingContext2D): Promise<void> {
context.clearRect(0, 0, context.canvas.width, context.canvas.height)
context.save()
for (const node of this.view.nodes) {
node?.render(context)
}
context.restore()
}
/**
* Advances the state of this scene one frame forward.
*
* @returns A boolean indicating whether the scene has completed.
*/
async next(): Promise<boolean> {
const done = this.action.next().done || false
if (!done) {
this.frame(untrack(this.frame) + 1)
}
return done
}
/** Resets the state of this scene. */
async reset(): Promise<void> {
this.frame(0)
this.view.clear()
this.action = this.initializer(this.view)[Symbol.iterator]()
}
}