diff options
Diffstat (limited to 'src/engine/systems/Modal.ts')
-rw-r--r-- | src/engine/systems/Modal.ts | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/engine/systems/Modal.ts b/src/engine/systems/Modal.ts new file mode 100644 index 0000000..7643a73 --- /dev/null +++ b/src/engine/systems/Modal.ts @@ -0,0 +1,93 @@ +import { Game } from ".."; +import { System, SystemNames } from "."; +import { Miscellaneous, ModalClose, ModalOpen, SOUNDS } from "../config"; +import { ComponentNames, Modal as ModalComponent } from "../components"; +import { Entity } from "../entities"; +import { + CodeConsumer, + CodeEditorInstance, + CodeEditorSingleton, + ModalInstance, + ModalSingleton, +} from "../utils"; + +export interface ModalInitState { + type: "CONTENT" | "CODE_EDITOR"; + contentInit?: { + content: string; + }; + codeInit?: { + code: string; + codeConsumer: CodeConsumer; + readonly?: boolean; + result?: { data?: string; error?: string }; + }; +} + +export class Modal extends System { + private openingEntity: null | Entity = null; + private modalInstance: ModalInstance = ModalSingleton; + private codeEditorInstance: CodeEditorInstance = CodeEditorSingleton; + + constructor() { + super(SystemNames.Modal); + } + + public update(_dt: number, game: Game) { + if (this.openingEntity) { + if (this.openingEntity.hasComponent(ComponentNames.Modal)) { + return; + } + this.closeCallback(); + } + + game.forEachEntityWithComponent(ComponentNames.Modal, (entity) => { + const modalComponent = entity.getComponent<ModalComponent>( + ComponentNames.Modal + ); + if (this.openingEntity) { + return; + } + + this.openingEntity = entity; + SOUNDS.get(ModalOpen.name)!.play(); + + if (modalComponent.initState.type === "CONTENT") { + const content = ` + <div style="text-align:center"> + <div>${modalComponent.initState.contentInit!.content}</div> + <br> + <button id="close">Close</button> + </div>`; + this.modalInstance.open(content); + document + .getElementById("close") + ?.addEventListener("click", this.closeCallback.bind(this)); + } + + if (modalComponent.initState.type === "CODE_EDITOR") { + this.codeEditorInstance.open( + modalComponent.initState.codeInit!.code, + (code) => { + const result = + modalComponent.initState.codeInit!.codeConsumer(code); + if (result.consumed) { + this.closeCallback(); + } + return result; + }, + !!modalComponent.initState.codeInit!.readonly, + modalComponent.initState.codeInit!.result, + ); + } + }); + } + + private closeCallback() { + this.openingEntity = null; + this.modalInstance.vanish(); + this.codeEditorInstance.close(); + document.getElementById(Miscellaneous.CANVAS_ID)!.focus(); + SOUNDS.get(ModalClose.name)!.play(); + } +} |