100 lines
3.6 KiB
JavaScript
100 lines
3.6 KiB
JavaScript
import { promptUpload } from "./prompt_upload.js";
|
|
|
|
export class SpriteEditor {
|
|
constructor(rootEl, sprites) {
|
|
this.list = rootEl.querySelector("#sprite-editor-sprite-list");
|
|
this.editor = rootEl.querySelector("#sprite-editor");
|
|
this.toggleButton = rootEl.querySelector("#toggle-sprite-editor-button");
|
|
this.container = rootEl;
|
|
|
|
this.preview = {};
|
|
this.preview.title = rootEl.querySelector("#sprite-editor-preview-title");
|
|
this.preview.image = rootEl.querySelector("#sprite-editor-preview-image");
|
|
this.preview.snippet = rootEl.querySelector("#sprite-editor-preview-snippet");
|
|
this.sprites = sprites;
|
|
|
|
rootEl.querySelector("#sprite-editor-upload-button").addEventListener("click", () => {
|
|
this.promptUpload();
|
|
});
|
|
|
|
this.renderList();
|
|
}
|
|
|
|
async promptUpload() {
|
|
for (const file of await promptUpload("image/*", true)) {
|
|
const rootName = file.name;
|
|
let fullName = file.name;
|
|
for (let i = 0; this.sprites.some((x) => x.name === fullName); ++i) {
|
|
const extensionIdx = rootName.split("").findLastIndex((x) => x === ".");
|
|
let name = rootName;
|
|
let extension = "";
|
|
if (extensionIdx !== -1) {
|
|
name = rootName.slice(0, extensionIdx);
|
|
extension = rootName.slice(extensionIdx);
|
|
}
|
|
fullName = `${name}-${i}${extension}`;
|
|
}
|
|
this.addSprite({
|
|
name: fullName,
|
|
mime: file.type,
|
|
bytes: await fetch(URL.createObjectURL(file)).then((x) => x.bytes()),
|
|
});
|
|
}
|
|
}
|
|
|
|
addSprite({ name, bytes, mime }) {
|
|
const id = Math.round(Math.random() * 1e6);
|
|
this.sprites.push({ id, bytes, name, mime });
|
|
this.renderList();
|
|
}
|
|
|
|
deleteSprite(id) {
|
|
this.sprites = this.sprites.filter((x) => x.id !== id);
|
|
this.renderList();
|
|
}
|
|
|
|
setPreview(id) {
|
|
const sprite = this.sprites.find((x) => x.id === id);
|
|
this.preview.title.textContent = sprite.name;
|
|
this.preview.image.src = `data:${sprite.mime};base64,${sprite.bytes.toBase64()}`;
|
|
|
|
const sanitizedName = sprite.name.replace(/</g, "<").replace(/&/g, "&");
|
|
this.preview.snippet.innerHTML = "lib.drawSprite(<br>" +
|
|
" x, y,<br>" +
|
|
" width, height,<br>" +
|
|
` "${sanitizedName}"<br>` +
|
|
");";
|
|
}
|
|
|
|
renderList() {
|
|
const children = this.sprites
|
|
.map((sprite) => {
|
|
const listItem = document.createElement("li");
|
|
listItem.classList.add("sprite-editor-list-item");
|
|
const name = document.createElement("span");
|
|
name.textContent = sprite.name;
|
|
name.addEventListener("click", () => {
|
|
this.setPreview(sprite.id);
|
|
});
|
|
listItem.append(name);
|
|
return listItem;
|
|
});
|
|
|
|
this.list.replaceChildren(...children);
|
|
}
|
|
|
|
toggleEditor() {
|
|
if (getComputedStyle(this.editor).display === "none") {
|
|
this.editor.style.display = "block";
|
|
this.container.style.flexGrow = "1";
|
|
this.toggleButton.innerHTML = "›";
|
|
this.toggleButton.setAttribute("expanded", true);
|
|
} else {
|
|
this.editor.style.display = "none";
|
|
this.container.style.flexGrow = "0";
|
|
this.toggleButton.innerHTML = "‹";
|
|
this.toggleButton.removeAttribute("expanded");
|
|
}
|
|
}
|
|
}
|