the abstraction engine
diff --git a/src/css/modal.css b/src/css/modal.css
new file mode 100644
index 0000000..bd6f2a3
--- /dev/null
+++ b/src/css/modal.css
@@ -0,0 +1,67 @@
+/* The Modal (background) */
+.modal {
+ display: none; /* Hidden by default */
+ position: fixed; /* Stay in place */
+ z-index: 1; /* Sit on top */
+ left: 0;
+ top: 0;
+ width: 100%; /* Full width */
+ height: 100%; /* Full height */
+ justify-content: center; /* Center horizontally */
+ align-items: center; /* Center vertically */
+ background-color: rgba(0, 0, 0, 0.4); /* Black w/ opacity */
+ overflow: auto; /* Enable scroll if needed */
+ animation: fadeIn 0.25s; /* Fade in the background */
+}
+
+/* Modal Content */
+.modal-content {
+ display: flex;
+ background-color: #282828; /* Gruvbox background */
+ color: #ebdbb2; /* Gruvbox foreground */
+ margin: auto;
+ padding: 20px;
+ border: 1px solid #928374; /* Gruvbox grey */
+ width: 40%; /* Adjust as needed */
+ box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
+ animation: scaleUp 0.25s; /* Scale animation */
+ border-radius: 8px; /* Rounded corners */
+ justify-content: center; /* Center horizontally */
+}
+
+/* Animations */
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+@keyframes fadeOut {
+ from {
+ opacity: 1;
+ }
+ to {
+ opacity: 0;
+ }
+}
+
+@keyframes scaleUp {
+ from {
+ transform: scale(0.5);
+ }
+ to {
+ transform: scale(1);
+ }
+}
+
+@keyframes scaleDown {
+ from {
+ transform: scale(1);
+ }
+ to {
+ transform: scale(0.5);
+ }
+}
diff --git a/src/css/style.css b/src/css/style.css
index 8f72fce..2ff3cb2 100644
--- a/src/css/style.css
+++ b/src/css/style.css
@@ -1,5 +1,6 @@
@import url("./theme.css");
@import url("./tf.css");
+@import url("./modal.css");
@font-face {
font-family: "scientifica";
diff --git a/src/engine/TheAbstractionEngine.ts b/src/engine/TheAbstractionEngine.ts
index 78d4f88..15ef011 100644
--- a/src/engine/TheAbstractionEngine.ts
+++ b/src/engine/TheAbstractionEngine.ts
@@ -39,9 +39,9 @@ export class TheAbstractionEngine {
const player = new Player();
this.game.addEntity(player);
- const box = new FunctionBox({ x: 3, y: 1 });
+ const box = new FunctionBox({ x: 3, y: 1 }, "λ x . (x)");
this.game.addEntity(box);
- const box2 = new FunctionBox({ x: 4, y: 1 });
+ const box2 = new FunctionBox({ x: 4, y: 1 }, "λ x . (x)");
this.game.addEntity(box2);
}
diff --git a/src/engine/config/constants.ts b/src/engine/config/constants.ts
index 5dcd60c..288513a 100644
--- a/src/engine/config/constants.ts
+++ b/src/engine/config/constants.ts
@@ -54,4 +54,6 @@ export namespace Miscellaneous {
export const GRID_CELL_WIDTH = Math.floor(WIDTH / GRID_COLUMNS);
export const GRID_CELL_HEIGHT = Math.floor(HEIGHT / GRID_ROWS);
+
+ export const MODAL_ID = "modal";
}
diff --git a/src/engine/entities/FunctionBox.ts b/src/engine/entities/FunctionBox.ts
index 393514e..57eeedb 100644
--- a/src/engine/entities/FunctionBox.ts
+++ b/src/engine/entities/FunctionBox.ts
@@ -8,6 +8,7 @@ import {
Sprite,
} from "../components";
import { Coord2D } from "../interfaces";
+import { openModal, closeModal } from "../utils";
export class FunctionBox extends Entity {
private static spriteSpec: SpriteSpec = SPRITE_SPECS.get(
@@ -52,15 +53,23 @@ export class FunctionBox extends Entity {
this.hooks.set(ComponentNames.Highlight, {
add: () => {
- this.addComponent(new Interactable(() => this.viewInsides()));
+ let modalOpen = false;
+ const interaction = () => {
+ if (modalOpen) {
+ modalOpen = false;
+ closeModal();
+ return;
+ }
+ modalOpen = true;
+ openModal(this.code);
+ };
+
+ this.addComponent(new Interactable(interaction));
},
remove: () => {
+ closeModal();
this.removeComponent(ComponentNames.Interactable);
},
});
}
-
- public viewInsides() {
- console.log("I am a function box!");
- }
}
diff --git a/src/engine/systems/Input.ts b/src/engine/systems/Input.ts
index df4d651..3da018d 100644
--- a/src/engine/systems/Input.ts
+++ b/src/engine/systems/Input.ts
@@ -52,6 +52,9 @@ export class Input extends System {
}
interactable.interact();
+ KeyConstants.ActionKeys.get(Action.INTERACT)!.forEach((key) =>
+ this.keyReleased(key),
+ );
}
public handleMovement(entity: Entity) {
diff --git a/src/engine/utils/index.ts b/src/engine/utils/index.ts
index 439e664..78b600e 100644
--- a/src/engine/utils/index.ts
+++ b/src/engine/utils/index.ts
@@ -1,3 +1,4 @@
export * from "./clamp";
export * from "./dotProduct";
export * from "./rotateVector";
+export * from "./modal";
diff --git a/src/engine/utils/modal.ts b/src/engine/utils/modal.ts
new file mode 100644
index 0000000..e7b36b1
--- /dev/null
+++ b/src/engine/utils/modal.ts
@@ -0,0 +1,38 @@
+import { Miscellaneous } from "../config";
+
+let modalOpen = false;
+
+export const openModal = (content: string, id = Miscellaneous.MODAL_ID) => {
+ const modal = document.getElementById(id);
+ if (modal && !modalOpen) {
+ modal.style.display = "flex";
+ modal.style.animation = "fadeIn 0.25s";
+
+ modal.innerHTML = `
${content}
`;
+ const modalContent = document.querySelector
(".modal-content");
+ if (modalContent) {
+ modalContent.style.animation = "scaleUp 0.25s";
+ }
+
+ modalOpen = true;
+ }
+};
+
+export const closeModal = (id = Miscellaneous.MODAL_ID) => {
+ const modal = document.getElementById(id);
+ if (modal && modalOpen) {
+ modal.style.animation = "fadeOut 0.25s";
+
+ const modalContent = document.querySelector(".modal-content");
+ if (modalContent) {
+ modalContent.style.animation = "scaleDown 0.25s";
+ }
+
+ setTimeout(() => {
+ modal.innerHTML = "";
+ modal.style.display = "none";
+
+ modalOpen = false;
+ }, 250);
+ }
+};