diff --git a/extensions/Lily/LooksPlus.js b/extensions/Lily/LooksPlus.js index 2a7bc3bfe5..c987b334d6 100644 --- a/extensions/Lily/LooksPlus.js +++ b/extensions/Lily/LooksPlus.js @@ -20,6 +20,30 @@ return true; }; + /** + * @param {RenderWebGL.SVGSkin} svgSkin + * @returns {Promise} + */ + const svgSkinFinishedLoading = (svgSkin) => + new Promise((resolve) => { + if (svgSkin._svgImageLoaded) { + resolve(); + return; + } + + const handleEvent = () => { + cleanup(); + resolve(); + }; + const cleanup = () => { + svgSkin._svgImage.removeEventListener("load", handleEvent); + svgSkin._svgImage.removeEventListener("error", handleEvent); + }; + + svgSkin._svgImage.addEventListener("load", handleEvent); + svgSkin._svgImage.addEventListener("error", handleEvent); + }); + /** * @param {VM.BlockUtility} util * @param {unknown} targetName @@ -176,6 +200,7 @@ opcode: "replaceCostumeContent", blockType: Scratch.BlockType.COMMAND, text: Scratch.translate("set [TYPE] for [COSTUME] to [CONTENT]"), + hideFromPalette: true, // needed for compatibility, also superceeded by skins arguments: { TYPE: { type: Scratch.ArgumentType.STRING, @@ -192,6 +217,21 @@ }, extensions: ["colours_looks"], }, + { + opcode: "replaceCostumeContentNew", + blockType: Scratch.BlockType.COMMAND, + text: Scratch.translate("set svg for [COSTUME] to [CONTENT]"), + arguments: { + COSTUME: { + type: Scratch.ArgumentType.COSTUME, + }, + CONTENT: { + type: Scratch.ArgumentType.STRING, + defaultValue: "", + }, + }, + extensions: ["colours_looks"], + }, { opcode: "restoreCostumeContent", blockType: Scratch.BlockType.COMMAND, @@ -483,6 +523,32 @@ } } + async replaceCostumeContentNew(args, util) { + const costumeIndex = this.getCostumeInput(args.COSTUME, util.target); + const costume = util.target.sprite.costumes[costumeIndex]; + if (!costume) { + console.error("Costume doesn't exist"); + return; + } + + //This is here to ensure no changes are made to bitmap costumes, as changes are irreversible + //Check will be removed when it's possible to edit bitmap skins + const format = costume.asset.assetType.runtimeFormat; + if (format !== "svg") { + console.error("Costume is not vector"); + return; + } + + const content = args.CONTENT; + try { + renderer.updateSVGSkin(costume.skinId, Scratch.Cast.toString(content)); + renderer._allSkins[costume.skinId].differsFromAsset = true; + await svgSkinFinishedLoading(renderer._allSkins[costume.skinId]); + } catch (e) { + console.error(e); + } + } + restoreCostumeContent(args, util) { const costumeIndex = this.getCostumeInput(args.COSTUME, util.target); const costume = util.target.sprite.costumes[costumeIndex];