diff --git a/HISTORY.md b/HISTORY.md index 3bafb6c5..e6b33afa 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -46,6 +46,7 @@ * threads: clear "answer" on ASK nothing/falsy * byob, blocks: export block definition from inside the block editor * objects: added "code" field to Costume constructor +* objects, gui, extensions, store: support blocks embedded into costumes (under construction) ### 2022-04-19 * threads: ASK nothing or a falsy value terminates the thread currently displaying a question diff --git a/src/extensions.js b/src/extensions.js index a983f698..e2445b63 100644 --- a/src/extensions.js +++ b/src/extensions.js @@ -29,11 +29,12 @@ /*global modules, List, StageMorph, Costume, SpeechSynthesisUtterance, Sound, IDE_Morph, CamSnapshotDialogMorph, SoundRecorderDialogMorph, isSnapObject, nop, -Color, Process, contains, localize, SnapTranslator, isString, detect*/ +Color, Process, contains, localize, SnapTranslator, isString, detect, +SVG_Costume*/ /*jshint esversion: 11, bitwise: false*/ -modules.extensions = '2022-April-07'; +modules.extensions = '2022-April-20'; // Global stuff @@ -668,6 +669,24 @@ SnapExtensions.primitives.set( } ); +// Costumes (cst_): + +SnapExtensions.primitives.set( + // experimental, will probably be taken out again, don't rely on this + 'cst_code(cst, code)', + function (cst, code, proc) { + var ide = this.parentThatIsA(IDE_Morph); + proc.assertType(cst, 'costume'); + proc.assertType(code, 'text'); + if (cst instanceof SVG_Costume) { + throw new Error('option currently not supported for SVG costumes'); + } + cst.code = code || null; + cst.version = Date.now(); + ide.recordUnsavedChanges(); + } +); + // Variables (var_): SnapExtensions.primitives.set( diff --git a/src/gui.js b/src/gui.js index 7a27b060..531d788a 100644 --- a/src/gui.js +++ b/src/gui.js @@ -86,7 +86,7 @@ BlockVisibilityDialogMorph, ThreadManager*/ // Global stuff //////////////////////////////////////////////////////// -modules.gui = '2022-April-06'; +modules.gui = '2022-April-20'; // Declarations @@ -9919,11 +9919,13 @@ CostumeIconMorph.prototype.init = function (aCostume) { }; CostumeIconMorph.prototype.createThumbnail = function () { - var txt; + var watermark, txt; SpriteIconMorph.prototype.createThumbnail.call(this); - if (this.object instanceof SVG_Costume) { + watermark = this.object instanceof SVG_Costume ? 'svg' + : (this.object.code ? '' : null); + if (watermark) { txt = new StringMorph( - 'svg', + watermark, this.fontSize * 0.8, this.fontStyle, false, @@ -9970,6 +9972,9 @@ CostumeIconMorph.prototype.userMenu = function () { menu.addItem("duplicate", "duplicateCostume"); menu.addItem("delete", "removeCostume"); menu.addLine(); + if (this.object.code) { + menu.addItem("get blocks", "importCode"); + } menu.addItem("export", "exportCostume"); return menu; }; @@ -10049,6 +10054,10 @@ CostumeIconMorph.prototype.removeCostume = function () { } }; +CostumeIconMorph.prototype.importCode = function () { + this.parentThatIsA(IDE_Morph).droppedText(this.object.code); +}; + CostumeIconMorph.prototype.exportCostume = function () { var ide = this.parentThatIsA(IDE_Morph); if (this.object instanceof SVG_Costume) { diff --git a/src/objects.js b/src/objects.js index 03e30820..c5b03eb7 100644 --- a/src/objects.js +++ b/src/objects.js @@ -10414,7 +10414,7 @@ function Costume(canvas, name, rotationCenter, noFit, maxExtent) { if (!noFit) {this.shrinkToFit(maxExtent || this.maxExtent()); } this.name = name || null; this.rotationCenter = rotationCenter || this.center(); - this.code = null; + this.code = null; // must be a string or null this.version = Date.now(); // for observer optimization this.loaded = null; // for de-serialization only } diff --git a/src/store.js b/src/store.js index a5f34d3c..36ccf3c7 100644 --- a/src/store.js +++ b/src/store.js @@ -63,7 +63,7 @@ Project*/ // Global stuff //////////////////////////////////////////////////////// -modules.store = '2022-April-05'; +modules.store = '2022-April-20'; // XML_Serializer /////////////////////////////////////////////////////// /* @@ -1651,6 +1651,12 @@ SnapSerializer.prototype.loadValue = function (model, object) { context.drawImage(image, 0, 0); v.contents = canvas; v.version = +new Date(); + if (Object.prototype.hasOwnProperty.call( + model.attributes, + 'code' + )) { + v.code = model.attributes.code; + } if (typeof v.loaded === 'function') { v.loaded(); } else { @@ -1977,12 +1983,13 @@ Costume.prototype[XML_Serializer.prototype.mediaDetectionProperty] = true; Costume.prototype.toXML = function (serializer) { return serializer.format( - '', + '', this.name, this.rotationCenter.x, this.rotationCenter.y, this instanceof SVG_Costume ? this.contents.src - : normalizeCanvas(this.contents).toDataURL('image/png') + : normalizeCanvas(this.contents).toDataURL('image/png'), + this.code ? serializer.format(' code="@"', this.code) : '' ); };