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) : ''
);
};