import init, { add_room, get_palettes, get_preview, load_image, load_game, load_default_game, output, set_brightness, set_dither, set_palette, set_room_name, } from './pkg/pixsy.js'; // stolen from https://ourcodeworld.com/articles/read/189/how-to-create-a-file-and-generate-a-download-with-javascript-in-the-browser-without-a-server function download(filename, text) { let element = document.createElement('a'); element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); element.setAttribute('download', filename); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); } function copyToClipboard() { const button = el("clipboard"); el("output").select(); document.execCommand("copy"); button.innerText = "copied!"; setTimeout(() => { button.innerText = "copy to clipboard"; }, 2000); } function el(id) { return document.getElementById(id); } function pagination(e) { const parent = e.target.parentNode; parent.style.display = "none"; if (e.target.classList.contains("next")) { parent.nextSibling.style.display = "block"; } else if (e.target.classList.contains("prev")) { parent.previousSibling.style.display = "block"; } else if (e.target.classList.contains("start")) { document.getElementById("start").style.display = "block"; } } function readFile(input, callback, type = "text") { if (input.files && input.files[0]) { let reader = new FileReader(); reader.onload = callback; if (type === "text") { reader.readAsText(input.files[0]); } else { reader.readAsDataURL(input.files[0]); } } } async function run() { if (typeof WebAssembly !== "object") { window.location = "http://tinybird.info/image-to-bitsy/old/" } await init(); const buttonAddImage = el("add"); const buttonBackToImage = el("back-to-image"); const buttonCopyToClipboard = el("clipboard") const buttonDownload = el("download"); const buttonGameDataProceed = el("game-data-next"); const buttonImageProceed = el("image-next"); const buttonRoomProceed = el("room-next"); const buttonLoadGame = el("load"); const buttonNewGame = el("new"); const buttonReset = el("reset"); const checkboxDither = el("dither"); const divCroppie = el("crop"); const divNewPalette = el("new-palette"); const inputBrightness = el("brightness"); const inputColourBackground = el("colour-background"); const inputColourForeground = el("colour-foreground"); const inputRoomName = el("room-name"); const selectPalette = el("palette"); const textareaGameDataInput = el("game-data"); const textareaGameDataOutput = el("output"); const croppie = new Croppie(divCroppie, { viewport: {width: 128, height: 128, type: 'square'}, boundary: {width: 256, height: 256}, enableZoom: true, }); // hide all pages except start page for (let page of document.getElementsByClassName('page')) { page.style.display = "none"; } el("start").style.display = "block"; for (let pageButton of document.getElementsByClassName("pagination")) { pageButton.addEventListener('click', pagination); pageButton.addEventListener('touchend', pagination); } // croppie needs to be on screen to work; // halt pagination until we're finished gathering the results buttonImageProceed.removeEventListener("click", pagination); function new_game() { load_default_game(); textareaGameDataInput.value = output(); checkGameData(); // we don't need to look at the default game data, so skip ahead to the image page buttonGameDataProceed.click(); } function clear_game() { textareaGameDataInput.value = ""; checkGameData(); } buttonNewGame.addEventListener("click", new_game); buttonNewGame.addEventListener("touchend", new_game); buttonLoadGame.addEventListener("click", clear_game); buttonLoadGame.addEventListener("touchend", clear_game); // handle game data and image el("game").addEventListener("change", function() { readFile(this, function (e) { textareaGameDataInput.value = e.target.result; checkGameData(); }, "text"); }); function setPaletteDropdown() { const palettes = JSON.parse(get_palettes()); selectPalette.innerHTML = ""; palettes.push({ id: "NEW_PALETTE", name: "new palette" }); for (let palette of palettes) { let option = document.createElement("option"); option.value = palette.id; option.innerText = palette.name; selectPalette.appendChild(option); } } function checkGameData() { let result = load_game(textareaGameDataInput.value) if (result === "Loaded game") { buttonGameDataProceed.removeAttribute("disabled"); setPaletteDropdown(); } else { buttonGameDataProceed.setAttribute("disabled", "disabled"); } } textareaGameDataInput.addEventListener("change", checkGameData); textareaGameDataInput.addEventListener("keyup", checkGameData); checkGameData(); el('image').addEventListener('change', function () { readFile(this, function (e) { croppie.bind({url: e.target.result, zoom: 0}); divCroppie.style.display = "block"; buttonImageProceed.removeAttribute("disabled"); }, "image"); }); function loadPreview() { el("preview").setAttribute("src", get_preview()); } function handleImage() { croppie.result({ type: "base64", size: "viewport", format: "png", }).then((result) => { console.log("Loading image: " + load_image(result)); el("page-image").style.display = "none"; el("page-room" ).style.display = "block"; loadPreview(); }); } buttonImageProceed.addEventListener("click", handleImage); buttonImageProceed.addEventListener("touchend", handleImage); selectPalette.addEventListener("change", () => { set_palette(selectPalette.value, inputColourBackground.value, inputColourForeground.value); if (selectPalette.value === "NEW_PALETTE") { divNewPalette.style.display = "block"; } else { divNewPalette.style.display = "none"; } loadPreview(); }); function updateCustomPalette() { set_palette(selectPalette.value, inputColourBackground.value, inputColourForeground.value); loadPreview(); } inputColourForeground.addEventListener("change", updateCustomPalette); inputColourBackground.addEventListener("change", updateCustomPalette); checkboxDither.addEventListener("change", () => { set_dither(checkboxDither.checked); loadPreview(); }); inputRoomName.addEventListener("change", () => { set_room_name(inputRoomName.value); }); inputBrightness.addEventListener("input", () => { set_brightness(inputBrightness.value); loadPreview(); }); function addRoom() { el("added").innerText = add_room(); textareaGameDataOutput.value = output(); } buttonRoomProceed.addEventListener("click", addRoom); buttonRoomProceed.addEventListener("touchend", addRoom); function handleDownload() { download("output.bitsy", textareaGameDataOutput.value); } buttonCopyToClipboard.addEventListener("click", copyToClipboard); buttonCopyToClipboard.addEventListener("touchend", copyToClipboard); buttonDownload.addEventListener("click", handleDownload); buttonDownload.addEventListener("touchend", handleDownload); function addImage() { textareaGameDataInput.value = textareaGameDataOutput.value; textareaGameDataOutput.value = ""; buttonBackToImage.click(); } buttonAddImage.addEventListener("click", addImage); buttonAddImage.addEventListener("touchend", addImage); // would it be easier just to reload the page? lol function reset() { clear_game(); // todo clear file inputs inputBrightness.value = 0; inputRoomName.value = ""; selectPalette.innerHTML = ""; divNewPalette.style.display = "none"; inputColourBackground.value = "#000000"; inputColourForeground.value = "#ffffff"; checkboxDither.checked = true; } buttonReset.addEventListener("click", reset); buttonReset.addEventListener("touchend", reset); } run();