/// import { Debounce } from "./debounce.js"; import { PlaygroundConsole } from "./playground_console.js"; import { CodeRunner } from "./code_runner.js"; import { AssetEditor } from "./asset_editor.js"; import { AssetProvider } from "./asset_provider.js"; import { Gamelib } from "./gamelib.js"; import { GamelibCompleter } from "./gamelib_completer.js"; import { TextCompleter } from "./text_completer.js"; import { ConsoleInput } from "./console_input.js"; import { ProjectSaveHandler } from "./project_save_handler.js"; const editor = ace.edit("editor"); editor.setTheme("ace/theme/gruvbox"); editor.session.setMode("ace/mode/javascript"); const langTools = ace.require("ace/ext/language_tools"); editor.setOptions({ enableBasicAutocompletion: true, enableLiveAutocompletion: true, copyWithEmptySelection: true, }); langTools.setCompleters([new GamelibCompleter(), new TextCompleter()]); editor.setValue(sessionStorage.getItem("code") ?? editor.getValue(), -1); const playgroundConsole = new PlaygroundConsole( document.querySelector("#console-code"), editor, ); addEventListener("DOMContentLoaded", () => { playgroundConsole.getAdapter().log("Karlkode 1.0"); }); const assetProvider = new AssetProvider(); const assetEditor = new AssetEditor(document.querySelector("#asset-editor-container"), []); const gamelib = new Gamelib( playgroundConsole.getAdapter(), assetProvider, document.querySelector("canvas"), ); globalThis.karlkoder = { lib() { return gamelib.getAdapter(); }, }; const codeRunner = new CodeRunner(playgroundConsole.getAdapter(), gamelib); new ConsoleInput(document.querySelector("#console-input"), playgroundConsole, codeRunner); const runButton = document.querySelector("#run-button"); const toggleAssetEditorButton = document.querySelector("#toggle-asset-editor-button"); const projectName = document.querySelector("#project-name"); const saveButton = document.querySelector("#save-button"); const loadButton = document.querySelector("#load-button"); const exportButton = document.querySelector("#export-button"); const dropZone = document.querySelector("main"); const projectSaveHandler = new ProjectSaveHandler(editor, assetEditor, assetProvider, projectName); const sessionSaveDebounce = new Debounce(1000); editor.addEventListener("change", () => { sessionSaveDebounce.run(() => { sessionStorage.setItem("code", editor.getValue()); }); }); if (sessionStorage.getItem("project-name")) { projectName.value = sessionStorage.getItem("project-name"); } projectName.onchange = () => { sessionStorage.setItem("project-name", projectName.value); }; runButton.onclick = async () => { const code = editor.getValue(); const assets = await assetEditor.getAssets(); gamelib.assetProvider.injectAssets(assets); codeRunner.setCode(code); codeRunner.toggle(); document.querySelector("canvas").focus(); if (codeRunner.isRunning) { runButton.textContent = "✋ Stop"; runButton.classList.add("running"); } else { runButton.textContent = "🏃 Run"; runButton.classList.remove("running"); } }; exportButton.onclick = async () => { projectSaveHandler.exportProject(); }; loadButton.onclick = () => { projectSaveHandler.showLoadFilePrompt(); }; saveButton.onclick = () => { projectSaveHandler.saveFile(); }; addEventListener("keydown", (ev) => { if (ev.ctrlKey && ev.key === "s") { ev.preventDefault(); projectSaveHandler.saveFile(); } }); toggleAssetEditorButton.addEventListener("click", () => assetEditor.toggleEditor()); window.ondragover = (ev) => ev.preventDefault(); window.ondrop = (ev) => ev.preventDefault(); dropZone.onclick = (ev) => ev.preventDefault(); dropZone.ondragover = (ev) => ev.preventDefault(); dropZone.ondrop = async (ev) => { for (const file of ev.dataTransfer.files) { if (file.name.endsWith(".karlkode")) { await projectSaveHandler.loadFromFile(file); continue; } if (file.type.startsWith("image/")) { await assetEditor.addAsset({ name: file.name, file }); continue; } alert("Invalid file: " + file.name); } ev.preventDefault(); };