From ca9445c245d6c36f9a53ff3afeef47ff6920b59b Mon Sep 17 00:00:00 2001 From: jmoenig Date: Mon, 31 Mar 2014 12:01:03 +0200 Subject: experimental “wardrobe” and “jukebox” reporters in dev mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tentative preparations for first-class costumes and sounds --- history.txt | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'history.txt') diff --git a/history.txt b/history.txt index 2096b08..4c4201e 100755 --- a/history.txt +++ b/history.txt @@ -2103,3 +2103,7 @@ ______ * Widgets: new “promptVector” dialog box feature * GUI: Use new vector prompter for stage dimensions * German translation update + +140331 +------ +* Objects: experimental “wardrobe” and “jukebox” reporters in dev mode -- cgit v1.3.1 From 6fd93533ecb01c27589bfe569d8e22013a77f65c Mon Sep 17 00:00:00 2001 From: jmoenig Date: Mon, 31 Mar 2014 13:09:31 +0200 Subject: display costume thumbnails in speech/thought/value bubbles and watcher cells --- blocks.js | 8 +++++++- history.txt | 1 + objects.js | 12 ++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'history.txt') diff --git a/blocks.js b/blocks.js index 480545d..f0ddd93 100644 --- a/blocks.js +++ b/blocks.js @@ -155,7 +155,7 @@ DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph, Costume*/ // Global stuff //////////////////////////////////////////////////////// -modules.blocks = '2014-February-11'; +modules.blocks = '2014-March-31'; var SyntaxElementMorph; @@ -1635,6 +1635,12 @@ SyntaxElementMorph.prototype.showBubble = function (value) { morphToShow.silentSetWidth(img.width); morphToShow.silentSetHeight(img.height); morphToShow.image = img; + } else if (value instanceof Costume) { + img = value.thumbnail(new Point(40, 40)); + morphToShow = new Morph(); + morphToShow.silentSetWidth(img.width); + morphToShow.silentSetHeight(img.height); + morphToShow.image = img; } else if (value instanceof Context) { img = value.image(); morphToShow = new Morph(); diff --git a/history.txt b/history.txt index 4c4201e..1399ba6 100755 --- a/history.txt +++ b/history.txt @@ -2107,3 +2107,4 @@ ______ 140331 ------ * Objects: experimental “wardrobe” and “jukebox” reporters in dev mode +* Blocks, Objects: display costume thumbnails in speech/thought/value bubbles and watcher cells diff --git a/objects.js b/objects.js index 37daa69..a6d2c9a 100644 --- a/objects.js +++ b/objects.js @@ -5058,6 +5058,12 @@ SpriteBubbleMorph.prototype.dataAsMorph = function (data) { contents.silentSetWidth(img.width); contents.silentSetHeight(img.height); contents.image = img; + } else if (data instanceof Costume) { + img = data.thumbnail(new Point(40, 40)); + contents = new Morph(); + contents.silentSetWidth(img.width); + contents.silentSetHeight(img.height); + contents.image = img; } else if (data instanceof HTMLCanvasElement) { contents = new Morph(); contents.silentSetWidth(data.width); @@ -5900,6 +5906,12 @@ CellMorph.prototype.drawNew = function () { this.contentsMorph.silentSetWidth(img.width); this.contentsMorph.silentSetHeight(img.height); this.contentsMorph.image = img; + } else if (this.contents instanceof Costume) { + img = this.contents.thumbnail(new Point(40, 40)); + this.contentsMorph = new Morph(); + this.contentsMorph.silentSetWidth(img.width); + this.contentsMorph.silentSetHeight(img.height); + this.contentsMorph.image = img; } else if (this.contents instanceof List) { if (this.isCircular()) { this.contentsMorph = new TextMorph( -- cgit v1.3.1 From ce3340e623fd0f03ecb15de5ec54eda8113c7c67 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Mon, 31 Mar 2014 13:19:39 +0200 Subject: let “switch to costume” block accept actual costume objects (in addition to names and numbers) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- history.txt | 1 + objects.js | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'history.txt') diff --git a/history.txt b/history.txt index 1399ba6..2c0362b 100755 --- a/history.txt +++ b/history.txt @@ -2108,3 +2108,4 @@ ______ ------ * Objects: experimental “wardrobe” and “jukebox” reporters in dev mode * Blocks, Objects: display costume thumbnails in speech/thought/value bubbles and watcher cells +* Objects: let “switch to costume” block accept actual costume objects (in addition to names and numbers) diff --git a/objects.js b/objects.js index a6d2c9a..cc02ebe 100644 --- a/objects.js +++ b/objects.js @@ -2291,6 +2291,11 @@ SpriteMorph.prototype.doWearPreviousCostume = function () { }; SpriteMorph.prototype.doSwitchToCostume = function (id) { + if (id instanceof Costume) { // allow first-class costumes + this.wearCostume(id); + return; + } + var num, arr = this.costumes.asArray(), costume; -- cgit v1.3.1 From 51e17d2ce9368c3546b7e27809dfbd187cefb246 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Wed, 30 Apr 2014 12:18:06 +0200 Subject: enable storage of first-class costumes --- history.txt | 6 ++++++ objects.js | 2 +- store.js | 14 ++++++++++---- 3 files changed, 17 insertions(+), 5 deletions(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index 2c0362b..69b48bc 100755 --- a/history.txt +++ b/history.txt @@ -2109,3 +2109,9 @@ ______ * Objects: experimental “wardrobe” and “jukebox” reporters in dev mode * Blocks, Objects: display costume thumbnails in speech/thought/value bubbles and watcher cells * Objects: let “switch to costume” block accept actual costume objects (in addition to names and numbers) + +140430 +------ +* new Finnish translation, yay! Thanks, Jouni! +* new Brazilian Portuguese translation, yay! Thanks, Aldo! +* enable storage and retrieval of first-class costumes in both file formats diff --git a/objects.js b/objects.js index 1c4e61e..b506195 100644 --- a/objects.js +++ b/objects.js @@ -124,7 +124,7 @@ PrototypeHatBlockMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.objects = '2014-March-31'; +modules.objects = '2014-April-30'; var SpriteMorph; var StageMorph; diff --git a/store.js b/store.js index b3f5d95..d69667a 100644 --- a/store.js +++ b/store.js @@ -61,7 +61,7 @@ SyntaxElementMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.store = '2014-February-13'; +modules.store = '2014-April-30'; // XML_Serializer /////////////////////////////////////////////////////// @@ -457,8 +457,6 @@ SnapSerializer.prototype.loadProjectModel = function (xmlNode) { } }); - this.objects = {}; - /* Global Variables */ if (model.globalVariables) { @@ -468,6 +466,8 @@ SnapSerializer.prototype.loadProjectModel = function (xmlNode) { ); } + this.objects = {}; + /* Watchers */ model.sprites.childrenNamed('watcher').forEach(function (model) { @@ -521,7 +521,7 @@ SnapSerializer.prototype.loadProjectModel = function (xmlNode) { )) ); project.stage.add(watcher); - watcher.update(); + watcher.onNextStep = function () {this.currentValue = null; }; // set watcher's contentsMorph's extent if it is showing a list and // its monitor dimensions are given @@ -1302,6 +1302,12 @@ SnapSerializer.prototype.openProject = function (project, ide) { ide.createCorral(); ide.selectSprite(sprite); ide.fixLayout(); + + // force watchers to update + //project.stage.watchers().forEach(function (watcher) { + // watcher.onNextStep = function () {this.currentValue = null;}; + //}) + ide.world().keyboardReceiver = project.stage; }; -- cgit v1.3.1 From 5ab8b7e56357fd38fbc9d43a03033cb569de4a1c Mon Sep 17 00:00:00 2001 From: jmoenig Date: Wed, 30 Apr 2014 12:52:54 +0200 Subject: checkpoint --- blocks.js | 2 +- history.txt | 5 +++++ threads.js | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'history.txt') diff --git a/blocks.js b/blocks.js index f0ddd93..8e868f8 100644 --- a/blocks.js +++ b/blocks.js @@ -155,7 +155,7 @@ DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph, Costume*/ // Global stuff //////////////////////////////////////////////////////// -modules.blocks = '2014-March-31'; +modules.blocks = '2014-April-30'; var SyntaxElementMorph; diff --git a/history.txt b/history.txt index 69b48bc..5fb2b40 100755 --- a/history.txt +++ b/history.txt @@ -2114,4 +2114,9 @@ ______ ------ * new Finnish translation, yay! Thanks, Jouni! * new Brazilian Portuguese translation, yay! Thanks, Aldo! +* Russian translation update +* Portuguese translation update +* additional localisations, thanks, Manuel! +* text-encoding fix for exporting variable contents, thanks, Blob! +* set turbo mode block fix, thanks, Michael and Nathan! * enable storage and retrieval of first-class costumes in both file formats diff --git a/threads.js b/threads.js index ca6bcd2..2d954a8 100644 --- a/threads.js +++ b/threads.js @@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/ // Global stuff //////////////////////////////////////////////////////// -modules.threads = '2014-Feb-10'; +modules.threads = '2014-April-30'; var ThreadManager; var Process; -- cgit v1.3.1 From 7edecf8255860cd2498bd8e9e72bec5e29992489 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 2 May 2014 08:40:17 +0200 Subject: integrate #394 --- history.txt | 4 ++++ objects.js | 27 +++++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index 5fb2b40..bcf8e5c 100755 --- a/history.txt +++ b/history.txt @@ -2120,3 +2120,7 @@ ______ * text-encoding fix for exporting variable contents, thanks, Blob! * set turbo mode block fix, thanks, Michael and Nathan! * enable storage and retrieval of first-class costumes in both file formats + +140502 +------ +* error message when trying to import a non-text file into a variable, thanks, Nate! diff --git a/objects.js b/objects.js index 21d5156..d1e99ff 100644 --- a/objects.js +++ b/objects.js @@ -124,7 +124,7 @@ PrototypeHatBlockMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.objects = '2014-April-30'; +modules.objects = '2014-May-02'; var SpriteMorph; var StageMorph; @@ -6450,7 +6450,17 @@ WatcherMorph.prototype.userMenu = function () { inp.addEventListener( "change", function () { - var file, i; + var file; + + function txtOnlyMsg(ftype) { + ide.inform( + 'Unable to import', + 'Snap! can only import "text" files.\n' + + 'You selected a file of type "' + + ftype + + '".' + ); + } function readText(aFile) { var frd = new FileReader(); @@ -6460,18 +6470,19 @@ WatcherMorph.prototype.userMenu = function () { e.target.result ); }; - frd.readAsText(aFile); + + if (aFile.type.indexOf("text") === 0) { + frd.readAsText(aFile); + } else { + txtOnlyMsg(aFile.type); + } } document.body.removeChild(inp); ide.filePicker = null; if (inp.files.length > 0) { file = inp.files[inp.files.length - 1]; - if (file.type.indexOf("text") === 0) { - readText(file); - } else { - ide.inform("Unable to import", "Snap! can only import \"text\" files.\n You selected a file of type \"" + file.type + "\"."); - } + readText(file); } }, false -- cgit v1.3.1 From f6561867d24f18b5ae803385f1475fce973fd548 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 2 May 2014 10:55:03 +0200 Subject: fixed #407 (custom-block coloring w/ zebra off) --- byob.js | 11 ++++++----- history.txt | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'history.txt') diff --git a/byob.js b/byob.js index e47f7c5..6a10110 100644 --- a/byob.js +++ b/byob.js @@ -106,7 +106,7 @@ SymbolMorph, isNil*/ // Global stuff //////////////////////////////////////////////////////// -modules.byob = '2014-April-30'; +modules.byob = '2014-May-02'; // Declarations @@ -167,9 +167,6 @@ CustomBlockDefinition.prototype.templateInstance = function () { var block; block = this.blockInstance(); block.refreshDefaults(); - if (!block.zebraContrast) { - block.forceNormalColoring(); // label still is wrong - } block.isDraggable = false; block.isTemplate = true; return block; @@ -375,8 +372,12 @@ CustomCommandBlockMorph.prototype.refresh = function () { this.setCategory(def.category); if (this.blockSpec !== newSpec) { oldInputs = this.inputs(); + if (!this.zebraContrast) { + this.forceNormalColoring(); + } else { + this.fixBlockColor(); + } this.setSpec(newSpec); - this.fixBlockColor(); this.fixLabelColor(); this.restoreInputs(oldInputs); } else { // update all input slots' drop-downs diff --git a/history.txt b/history.txt index bcf8e5c..af54766 100755 --- a/history.txt +++ b/history.txt @@ -2124,3 +2124,4 @@ ______ 140502 ------ * error message when trying to import a non-text file into a variable, thanks, Nate! +* fixed #407 (custom-block coloring w/ zebra off) -- cgit v1.3.1 From a53c189e4b379a262bc424be263c19290be18e6d Mon Sep 17 00:00:00 2001 From: jmoenig Date: Tue, 20 May 2014 09:26:44 +0200 Subject: Morphic: Prevent default action for ctrl-/cmd-key events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … and allow using these for Snap! without having Chrome trigger its own actions for them --- history.txt | 4 ++++ morphic.js | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index af54766..faf992d 100755 --- a/history.txt +++ b/history.txt @@ -2125,3 +2125,7 @@ ______ ------ * error message when trying to import a non-text file into a variable, thanks, Nate! * fixed #407 (custom-block coloring w/ zebra off) + +140520 +------ +* Morphic: Prevent default action for ctrl-/cmd-key events diff --git a/morphic.js b/morphic.js index b55b180..48e29bb 100644 --- a/morphic.js +++ b/morphic.js @@ -1035,7 +1035,7 @@ /*global window, HTMLCanvasElement, getMinimumFontHeight, FileReader, Audio, FileList, getBlurredShadowSupport*/ -var morphicVersion = '2014-February-03'; +var morphicVersion = '2014-April-20'; var modules = {}; // keep track of additional loaded modules var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug @@ -10268,6 +10268,9 @@ WorldMorph.prototype.initEventListeners = function () { } event.preventDefault(); } + if (event.ctrlKey || event.metaKey) { + event.preventDefault(); + } }, false ); -- cgit v1.3.1 From 669d93a62967d88b4c4dd33b919737a386bf958a Mon Sep 17 00:00:00 2001 From: jmoenig Date: Tue, 20 May 2014 09:29:19 +0200 Subject: Snap.html: Focus the world canvas on startup so Snap reacts to keyboard events right away (without having to click on the IDE first) --- history.txt | 3 ++- snap.html | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index faf992d..960daf1 100755 --- a/history.txt +++ b/history.txt @@ -2128,4 +2128,5 @@ ______ 140520 ------ -* Morphic: Prevent default action for ctrl-/cmd-key events +* Morphic: Prevent default action for ctrl-/cmd-key event +* Snap.html: Focus the world canvas on startup, so Snap reacts to keyboard events right away diff --git a/snap.html b/snap.html index 66604c5..904aba8 100755 --- a/snap.html +++ b/snap.html @@ -22,6 +22,7 @@ var world; window.onload = function () { world = new WorldMorph(document.getElementById('world')); + world.worldCanvas.focus(); new IDE_Morph().openIn(world); setInterval(loop, 1); }; -- cgit v1.3.1 From 295de115a387d24ded700146203c07ba7c522d16 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Tue, 20 May 2014 09:34:37 +0200 Subject: Threads: new Variable data structure for refactoring upvar references, not yet used anywhere --- history.txt | 1 + threads.js | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index 960daf1..c49f5f8 100755 --- a/history.txt +++ b/history.txt @@ -2130,3 +2130,4 @@ ______ ------ * Morphic: Prevent default action for ctrl-/cmd-key event * Snap.html: Focus the world canvas on startup, so Snap reacts to keyboard events right away +* Threads: new Variable data structure, for refactoring upvar references, not yet used anywhere diff --git a/threads.js b/threads.js index b82a8c5..21147a3 100644 --- a/threads.js +++ b/threads.js @@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/ // Global stuff //////////////////////////////////////////////////////// -modules.threads = '2014-May-02'; +modules.threads = '2014-May-20'; var ThreadManager; var Process; @@ -3110,6 +3110,20 @@ VariableFrame.prototype.allNames = function () { return answer; }; +// Variable ///////////////////////////////////////////////////////////////// + +function Variable(value) { + this.value = value; +} + +Variable.prototype.toString = function () { + return 'a Variable [' + this.value + ']'; +}; + +Variable.prototype.copy = function () { + return new Variable(this.value); +}; + // UpvarReference /////////////////////////////////////////////////////////// // ... quasi-inherits some features from VariableFrame -- cgit v1.3.1 From a1b9d3e3964fd363cdb169c9de9287b54e736637 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Tue, 20 May 2014 09:43:31 +0200 Subject: Search Blocks feature, keyboard shortcuts Thanks, Kyle, for designing and architecting the search blocks feature!! --- gui.js | 49 +++++++++------ history.txt | 2 + objects.js | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 232 insertions(+), 21 deletions(-) (limited to 'history.txt') diff --git a/gui.js b/gui.js index 0f4f2eb..4de6b3d 100644 --- a/gui.js +++ b/gui.js @@ -68,7 +68,7 @@ sb, CommentMorph, CommandBlockMorph, BlockLabelPlaceHolderMorph, Audio*/ // Global stuff //////////////////////////////////////////////////////// -modules.gui = '2014-February-13'; +modules.gui = '2014-May-20'; // Declarations @@ -848,7 +848,7 @@ IDE_Morph.prototype.createCategories = function () { this.add(this.categories); }; -IDE_Morph.prototype.createPalette = function () { +IDE_Morph.prototype.createPalette = function (forSearching) { // assumes that the logo pane has already been created // needs the categories pane for layout var myself = this; @@ -857,7 +857,15 @@ IDE_Morph.prototype.createPalette = function () { this.palette.destroy(); } - this.palette = this.currentSprite.palette(this.currentCategory); + if (forSearching) { + this.palette = new ScrollFrameMorph( + null, + null, + this.currentSprite.sliderColor + ); + } else { + this.palette = this.currentSprite.palette(this.currentCategory); + } this.palette.isDraggable = false; this.palette.acceptsDrops = true; this.palette.contents.acceptsDrops = false; @@ -882,6 +890,7 @@ IDE_Morph.prototype.createPalette = function () { this.add(this.palette); this.palette.scrollX(this.palette.padding); this.palette.scrollY(this.palette.padding); + return this.palette; }; IDE_Morph.prototype.createStage = function () { @@ -2273,23 +2282,7 @@ IDE_Morph.prototype.projectMenu = function () { } ); menu.addItem('Open...', 'openProjectsBrowser'); - menu.addItem( - 'Save', - function () { - if (myself.source === 'examples') { - myself.source = 'local'; // cannot save to examples - } - if (myself.projectName) { - if (myself.source === 'local') { // as well as 'examples' - myself.saveProject(myself.projectName); - } else { // 'cloud' - myself.saveProjectToCloud(myself.projectName); - } - } else { - myself.saveProjectsBrowser(); - } - } - ); + menu.addItem('Save', "save"); if (shiftClicked) { menu.addItem( 'Save to disk', @@ -2720,6 +2713,22 @@ IDE_Morph.prototype.newProject = function () { this.fixLayout(); }; +IDE_Morph.prototype.save = function () { + if (this.source === 'examples') { + this.source = 'local'; // cannot save to examples + } + if (this.projectName) { + if (this.source === 'local') { // as well as 'examples' + this.saveProject(this.projectName); + } else { // 'cloud' + this.saveProjectToCloud(this.projectName); + } + } else { + this.saveProjectsBrowser(); + } +}; + + IDE_Morph.prototype.saveProject = function (name) { var myself = this; this.nextSteps([ diff --git a/history.txt b/history.txt index c49f5f8..126c11c 100755 --- a/history.txt +++ b/history.txt @@ -2131,3 +2131,5 @@ ______ * Morphic: Prevent default action for ctrl-/cmd-key event * Snap.html: Focus the world canvas on startup, so Snap reacts to keyboard events right away * Threads: new Variable data structure, for refactoring upvar references, not yet used anywhere +* Objects, GUI: Search Blocks, feature. Thanks, Kyle, for architecting and designing this!!! +* Objects, GUI: Keyboard-shortcuts for opening (cmd-o), saving (cmd-s) projects and for finding blocks (cmd-f) diff --git a/objects.js b/objects.js index d1e99ff..66ceb97 100644 --- a/objects.js +++ b/objects.js @@ -124,7 +124,7 @@ PrototypeHatBlockMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.objects = '2014-May-02'; +modules.objects = '2014-May-20'; var SpriteMorph; var StageMorph; @@ -203,90 +203,106 @@ SpriteMorph.prototype.initBlocks = function () { // Motion forward: { + only: SpriteMorph, type: 'command', category: 'motion', spec: 'move %n steps', defaults: [10] }, turn: { + only: SpriteMorph, type: 'command', category: 'motion', spec: 'turn %clockwise %n degrees', defaults: [15] }, turnLeft: { + only: SpriteMorph, type: 'command', category: 'motion', spec: 'turn %counterclockwise %n degrees', defaults: [15] }, setHeading: { + only: SpriteMorph, type: 'command', category: 'motion', spec: 'point in direction %dir' }, doFaceTowards: { + only: SpriteMorph, type: 'command', category: 'motion', spec: 'point towards %dst' }, gotoXY: { + only: SpriteMorph, type: 'command', category: 'motion', spec: 'go to x: %n y: %n', defaults: [0, 0] }, doGotoObject: { + only: SpriteMorph, type: 'command', category: 'motion', spec: 'go to %dst' }, doGlide: { + only: SpriteMorph, type: 'command', category: 'motion', spec: 'glide %n secs to x: %n y: %n', defaults: [1, 0, 0] }, changeXPosition: { + only: SpriteMorph, type: 'command', category: 'motion', spec: 'change x by %n', defaults: [10] }, setXPosition: { + only: SpriteMorph, type: 'command', category: 'motion', spec: 'set x to %n', defaults: [0] }, changeYPosition: { + only: SpriteMorph, type: 'command', category: 'motion', spec: 'change y by %n', defaults: [10] }, setYPosition: { + only: SpriteMorph, type: 'command', category: 'motion', spec: 'set y to %n', defaults: [0] }, bounceOffEdge: { + only: SpriteMorph, type: 'command', category: 'motion', spec: 'if on edge, bounce' }, xPosition: { + only: SpriteMorph, type: 'reporter', category: 'motion', spec: 'x position' }, yPosition: { + only: SpriteMorph, type: 'reporter', category: 'motion', spec: 'y position' }, direction: { + only: SpriteMorph, type: 'reporter', category: 'motion', spec: 'direction' @@ -309,24 +325,28 @@ SpriteMorph.prototype.initBlocks = function () { spec: 'costume #' }, doSayFor: { + only: SpriteMorph, type: 'command', category: 'looks', spec: 'say %s for %n secs', defaults: [localize('Hello!'), 2] }, bubble: { + only: SpriteMorph, type: 'command', category: 'looks', spec: 'say %s', defaults: [localize('Hello!')] }, doThinkFor: { + only: SpriteMorph, type: 'command', category: 'looks', spec: 'think %s for %n secs', defaults: [localize('Hmm...'), 2] }, doThink: { + only: SpriteMorph, type: 'command', category: 'looks', spec: 'think %s', @@ -350,38 +370,45 @@ SpriteMorph.prototype.initBlocks = function () { spec: 'clear graphic effects' }, changeScale: { + only: SpriteMorph, type: 'command', category: 'looks', spec: 'change size by %n', defaults: [10] }, setScale: { + only: SpriteMorph, type: 'command', category: 'looks', spec: 'set size to %n %', defaults: [100] }, getScale: { + only: SpriteMorph, type: 'reporter', category: 'looks', spec: 'size' }, show: { + only: SpriteMorph, type: 'command', category: 'looks', spec: 'show' }, hide: { + only: SpriteMorph, type: 'command', category: 'looks', spec: 'hide' }, comeToFront: { + only: SpriteMorph, type: 'command', category: 'looks', spec: 'go to front' }, goBack: { + only: SpriteMorph, type: 'command', category: 'looks', spec: 'go back %n layers', @@ -390,17 +417,20 @@ SpriteMorph.prototype.initBlocks = function () { // Looks - Debugging primitives for development mode reportCostumes: { + dev: true, type: 'reporter', category: 'looks', spec: 'wardrobe' }, alert: { + dev: true, type: 'command', category: 'looks', spec: 'alert %mult%s' }, log: { + dev: true, type: 'command', category: 'looks', spec: 'console log %mult%s' @@ -454,6 +484,7 @@ SpriteMorph.prototype.initBlocks = function () { // Sound - Debugging primitives for development mode reportSounds: { + dev: true, type: 'reporter', category: 'sound', spec: 'jukebox' @@ -466,57 +497,67 @@ SpriteMorph.prototype.initBlocks = function () { spec: 'clear' }, down: { + only: SpriteMorph, type: 'command', category: 'pen', spec: 'pen down' }, up: { + only: SpriteMorph, type: 'command', category: 'pen', spec: 'pen up' }, setColor: { + only: SpriteMorph, type: 'command', category: 'pen', spec: 'set pen color to %clr' }, changeHue: { + only: SpriteMorph, type: 'command', category: 'pen', spec: 'change pen color by %n', defaults: [10] }, setHue: { + only: SpriteMorph, type: 'command', category: 'pen', spec: 'set pen color to %n', defaults: [0] }, changeBrightness: { + only: SpriteMorph, type: 'command', category: 'pen', spec: 'change pen shade by %n', defaults: [10] }, setBrightness: { + only: SpriteMorph, type: 'command', category: 'pen', spec: 'set pen shade to %n', defaults: [100] }, changeSize: { + only: SpriteMorph, type: 'command', category: 'pen', spec: 'change pen size by %n', defaults: [1] }, setSize: { + only: SpriteMorph, type: 'command', category: 'pen', spec: 'set pen size to %n', defaults: [1] }, doStamp: { + only: SpriteMorph, type: 'command', category: 'pen', spec: 'stamp' @@ -710,31 +751,37 @@ SpriteMorph.prototype.initBlocks = function () { // Sensing reportTouchingObject: { + only: SpriteMorph, type: 'predicate', category: 'sensing', spec: 'touching %col ?' }, reportTouchingColor: { + only: SpriteMorph, type: 'predicate', category: 'sensing', spec: 'touching %clr ?' }, reportColorIsTouchingColor: { + only: SpriteMorph, type: 'predicate', category: 'sensing', spec: 'color %clr is touching %clr ?' }, colorFiltered: { + dev: true, type: 'reporter', category: 'sensing', spec: 'filtered for %clr' }, reportStackSize: { + dev: true, type: 'reporter', category: 'sensing', spec: 'stack size' }, reportFrameCount: { + dev: true, type: 'reporter', category: 'sensing', spec: 'frames' @@ -746,6 +793,7 @@ SpriteMorph.prototype.initBlocks = function () { defaults: [localize('what\'s your name?')] }, reportLastAnswer: { // retained for legacy compatibility + dev: true, type: 'reporter', category: 'sensing', spec: 'answer' @@ -786,6 +834,7 @@ SpriteMorph.prototype.initBlocks = function () { spec: 'reset timer' }, reportTimer: { // retained for legacy compatibility + dev: true, type: 'reporter', category: 'sensing', spec: 'timer' @@ -969,12 +1018,14 @@ SpriteMorph.prototype.initBlocks = function () { defaults: [localize('hello') + ' ' + localize('world'), " "] }, reportTypeOf: { // only in dev mode for debugging + dev: true, type: 'reporter', category: 'operators', spec: 'type of %s', defaults: [5] }, reportTextFunction: { // only in dev mode - experimental + dev: true, type: 'reporter', category: 'operators', spec: '%txtfun of %s', @@ -1083,6 +1134,7 @@ SpriteMorph.prototype.initBlocks = function () { // MAP - experimental reportMap: { + dev: true, type: 'reporter', category: 'lists', spec: 'map %repRing over %l' @@ -2068,6 +2120,7 @@ SpriteMorph.prototype.freshPalette = function (category) { }); } + menu.addItem('find blocks...', function () {myself.searchBlocks(); }); if (canHidePrimitives()) { menu.addItem( 'hide primitives', @@ -2199,6 +2252,139 @@ SpriteMorph.prototype.freshPalette = function (category) { return palette; }; +// SpriteMorph blocks searching + +SpriteMorph.prototype.blocksMatching = function (searchString, strictly) { + // answer an array of block templates whose spec contains + // the given search string, ordered by descending relevance + var blocks = [], + blocksDict, + myself = this, + search = searchString.toLowerCase(), + stage = this.parentThatIsA(StageMorph); + + function labelOf(aBlockSpec) { + var words = (BlockMorph.prototype.parseSpec(aBlockSpec)), + filtered = words.filter( + function (each) {return (each.indexOf('%') !== 0); } + ); + return filtered.join(' '); + } + + function fillDigits(anInt, totalDigits, fillChar) { + var ans = String(anInt); + while (ans.length < totalDigits) {ans = fillChar + ans; } + return ans; + } + + function relevance(aBlockLabel, aSearchString) { + var lbl = ' ' + aBlockLabel, + idx = lbl.indexOf(aSearchString), + atWord; + if (idx === -1) {return -1; } + atWord = (lbl.charAt(idx - 1) === ' '); + if (strictly && !atWord) {return -1; } + return (atWord ? '1' : '2') + fillDigits(idx, 4, '0'); + } + + function primitive(selector) { + var newBlock = SpriteMorph.prototype.blockForSelector(selector, true); + newBlock.isTemplate = true; + return newBlock; + } + + // custom blocks + [this.customBlocks, stage.globalBlocks].forEach(function (blocksList) { + blocksList.forEach(function (definition) { + var spec = localize(definition.blockSpec()).toLowerCase(), + rel = relevance(labelOf(spec), search); + if (rel !== -1) { + blocks.push([definition.templateInstance(), rel + '1']); + } + }); + }); + // primitives + blocksDict = SpriteMorph.prototype.blocks; + Object.keys(blocksDict).forEach(function (selector) { + if (!StageMorph.prototype.hiddenPrimitives[selector]) { + var block = blocksDict[selector], + spec = localize(block.spec).toLowerCase(), + rel = relevance(labelOf(spec), search); + if ( + (rel !== -1) && + (!block.dev) && + (!block.only || (block.only === myself.constructor)) + ) { + blocks.push([primitive(selector), rel + '2']); + } + } + }); + blocks.sort(function (x, y) {return x[1] < y[1] ? -1 : 1; }); + return blocks.map(function (each) {return each[0]; }); +}; + +SpriteMorph.prototype.searchBlocks = function () { + var myself = this, + unit = SyntaxElementMorph.prototype.fontSize, + ide = this.parentThatIsA(IDE_Morph), + oldSearch = '', + searchBar = new InputFieldMorph(''), + searchPane = ide.createPalette('forSearch'); + + function show(blocks) { + var oldFlag = Morph.prototype.trackChanges, + x = searchPane.contents.left() + 5, + y = (searchBar.bottom() + unit); + Morph.prototype.trackChanges = false; + searchPane.contents.children = [searchPane.contents.children[0]]; + blocks.forEach(function (block) { + block.setPosition(new Point(x, y)); + searchPane.addContents(block); + y += block.height(); + y += unit * 0.3; + }); + Morph.prototype.trackChanges = oldFlag; + searchPane.changed(); + } + + searchPane.owner = this; + searchPane.padding = unit / 2; + searchPane.color = myself.paletteColor; + searchPane.contents.color = myself.paletteColor; + searchPane.growth = new Point(0, MorphicPreferences.scrollBarSize); + searchPane.addContents(searchBar); + searchBar.drawNew(); + searchBar.setWidth(ide.logo.width() - 20); + searchBar.contrast = 90; + searchBar.setPosition( + searchPane.contents.topLeft().add(new Point(10, 10)) + ); + searchBar.drawNew(); + + searchPane.accept = function () { + var search = searchBar.getValue(); + if (search.length > 0) { + show(myself.blocksMatching(search)); + } + }; + + searchPane.reactToKeystroke = function () { + var search = searchBar.getValue(); + if (search !== oldSearch) { + oldSearch = search; + show(myself.blocksMatching(search, search.length < 2)); + } + }; + + searchBar.cancel = function () { + ide.refreshPalette(); + ide.palette.adjustScrollBars(); + }; + + ide.fixLayout('refreshPalette'); + searchBar.edit(); +}; + // SpriteMorph variable management SpriteMorph.prototype.addVariable = function (name, isGlobal) { @@ -4210,6 +4396,9 @@ StageMorph.prototype.processKeyEvent = function (event, action) { break; default: keyName = String.fromCharCode(event.keyCode || event.charCode); + if (event.ctrlKey || event.metaKey) { + keyName = 'ctrl ' + keyName; + } } action.call(this, keyName); }; @@ -4224,6 +4413,15 @@ StageMorph.prototype.fireKeyEvent = function (key) { if (evt === 'ctrl enter') { return this.fireGreenFlagEvent(); } + if (evt === 'ctrl f') { + return this.parentThatIsA(IDE_Morph).currentSprite.searchBlocks(); + } + if (evt === 'ctrl o') { + return this.parentThatIsA(IDE_Morph).openProjectsBrowser(); + } + if (evt === 'ctrl s') { + return this.parentThatIsA(IDE_Morph).save(); + } if (evt === 'esc') { return this.fireStopAllEvent(); } @@ -4847,6 +5045,8 @@ StageMorph.prototype.paletteColor = SpriteMorph.prototype.paletteColor; StageMorph.prototype.setName = SpriteMorph.prototype.setName; StageMorph.prototype.palette = SpriteMorph.prototype.palette; StageMorph.prototype.freshPalette = SpriteMorph.prototype.freshPalette; +StageMorph.prototype.blocksMatching = SpriteMorph.prototype.blocksMatching; +StageMorph.prototype.searchBlocks = SpriteMorph.prototype.searchBlocks; StageMorph.prototype.showingWatcher = SpriteMorph.prototype.showingWatcher; StageMorph.prototype.addVariable = SpriteMorph.prototype.addVariable; StageMorph.prototype.deleteVariable = SpriteMorph.prototype.deleteVariable; -- cgit v1.3.1 From 8125861f8062727cc7a3abb2e3a140279a10b862 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Mon, 26 May 2014 09:40:55 +0200 Subject: Fixed #445 (minor search + zoom issues) --- history.txt | 4 ++++ objects.js | 6 ++---- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index 126c11c..ecfdff4 100755 --- a/history.txt +++ b/history.txt @@ -2133,3 +2133,7 @@ ______ * Threads: new Variable data structure, for refactoring upvar references, not yet used anywhere * Objects, GUI: Search Blocks, feature. Thanks, Kyle, for architecting and designing this!!! * Objects, GUI: Keyboard-shortcuts for opening (cmd-o), saving (cmd-s) projects and for finding blocks (cmd-f) + +140526 +------ +* Objects: Fixed #445 (minor search + zoom issues) diff --git a/objects.js b/objects.js index 66ceb97..5f91606 100644 --- a/objects.js +++ b/objects.js @@ -124,7 +124,7 @@ PrototypeHatBlockMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.objects = '2014-May-20'; +modules.objects = '2014-May-26'; var SpriteMorph; var StageMorph; @@ -2348,13 +2348,11 @@ SpriteMorph.prototype.searchBlocks = function () { } searchPane.owner = this; - searchPane.padding = unit / 2; searchPane.color = myself.paletteColor; searchPane.contents.color = myself.paletteColor; - searchPane.growth = new Point(0, MorphicPreferences.scrollBarSize); searchPane.addContents(searchBar); searchBar.drawNew(); - searchBar.setWidth(ide.logo.width() - 20); + searchBar.setWidth(ide.logo.width() - 30); searchBar.contrast = 90; searchBar.setPosition( searchPane.contents.topLeft().add(new Point(10, 10)) -- cgit v1.3.1 From 24f7a37a56e4c44d6dd339f227507871867f1436 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Mon, 26 May 2014 09:57:21 +0200 Subject: Localization additions and Portuguese translation update, thanks, Manuel! --- cloud.js | 5 +++-- history.txt | 1 + lang-pt.js | 2 +- locale.js | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'history.txt') diff --git a/cloud.js b/cloud.js index 0dd7780..54189d8 100644 --- a/cloud.js +++ b/cloud.js @@ -27,9 +27,10 @@ // Global settings ///////////////////////////////////////////////////// -/*global modules, IDE_Morph, SnapSerializer, hex_sha512, alert, nop*/ +/*global modules, IDE_Morph, SnapSerializer, hex_sha512, alert, nop, +localize*/ -modules.cloud = '2014-January-09'; +modules.cloud = '2014-May-26'; // Global stuff diff --git a/history.txt b/history.txt index ecfdff4..8155285 100755 --- a/history.txt +++ b/history.txt @@ -2137,3 +2137,4 @@ ______ 140526 ------ * Objects: Fixed #445 (minor search + zoom issues) +* Localization additions and Portuguese translation update, thanks, Manuel! diff --git a/lang-pt.js b/lang-pt.js index ffc8bf1..226abf5 100755 --- a/lang-pt.js +++ b/lang-pt.js @@ -185,7 +185,7 @@ SnapTranslator.dict.pt = { 'translator_e-mail': 'mmsequeira@gmail.com', 'last_changed': - '2014-01-12', + '2014-05-26', // GUI // control bar: diff --git a/locale.js b/locale.js index d981960..c10aa64 100644 --- a/locale.js +++ b/locale.js @@ -42,7 +42,7 @@ /*global modules, contains*/ -modules.locale = '2014-May-02'; +modules.locale = '2014-May-26'; // Global stuff @@ -209,7 +209,7 @@ SnapTranslator.dict.pt = { 'translator_e-mail': 'mmsequeira@gmail.com', 'last_changed': - '2014-01-12' + '2014-05-26' }; SnapTranslator.dict.cs = { -- cgit v1.3.1 From 6a4b4afbe98fa99623a81a89e2f6505ff5704d38 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Mon, 26 May 2014 10:46:00 +0200 Subject: Show last-changed-timestamp of cloud projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit display a tool-tip “bubble” in the “Open-Project” dialog next to the preview field --- gui.js | 16 ++++++++++++++-- history.txt | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'history.txt') diff --git a/gui.js b/gui.js index 4de6b3d..981696a 100644 --- a/gui.js +++ b/gui.js @@ -64,11 +64,12 @@ standardSettings, Sound, BlockMorph, ToggleMorph, InputSlotDialogMorph, ScriptsMorph, isNil, SymbolMorph, BlockExportDialogMorph, BlockImportDialogMorph, SnapTranslator, localize, List, InputSlotMorph, SnapCloud, Uint8Array, HandleMorph, SVG_Costume, fontHeight, hex_sha512, -sb, CommentMorph, CommandBlockMorph, BlockLabelPlaceHolderMorph, Audio*/ +sb, CommentMorph, CommandBlockMorph, BlockLabelPlaceHolderMorph, Audio, +SpeechBubbleMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.gui = '2014-May-20'; +modules.gui = '2014-May-26'; // Declarations @@ -4533,6 +4534,17 @@ ProjectDialogMorph.prototype.installCloudProjectList = function (pl) { myself.preview.texture = item.Thumbnail || null; myself.preview.cachedTexture = null; myself.preview.drawNew(); + (new SpeechBubbleMorph(new TextMorph( + localize('last changed') + '\n' + item.Updated, + null, + null, + null, + null, + 'center' + ))).popUp( + myself.world(), + myself.preview.rightCenter().add(new Point(2, 0)) + ); } if (item.Public === 'true') { myself.shareButton.hide(); diff --git a/history.txt b/history.txt index 8155285..bd4d9fe 100755 --- a/history.txt +++ b/history.txt @@ -2138,3 +2138,4 @@ ______ ------ * Objects: Fixed #445 (minor search + zoom issues) * Localization additions and Portuguese translation update, thanks, Manuel! +* GUI, cloud: Show last-changed-timestamp when opening cloud projects -- cgit v1.3.1 From bae41fde2870706b200aa9ec2b0e00ca5ceb59d9 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Wed, 4 Jun 2014 12:40:44 +0200 Subject: GUI: new (hidden) feature: “Export all scripts as pic” MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (including custom block refs) --- gui.js | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- history.txt | 6 ++++++ 2 files changed, 66 insertions(+), 1 deletion(-) (limited to 'history.txt') diff --git a/gui.js b/gui.js index 981696a..67510cf 100644 --- a/gui.js +++ b/gui.js @@ -69,7 +69,7 @@ SpeechBubbleMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.gui = '2014-May-26'; +modules.gui = '2014-Jun-04'; // Declarations @@ -2350,6 +2350,15 @@ IDE_Morph.prototype.projectMenu = function () { 'show global custom block definitions as XML\nin a new browser window' ); + if (shiftClicked) { + menu.addItem( + 'Export all scripts as pic...', + function () {myself.exportScriptsPicture(); }, + 'show a picture of all scripts\nand block definitions', + new Color(100, 0, 0) + ); + } + menu.addLine(); menu.addItem( 'Import tools', @@ -2847,6 +2856,56 @@ IDE_Morph.prototype.exportSprite = function (sprite) { + ''); }; +IDE_Morph.prototype.exportScriptsPicture = function () { + var pics = [], + pic, + padding = 20, + w = 0, + h = 0, + y = 0, + ctx; + + // collect all script pics + this.sprites.asArray().forEach(function (sprite) { + pics.push(sprite.image); + pics.push(sprite.scripts.scriptsPicture()); + sprite.customBlocks.forEach(function (def) { + pics.push(def.scriptsPicture()); + }); + }); + pics.push(this.stage.image); + pics.push(this.stage.scripts.scriptsPicture()); + this.stage.customBlocks.forEach(function (def) { + pics.push(def.scriptsPicture()); + }); + + // collect global block pics + this.stage.globalBlocks.forEach(function (def) { + pics.push(def.scriptsPicture()); + }); + + pics = pics.filter(function (each) {return !isNil(each); }); + + // determine dimensions of composite + pics.forEach(function (each) { + w = Math.max(w, each.width); + h += (each.height); + h += padding; + }); + h -= padding; + pic = newCanvas(new Point(w, h)); + ctx = pic.getContext('2d'); + + // draw all parts + pics.forEach(function (each) { + ctx.drawImage(each, 0, y); + y += padding; + y += each.height; + }); + + window.open(pic.toDataURL()); +}; + IDE_Morph.prototype.openProjectString = function (str) { var msg, myself = this; diff --git a/history.txt b/history.txt index bd4d9fe..a72aa2c 100755 --- a/history.txt +++ b/history.txt @@ -2139,3 +2139,9 @@ ______ * Objects: Fixed #445 (minor search + zoom issues) * Localization additions and Portuguese translation update, thanks, Manuel! * GUI, cloud: Show last-changed-timestamp when opening cloud projects + +140604 +------ +* Blocks: refactor “script pics” feature +* BYOB: new scriptsPicture() method for custom block definitions +* GUI: new (hidden) feature: “Export all scripts as pic” (including custom block refs) -- cgit v1.3.1 From ac39877b9c7f2cfadfca581fc98fe3b6a3c434fb Mon Sep 17 00:00:00 2001 From: jmoenig Date: Wed, 4 Jun 2014 13:48:43 +0200 Subject: German translation update, tweaks --- gui.js | 1 + history.txt | 3 +++ lang-de.js | 10 +++++++++- lists.js | 2 +- locale.js | 4 ++-- objects.js | 3 ++- store.js | 4 ++-- 7 files changed, 20 insertions(+), 7 deletions(-) (limited to 'history.txt') diff --git a/gui.js b/gui.js index 67510cf..d12453b 100644 --- a/gui.js +++ b/gui.js @@ -2535,6 +2535,7 @@ IDE_Morph.prototype.aboutSnap = function () { + '\n\nNathan Dinsmore: Saving/Loading, Snap-Logo Design, ' + 'countless bugfixes' + '\nKartik Chandra: Paint Editor' + + '\nYuan Yuan: Graphic Effects' + '\nIan Reynolds: UI Design, Event Bindings, ' + 'Sound primitives' + '\nIvan Motyashov: Initial Squeak Porting' diff --git a/history.txt b/history.txt index a72aa2c..a6b3276 100755 --- a/history.txt +++ b/history.txt @@ -2145,3 +2145,6 @@ ______ * Blocks: refactor “script pics” feature * BYOB: new scriptsPicture() method for custom block definitions * GUI: new (hidden) feature: “Export all scripts as pic” (including custom block refs) +* Graphic effects!!! Yay, thanks, Yuan! +* Bug fixes from Nathan, yay, thank, Nathan!! +* German translation update diff --git a/lang-de.js b/lang-de.js index 9ce0c50..0a62da0 100644 --- a/lang-de.js +++ b/lang-de.js @@ -185,7 +185,7 @@ SnapTranslator.dict.de = { 'translator_e-mail': 'jens@moenig.org', // optional 'last_changed': - '2014-02-13', // this, too, will appear in the Translators tab + '2014-06-04', // this, too, will appear in the Translators tab // GUI // control bar: @@ -1122,8 +1122,16 @@ SnapTranslator.dict.de = { 'Leer', // graphical effects + 'brightness': + 'Helligeit', 'ghost': 'Durchsichtigkeit', + 'negative': + 'Farbumkehr', + 'comic': + 'Moire', + 'confetti': + 'Farbverschiebung', // keys 'space': diff --git a/lists.js b/lists.js index 13ec880..ea553b0 100644 --- a/lists.js +++ b/lists.js @@ -61,7 +61,7 @@ PushButtonMorph, SyntaxElementMorph, Color, Point, WatcherMorph, StringMorph, SpriteMorph, ScrollFrameMorph, CellMorph, ArrowMorph, MenuMorph, snapEquals, Morph, isNil, localize, MorphicPreferences*/ -modules.lists = '2014-January-09'; +modules.lists = '2014-Jun-04'; var List; var ListWatcherMorph; diff --git a/locale.js b/locale.js index c10aa64..614b38c 100644 --- a/locale.js +++ b/locale.js @@ -42,7 +42,7 @@ /*global modules, contains*/ -modules.locale = '2014-May-26'; +modules.locale = '2014-Jun-04'; // Global stuff @@ -149,7 +149,7 @@ SnapTranslator.dict.de = { 'translator_e-mail': 'jens@moenig.org', 'last_changed': - '2014-02-13' + '2014-06-04' }; SnapTranslator.dict.it = { diff --git a/objects.js b/objects.js index cc4371b..dc02051 100644 --- a/objects.js +++ b/objects.js @@ -61,6 +61,7 @@ sound handling Achal Dave contributed research and prototyping for creating music using the Web Audio API + Yuan Yuan contributed graphic effects for costumes */ @@ -124,7 +125,7 @@ PrototypeHatBlockMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.objects = '2014-May-26'; +modules.objects = '2014-Jun-04'; var SpriteMorph; var StageMorph; diff --git a/store.js b/store.js index e448f74..11e2757 100644 --- a/store.js +++ b/store.js @@ -61,7 +61,7 @@ SyntaxElementMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.store = '2014-May-02'; +modules.store = '2014-Jun-04'; // XML_Serializer /////////////////////////////////////////////////////// @@ -1032,7 +1032,7 @@ SnapSerializer.prototype.loadInput = function (model, input, block) { input.setColor(this.loadColor(model.contents)); } else { val = this.loadValue(model); - if (val !== undefined && val !== null && input.setContents) { + if (!isNil(val) && input.setContents) { input.setContents(this.loadValue(model)); } } -- cgit v1.3.1 From ef140b093ebb61d37235ce7f4baf5fd4c0baf01d Mon Sep 17 00:00:00 2001 From: jmoenig Date: Wed, 4 Jun 2014 14:16:57 +0200 Subject: Paint Editor transform integration - little tweaks Thanks, Kartik!! --- history.txt | 3 ++- paint.js | 22 +++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index a6b3276..72a34a6 100755 --- a/history.txt +++ b/history.txt @@ -2146,5 +2146,6 @@ ______ * BYOB: new scriptsPicture() method for custom block definitions * GUI: new (hidden) feature: “Export all scripts as pic” (including custom block refs) * Graphic effects!!! Yay, thanks, Yuan! -* Bug fixes from Nathan, yay, thank, Nathan!! +* Bug fixes from Nathan, yay, thanks, Nathan!! * German translation update +* Paint Editor transforms, yay, thanks, Kartik!! diff --git a/paint.js b/paint.js index d4d2954..7105b72 100644 --- a/paint.js +++ b/paint.js @@ -54,6 +54,7 @@ Feb 11 - dynamically adjust to stage dimensions (Jens) Apr 30 - localizations (Manuel) June 3 - transformations (Kartik) + June 4 - tweaks (Jens) */ @@ -67,7 +68,7 @@ // Global stuff //////////////////////////////////////////////////////// -modules.paint = '2014-June-3'; +modules.paint = '2014-June-4'; // Declarations @@ -112,10 +113,10 @@ PaintEditorMorph.prototype.buildContents = function () { this.paper.setExtent(StageMorph.prototype.dimensions); this.addBody(new AlignmentMorph('row', this.padding)); - this.controls = new AlignmentMorph('column', this.padding); + this.controls = new AlignmentMorph('column', this.padding / 2); this.controls.alignment = 'left'; - this.edits = new AlignmentMorph('row', this.padding); + this.edits = new AlignmentMorph('row', this.padding / 2); this.buildEdits(); this.controls.add(this.edits); @@ -134,7 +135,7 @@ PaintEditorMorph.prototype.buildContents = function () { this.buildToolbox(); this.controls.add(this.toolbox); - this.scaleBox = new AlignmentMorph('row', this.padding); + this.scaleBox = new AlignmentMorph('row', this.padding / 2); this.buildScaleBox(); this.controls.add(this.scaleBox); @@ -584,13 +585,20 @@ PaintCanvasMorph.prototype.init = function (shift) { this.buildContents(); }; -PaintCanvasMorph.prototype.scale = function(x, y) { +PaintCanvasMorph.prototype.scale = function (x, y) { this.mask = newCanvas(this.extent()); var c = newCanvas(this.extent()); c.getContext("2d").save(); - c.getContext("2d").translate(this.rotationCenter.x, this.rotationCenter.y); + c.getContext("2d").translate( + this.rotationCenter.x, + this.rotationCenter.y + ); c.getContext("2d").scale(1 + x, 1 + y); - c.getContext("2d").drawImage(this.paper, -this.rotationCenter.x, -this.rotationCenter.y); + c.getContext("2d").drawImage( + this.paper, + -this.rotationCenter.x, + -this.rotationCenter.y + ); c.getContext("2d").restore(); this.paper = c; this.drawNew(); -- cgit v1.3.1 From f80235ee43f21db5a4036ce0cdbea65cc821899b Mon Sep 17 00:00:00 2001 From: jmoenig Date: Thu, 5 Jun 2014 17:13:27 +0200 Subject: stop replacing the empty string with the number zero in watchers fixed #473 --- history.txt | 4 ++++ objects.js | 10 ++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index 72a34a6..44160ca 100755 --- a/history.txt +++ b/history.txt @@ -2149,3 +2149,7 @@ ______ * Bug fixes from Nathan, yay, thanks, Nathan!! * German translation update * Paint Editor transforms, yay, thanks, Kartik!! + +140605 +------ +* Objects: stop replacing the empty string with the number zero in watchers diff --git a/objects.js b/objects.js index dc02051..e3f1674 100644 --- a/objects.js +++ b/objects.js @@ -125,7 +125,7 @@ PrototypeHatBlockMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.objects = '2014-Jun-04'; +modules.objects = '2014-Jun-05'; var SpriteMorph; var StageMorph; @@ -6591,9 +6591,11 @@ WatcherMorph.prototype.update = function () { } else { newValue = this.target[this.getter](); } - num = +newValue; - if (typeof newValue !== 'boolean' && !isNaN(num)) { - newValue = Math.round(newValue * 1000000000) / 1000000000; + if (newValue !== '' && !isNil(newValue)) { + num = +newValue; + if (typeof newValue !== 'boolean' && !isNaN(num)) { + newValue = Math.round(newValue * 1000000000) / 1000000000; + } } if (newValue !== this.currentValue) { this.changed(); -- cgit v1.3.1 From 9f690fbfa393c2bc73ac4a8a479ae089161a7556 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Thu, 5 Jun 2014 17:16:27 +0200 Subject: initialize new variables with zero (instead of null) --- history.txt | 1 + threads.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index 44160ca..53e6087 100755 --- a/history.txt +++ b/history.txt @@ -2153,3 +2153,4 @@ ______ 140605 ------ * Objects: stop replacing the empty string with the number zero in watchers +* Threads: initialize new variables with zero (instead of null) diff --git a/threads.js b/threads.js index 21147a3..d489441 100644 --- a/threads.js +++ b/threads.js @@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/ // Global stuff //////////////////////////////////////////////////////// -modules.threads = '2014-May-20'; +modules.threads = '2014-Jun-05'; var ThreadManager; var Process; @@ -3054,7 +3054,7 @@ VariableFrame.prototype.getVar = function (name, upvars) { VariableFrame.prototype.addVar = function (name, value) { this.vars[name] = (value === 0 ? 0 : value === false ? false - : value === '' ? '' : value || null); + : value === '' ? '' : value || 0); }; VariableFrame.prototype.deleteVar = function (name) { -- cgit v1.3.1 From ccdce5da74cbc0b8bd1f60c8981894bc1f0e164b Mon Sep 17 00:00:00 2001 From: jmoenig Date: Thu, 5 Jun 2014 17:42:36 +0200 Subject: fixed #465 --- history.txt | 1 + objects.js | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index 53e6087..da0aebf 100755 --- a/history.txt +++ b/history.txt @@ -2154,3 +2154,4 @@ ______ ------ * Objects: stop replacing the empty string with the number zero in watchers * Threads: initialize new variables with zero (instead of null) +* Objects: fixed #465 diff --git a/objects.js b/objects.js index e3f1674..41f3e4a 100644 --- a/objects.js +++ b/objects.js @@ -3204,11 +3204,12 @@ SpriteMorph.prototype.forward = function (steps) { SpriteMorph.prototype.setHeading = function (degrees) { var x = this.xPosition(), y = this.yPosition(), - turn = degrees - this.heading; + dir = (+degrees || 90), + turn = dir - this.heading; // apply to myself this.changed(); - SpriteMorph.uber.setHeading.call(this, degrees); + SpriteMorph.uber.setHeading.call(this, dir); this.silentGotoXY(x, y, true); // just me this.positionTalkBubble(); -- cgit v1.3.1 From d7f30820b5d0363b89af5201643188545dd3e815 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Thu, 5 Jun 2014 17:56:19 +0200 Subject: fixed #457 --- history.txt | 1 + objects.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index da0aebf..fd4acc8 100755 --- a/history.txt +++ b/history.txt @@ -2155,3 +2155,4 @@ ______ * Objects: stop replacing the empty string with the number zero in watchers * Threads: initialize new variables with zero (instead of null) * Objects: fixed #465 +* Threads: fixed #457 diff --git a/objects.js b/objects.js index 41f3e4a..5de468b 100644 --- a/objects.js +++ b/objects.js @@ -4144,7 +4144,7 @@ StageMorph.prototype.init = function (globals) { this.keysPressed = {}; // for handling keyboard events, do not persist this.blocksCache = {}; // not to be serialized (!) this.paletteCache = {}; // not to be serialized (!) - this.lastAnswer = null; // last user input, do not persist + this.lastAnswer = ''; // last user input, do not persist this.activeSounds = []; // do not persist this.trailsCanvas = null; -- cgit v1.3.1 From 4e2ce9a4ee2ffb5e22423290fd3ae34045e339fb Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 6 Jun 2014 09:07:42 +0200 Subject: gracefully hide & show the stage, fixed #281 --- history.txt | 6 +++++- objects.js | 19 ++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index fd4acc8..3f52e14 100755 --- a/history.txt +++ b/history.txt @@ -2155,4 +2155,8 @@ ______ * Objects: stop replacing the empty string with the number zero in watchers * Threads: initialize new variables with zero (instead of null) * Objects: fixed #465 -* Threads: fixed #457 +* Objects: fixed #457 + +140605 +------ +* Objects: gracefully hide & show the stage, fixed #281 diff --git a/objects.js b/objects.js index 897f14d..88ee351 100644 --- a/objects.js +++ b/objects.js @@ -125,7 +125,7 @@ PrototypeHatBlockMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.objects = '2014-Jun-05'; +modules.objects = '2014-Jun-06'; var SpriteMorph; var StageMorph; @@ -5191,6 +5191,23 @@ StageMorph.prototype.thumbnail = function (extentPoint, excludedSprite) { return trg; }; +// StageMorph hiding and showing: + +/* + override the inherited behavior to recursively hide/show all + children. +*/ + +StageMorph.prototype.hide = function () { + this.isVisible = false; + this.changed(); +}; + +StageMorph.prototype.show = function () { + this.isVisible = true; + this.changed(); +}; + // StageMorph cloning overrice StageMorph.prototype.createClone = nop; -- cgit v1.3.1 From 76f6ad4c235f96dab4c67f2bae8b1bd9a8f20c7b Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 6 Jun 2014 09:15:16 +0200 Subject: add hide and show blocks for the stage --- history.txt | 1 + objects.js | 3 +++ 2 files changed, 4 insertions(+) (limited to 'history.txt') diff --git a/history.txt b/history.txt index 3f52e14..cabc941 100755 --- a/history.txt +++ b/history.txt @@ -2160,3 +2160,4 @@ ______ 140605 ------ * Objects: gracefully hide & show the stage, fixed #281 +* Objects: add hide and show blocks to the stage’s “looks” category diff --git a/objects.js b/objects.js index 88ee351..607df14 100644 --- a/objects.js +++ b/objects.js @@ -4739,6 +4739,9 @@ StageMorph.prototype.blockTemplates = function (category) { blocks.push(block('changeEffect')); blocks.push(block('setEffect')); blocks.push(block('clearEffects')); + blocks.push('-'); + blocks.push(block('show')); + blocks.push(block('hide')); // for debugging: /////////////// -- cgit v1.3.1 From 3f04b5b474d5b189182b90246280d25c4e858693 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 6 Jun 2014 10:34:15 +0200 Subject: more relabelling options for SAY and THINK variants --- history.txt | 1 + objects.js | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index cabc941..127e01b 100755 --- a/history.txt +++ b/history.txt @@ -2161,3 +2161,4 @@ ______ ------ * Objects: gracefully hide & show the stage, fixed #281 * Objects: add hide and show blocks to the stage’s “looks” category +* Objects: added more relabelling options to SAY and THINK variants diff --git a/objects.js b/objects.js index 607df14..1d027c2 100644 --- a/objects.js +++ b/objects.js @@ -1199,10 +1199,10 @@ SpriteMorph.prototype.blockAlternatives = { yPosition: ['xPosition'], // looks: - doSayFor: ['doThinkFor'], - doThinkFor: ['doSayFor'], - bubble: ['doThink'], - doThink: ['bubble'], + doSayFor: ['doThinkFor', 'bubble', 'doThink'], + doThinkFor: ['doSayFor', 'doThink', 'bubble'], + bubble: ['doThink', 'doSayFor', 'doThinkFor'], + doThink: ['bubble', 'doSayFor', 'doThinkFor'], show: ['hide'], hide: ['show'], changeEffect: ['setEffect'], -- cgit v1.3.1 From 9bbe9b2e0af9afd5d94d65d0f7399126c235384b Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 6 Jun 2014 11:45:41 +0200 Subject: enable relabelling blocks with C-Slots --- blocks.js | 12 ++++++++++-- history.txt | 1 + objects.js | 4 ++++ 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'history.txt') diff --git a/blocks.js b/blocks.js index b2955e9..4890fa1 100644 --- a/blocks.js +++ b/blocks.js @@ -155,7 +155,7 @@ DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph, Costume*/ // Global stuff //////////////////////////////////////////////////////// -modules.blocks = '2014-June-04'; +modules.blocks = '2014-June-06'; var SyntaxElementMorph; @@ -2295,6 +2295,7 @@ BlockMorph.prototype.restoreInputs = function (oldInputs) { // try to restore my previous inputs when my spec has been changed var i = 0, old, + nb, myself = this; this.inputs().forEach(function (inp) { @@ -2305,7 +2306,14 @@ BlockMorph.prototype.restoreInputs = function (oldInputs) { // original - turns empty numberslots to 0: // inp.setContents(old.evaluate()); // "fix" may be wrong b/c constants - inp.setContents(old.contents().text); + if (old.contents) { + inp.setContents(old.contents().text); + } + } else if (old instanceof CSlotMorph && inp instanceof CSlotMorph) { + nb = old.nestedBlock(); + if (nb) { + inp.nestedBlock(nb.fullCopy()); + } } i += 1; }); diff --git a/history.txt b/history.txt index 127e01b..9a1ec59 100755 --- a/history.txt +++ b/history.txt @@ -2162,3 +2162,4 @@ ______ * Objects: gracefully hide & show the stage, fixed #281 * Objects: add hide and show blocks to the stage’s “looks” category * Objects: added more relabelling options to SAY and THINK variants +* Blocks, objects: enable relabelling blocks with C-Slots diff --git a/objects.js b/objects.js index 1d027c2..5aac197 100644 --- a/objects.js +++ b/objects.js @@ -1233,6 +1233,10 @@ SpriteMorph.prototype.blockAlternatives = { receiveClick: ['receiveGo'], doBroadcast: ['doBroadcastAndWait'], doBroadcastAndWait: ['doBroadcast'], + doIf: ['doIfElse', 'doUntil'], + doIfElse: ['doIf', 'doUntil'], + doRepeat: ['doUntil'], + doUntil: ['doRepeat', 'doIf'], // sensing: getLastAnswer: ['getTimer'], -- cgit v1.3.1 From dcd7fb92546d6e9d9b4bd7eeb7d15417cdba3d50 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 6 Jun 2014 11:56:47 +0200 Subject: enable relabelling blocks across categories --- blocks.js | 1 + history.txt | 1 + 2 files changed, 2 insertions(+) (limited to 'history.txt') diff --git a/blocks.js b/blocks.js index 4890fa1..d5730b6 100644 --- a/blocks.js +++ b/blocks.js @@ -2268,6 +2268,7 @@ BlockMorph.prototype.relabel = function (alternativeSelectors) { menu.addItem( block, function () { + myself.setCategory(SpriteMorph.prototype.blocks[sel].category); myself.setSelector(sel); } ); diff --git a/history.txt b/history.txt index 9a1ec59..72268f6 100755 --- a/history.txt +++ b/history.txt @@ -2163,3 +2163,4 @@ ______ * Objects: add hide and show blocks to the stage’s “looks” category * Objects: added more relabelling options to SAY and THINK variants * Blocks, objects: enable relabelling blocks with C-Slots +* Blocks: enable relabelling blocks across categories -- cgit v1.3.1 From 7f1b542e73ce6cc80aa6c154152e96b336d18c00 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 6 Jun 2014 11:58:17 +0200 Subject: more relabelling options for SAY, THINK, ASK --- history.txt | 1 + objects.js | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index 72268f6..97b487e 100755 --- a/history.txt +++ b/history.txt @@ -2164,3 +2164,4 @@ ______ * Objects: added more relabelling options to SAY and THINK variants * Blocks, objects: enable relabelling blocks with C-Slots * Blocks: enable relabelling blocks across categories +* Objects: more relabelling options for SAY, THINK, ASK diff --git a/objects.js b/objects.js index 5aac197..89bc815 100644 --- a/objects.js +++ b/objects.js @@ -1199,10 +1199,10 @@ SpriteMorph.prototype.blockAlternatives = { yPosition: ['xPosition'], // looks: - doSayFor: ['doThinkFor', 'bubble', 'doThink'], - doThinkFor: ['doSayFor', 'doThink', 'bubble'], - bubble: ['doThink', 'doSayFor', 'doThinkFor'], - doThink: ['bubble', 'doSayFor', 'doThinkFor'], + doSayFor: ['doThinkFor', 'bubble', 'doThink', 'doAsk'], + doThinkFor: ['doSayFor', 'doThink', 'bubble', 'doAsk'], + bubble: ['doThink', 'doAsk', 'doSayFor', 'doThinkFor'], + doThink: ['bubble', 'doAsk', 'doSayFor', 'doThinkFor'], show: ['hide'], hide: ['show'], changeEffect: ['setEffect'], @@ -1239,6 +1239,7 @@ SpriteMorph.prototype.blockAlternatives = { doUntil: ['doRepeat', 'doIf'], // sensing: + doAsk: ['bubble', 'doThink', 'doSayFor', 'doThinkFor'], getLastAnswer: ['getTimer'], getTimer: ['getLastAnswer'], reportMouseX: ['reportMouseY'], -- cgit v1.3.1 From 7f8d5a3d1eacdc78f61da8e82ac481bbbb825938 Mon Sep 17 00:00:00 2001 From: jmoenig Date: Fri, 6 Jun 2014 13:57:45 +0200 Subject: relabelling custom blocks (experimental) --- blocks.js | 9 +++++++++ byob.js | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- history.txt | 1 + 3 files changed, 58 insertions(+), 1 deletion(-) (limited to 'history.txt') diff --git a/blocks.js b/blocks.js index af5542f..159d1a2 100644 --- a/blocks.js +++ b/blocks.js @@ -2009,6 +2009,7 @@ BlockMorph.prototype.userMenu = function () { var menu = new MenuMorph(this), world = this.world(), myself = this, + alternatives, blck; menu.addItem( @@ -2066,6 +2067,14 @@ BlockMorph.prototype.userMenu = function () { ); } ); + } else if (this.definition && this.alternatives) { // custom block + alternatives = this.alternatives(); + if (alternatives.length > 0) { + menu.addItem( + 'relabel...', + function () {myself.relabel(alternatives); } + ); + } } menu.addItem( diff --git a/byob.js b/byob.js index 0f79acf..a17f976 100644 --- a/byob.js +++ b/byob.js @@ -106,7 +106,7 @@ SymbolMorph, isNil*/ // Global stuff //////////////////////////////////////////////////////// -modules.byob = '2014-Jun-04'; +modules.byob = '2014-Jun-06'; // Declarations @@ -745,6 +745,7 @@ CustomCommandBlockMorph.prototype.userMenu = function () { } else { menu.addLine(); } + // menu.addItem("export definition...", 'exportBlockDefinition'); menu.addItem("delete block definition...", 'deleteBlockDefinition'); } @@ -846,6 +847,44 @@ CustomCommandBlockMorph.prototype.popUpbubbleHelp = function ( ).popUp(this.world(), this.rightCenter().add(new Point(-8, 0))); }; +// CustomCommandBlockMorph relabelling + +CustomCommandBlockMorph.prototype.relabel = function (alternatives) { + var menu = new MenuMorph(this), + oldInputs = this.inputs().map( + function (each) {return each.fullCopy(); } + ), + myself = this; + alternatives.forEach(function (def) { + var block = def.blockInstance(); + block.restoreInputs(oldInputs); + block.fixBlockColor(null, true); + block.addShadow(new Point(3, 3)); + menu.addItem( + block, + function () { + myself.definition = def; + myself.refresh(); + } + ); + }); + menu.popup(this.world(), this.bottomLeft().subtract(new Point( + 8, + this instanceof CommandBlockMorph ? this.corner : 0 + ))); +}; + +CustomCommandBlockMorph.prototype.alternatives = function () { + var rcvr = this.receiver(), + stage = rcvr.parentThatIsA(StageMorph), + allDefs = rcvr.customBlocks.concat(stage.globalBlocks), + myself = this; + return allDefs.filter(function (each) { + return each !== myself.definition && + each.type === myself.definition.type; + }); +}; + // CustomReporterBlockMorph //////////////////////////////////////////// // CustomReporterBlockMorph inherits from ReporterBlockMorph: @@ -961,6 +1000,14 @@ CustomReporterBlockMorph.prototype.bubbleHelp CustomReporterBlockMorph.prototype.popUpbubbleHelp = CustomCommandBlockMorph.prototype.popUpbubbleHelp; +// CustomReporterBlockMorph relabelling + +CustomReporterBlockMorph.prototype.relabel + = CustomCommandBlockMorph.prototype.relabel; + +CustomReporterBlockMorph.prototype.alternatives + = CustomCommandBlockMorph.prototype.alternatives; + // JaggedBlockMorph //////////////////////////////////////////////////// /* diff --git a/history.txt b/history.txt index 97b487e..02fc2a0 100755 --- a/history.txt +++ b/history.txt @@ -2165,3 +2165,4 @@ ______ * Blocks, objects: enable relabelling blocks with C-Slots * Blocks: enable relabelling blocks across categories * Objects: more relabelling options for SAY, THINK, ASK +* BYOB, Blocks: relabelling custom blocks (experimental) -- cgit v1.3.1