fledgling/src/vnmodal.ts

130 lines
2.4 KiB
TypeScript

import { D, I } from "./engine/public.ts";
import { AlignX, AlignY, Point } from "./engine/datatypes.ts";
import { FG_BOLD } from "./colors.ts";
import { withCamera } from "./layout.ts";
import { VNScene, VNSceneMessage, VNScenePart } from "./vnscene.ts";
const WIDTH = 384;
const HEIGHT = 384;
export class VNModal {
#scene: VNScene | null;
#nextIndex = 0;
#cathexis: SceneCathexis | null;
constructor() {
this.#scene = null;
this.#nextIndex = 0;
this.#cathexis = null;
}
get blocksHud(): boolean {
return true;
}
get isShown(): boolean {
return this.#scene != null;
}
play(scene: VNScene) {
this.#scene = scene;
this.#nextIndex = 0;
this.#cathexis = null;
this.#fixCathexis();
}
#fixCathexis() {
while (true) {
if (this.#cathexis?.isDone()) {
this.#cathexis = null;
}
if (this.#cathexis != null) {
return;
}
if (this.#scene == null) {
return;
}
if (this.#cathexis == null) {
let ix = this.#nextIndex;
if (ix < this.#scene?.length) {
this.#cathexis = createCathexis(this.#scene[ix]);
this.#nextIndex += 1;
} else {
this.#scene = null;
}
}
}
}
update() {
this.#fixCathexis();
withCamera("FullscreenPopover", () => this.#update());
}
draw() {
withCamera("FullscreenPopover", () => this.#draw());
}
#update() {
this.#cathexis?.update();
}
#draw() {
this.#cathexis?.draw();
}
}
interface SceneCathexis {
isDone(): boolean;
update(): void;
draw(): void;
}
function createCathexis(part: VNScenePart): SceneCathexis {
switch (part.type) {
case "message":
return new SceneMessageCathexis(part);
}
}
class SceneMessageCathexis {
#message: VNSceneMessage;
#done: boolean;
#gotOneFrame: boolean;
constructor(message: VNSceneMessage) {
this.#message = message;
this.#done = false;
this.#gotOneFrame = false;
}
isDone() {
return this.#done;
}
update() {
let firstFrame = !this.#gotOneFrame;
this.#gotOneFrame = true;
// TODO: SFX
if (!firstFrame && I.isAnythingPressed()) {
this.#done = true;
}
}
draw() {
D.drawText(this.#message.text, new Point(WIDTH / 2, HEIGHT / 2), FG_BOLD, {
alignX: AlignX.Center,
alignY: AlignY.Middle,
forceWidth: WIDTH,
});
}
}
let active: VNModal = new VNModal();
export function getVNModal() {
return active;
}