130 lines
2.4 KiB
TypeScript
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;
|
|
}
|