add a costume editor
This commit is contained in:
@@ -6,6 +6,7 @@ import * as PIXI from "pixi.js-legacy";
|
||||
import pako from "pako";
|
||||
import JSZip from "jszip";
|
||||
import { io } from "socket.io-client";
|
||||
import { openCostumeEditor, closeCostumeEditor } from "./costumeEditor.js";
|
||||
|
||||
import CustomRenderer from "../functions/render.js";
|
||||
import { setupThemeButton } from "../functions/theme.js";
|
||||
@@ -64,6 +65,19 @@ const tabButtons = document.querySelectorAll(".tab-button");
|
||||
const tabContents = document.querySelectorAll(".tab-content");
|
||||
const fullscreenButton = document.getElementById("fullscreen-button");
|
||||
|
||||
// Add this after the costumes-list setup or in your HTML
|
||||
const createCostumeButton = document.createElement('button');
|
||||
createCostumeButton.id = 'create-costume-button';
|
||||
createCostumeButton.className = 'primary';
|
||||
createCostumeButton.innerHTML = '<i class="fa-solid fa-paintbrush"></i> Create New Costume (WORK IN PROGRESS)';
|
||||
createCostumeButton.style.margin = '10px';
|
||||
|
||||
// Insert it before the costumes list
|
||||
const costumesTab = document.getElementById('costumes-tab');
|
||||
if (costumesTab) {
|
||||
costumesTab.insertBefore(createCostumeButton, costumesList);
|
||||
}
|
||||
|
||||
export const BASE_WIDTH = 480;
|
||||
export const BASE_HEIGHT = 360;
|
||||
const MAX_HTTP_BUFFER = 20 * 1024 * 1024;
|
||||
@@ -109,7 +123,7 @@ createPenGraphics();
|
||||
window.projectVariables = {};
|
||||
export const projectVariables = window.projectVariables;
|
||||
window.sprites = [];
|
||||
export const sprites = window.sprites;
|
||||
export let sprites = window.sprites;
|
||||
export let activeSprite = null;
|
||||
window.projectSounds = [];
|
||||
window.projectCostumes = ["default"];
|
||||
@@ -394,7 +408,9 @@ function deleteSprite(id, emit = false) {
|
||||
}
|
||||
});
|
||||
|
||||
sprites = sprites.filter(s => s.id !== sprite.id);
|
||||
window.sprites = sprites.filter(s => s.id !== sprite.id);
|
||||
sprites.length = 0;
|
||||
window.sprites.forEach(s => sprites.push(s));
|
||||
|
||||
workspace.clear();
|
||||
|
||||
@@ -541,7 +557,6 @@ function renderCostumesList() {
|
||||
const oldName = costume.name;
|
||||
costume.name = newName;
|
||||
|
||||
// ADD THIS CODE:
|
||||
const oldIndex = window.projectCostumes.indexOf(oldName);
|
||||
if (oldIndex !== -1 && !window.projectCostumes.includes(newName)) {
|
||||
window.projectCostumes[oldIndex] = newName;
|
||||
@@ -573,11 +588,46 @@ function renderCostumesList() {
|
||||
});
|
||||
}
|
||||
|
||||
// ADD THIS: Edit button
|
||||
const editBtn = document.createElement("button");
|
||||
editBtn.innerHTML = '<i class="fa-solid fa-pen-to-square"></i>';
|
||||
editBtn.className = "button";
|
||||
editBtn.draggable = false;
|
||||
editBtn.title = "Edit costume";
|
||||
editBtn.onclick = () => {
|
||||
openCostumeEditor(costume, async (dataURL) => {
|
||||
if (!dataURL) return;
|
||||
|
||||
// Update the existing costume
|
||||
const newTexture = PIXI.Texture.from(dataURL);
|
||||
costume.texture = newTexture;
|
||||
|
||||
// Update sprite if this is the current costume
|
||||
if (activeSprite.pixiSprite.texture === costume.texture) {
|
||||
activeSprite.pixiSprite.texture = newTexture;
|
||||
}
|
||||
|
||||
renderCostumesList();
|
||||
showNotification({ message: '✓ Costume updated' });
|
||||
|
||||
if (currentSocket && currentRoom) {
|
||||
currentSocket.emit("projectUpdate", {
|
||||
roomId: currentRoom,
|
||||
type: "updateCostume",
|
||||
data: {
|
||||
spriteId: activeSprite.id,
|
||||
name: costume.name,
|
||||
texture: dataURL,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const deleteBtn = createDeleteButton(() => {
|
||||
const deleted = activeSprite.costumes[index];
|
||||
activeSprite.costumes.splice(index, 1);
|
||||
|
||||
// ADD THIS CODE to remove from global array if not used elsewhere:
|
||||
if (deleted) {
|
||||
const existsElsewhere = sprites.some(s =>
|
||||
s.id !== activeSprite.id && s.costumes.some(c => c.name === deleted.name)
|
||||
@@ -593,8 +643,6 @@ function renderCostumesList() {
|
||||
activeSprite.pixiSprite.texture = PIXI.Texture.EMPTY;
|
||||
}
|
||||
renderCostumesList();
|
||||
|
||||
// ADD THIS LINE to refresh toolbox:
|
||||
workspace.updateToolbox(document.getElementById('toolbox'));
|
||||
|
||||
if (currentSocket && currentRoom && deleted) {
|
||||
@@ -611,6 +659,7 @@ function renderCostumesList() {
|
||||
|
||||
costumeContainer.appendChild(img);
|
||||
costumeContainer.appendChild(renameableLabel);
|
||||
costumeContainer.appendChild(editBtn);
|
||||
costumeContainer.appendChild(deleteBtn);
|
||||
costumeContainer.appendChild(sizeLabel);
|
||||
|
||||
@@ -1776,6 +1825,51 @@ loadButton.addEventListener("click", () => {
|
||||
});
|
||||
loadInput.addEventListener("change", loadProject);
|
||||
|
||||
// Create new costume with editor
|
||||
document.getElementById('create-costume-button')?.addEventListener('click', () => {
|
||||
if (!activeSprite) {
|
||||
showNotification({ message: 'Please select a sprite first' });
|
||||
return;
|
||||
}
|
||||
|
||||
openCostumeEditor(null, async (dataURL) => {
|
||||
if (!dataURL || !activeSprite) return;
|
||||
|
||||
const texture = PIXI.Texture.from(dataURL);
|
||||
|
||||
let uniqueName = 'costume';
|
||||
let counter = 1;
|
||||
const nameExists = name => activeSprite.costumes.some(c => c.name === name);
|
||||
|
||||
while (nameExists(uniqueName)) {
|
||||
counter++;
|
||||
uniqueName = `costume_${counter}`;
|
||||
}
|
||||
|
||||
activeSprite.costumes.push({ name: uniqueName, texture });
|
||||
|
||||
if (!window.projectCostumes.includes(uniqueName)) {
|
||||
window.projectCostumes.push(uniqueName);
|
||||
}
|
||||
workspace.updateToolbox(document.getElementById('toolbox'));
|
||||
|
||||
if (currentSocket && currentRoom) {
|
||||
currentSocket.emit("projectUpdate", {
|
||||
roomId: currentRoom,
|
||||
type: "addCostume",
|
||||
data: {
|
||||
spriteId: activeSprite.id,
|
||||
name: uniqueName,
|
||||
texture: dataURL,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
renderCostumesList();
|
||||
showNotification({ message: '✓ Costume created successfully' });
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById("costume-upload").addEventListener("change", e => {
|
||||
const file = e.target.files[0];
|
||||
if (!file || !activeSprite) return;
|
||||
|
||||
Reference in New Issue
Block a user