diff --git a/HISTORY.md b/HISTORY.md index 1603ec13..e1050361 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -4,6 +4,7 @@ * **New Features:** * new gesture: holding the shift-key when dragging extracts a single command from a stack of blocks * new "extract" single command block context menu option + * new CUT FROM command in the pen category * added "pie chart" option to PLOT command in the frequency distribution analysis library * added getProjectXML() method to the API * new noCloud flag that disables cloud access, thanks, Bernat @@ -24,6 +25,7 @@ ### 2020-11-02 * objects: tweaked drop-shadows for sprites * blocks: tweaked drop-shadows for comments +* objects, threads: added new CUT FROM command to the pen category ### 2020-10-28 * gui: tweaked wait-until-assets-are-loaded mechanism diff --git a/snap.html b/snap.html index a84eb104..87d57871 100755 --- a/snap.html +++ b/snap.html @@ -9,7 +9,7 @@ - + diff --git a/src/objects.js b/src/objects.js index 561ec035..a397be40 100644 --- a/src/objects.js +++ b/src/objects.js @@ -698,6 +698,11 @@ SpriteMorph.prototype.initBlocks = function () { category: 'pen', spec: 'paste on %spr' }, + doCutFrom: { + type: 'command', + category: 'pen', + spec: 'cut from %spr' + }, // Control receiveGo: { @@ -2380,6 +2385,7 @@ SpriteMorph.prototype.blockTemplates = function (category) { blocks.push(block('reportPenTrailsAsCostume')); blocks.push('-'); blocks.push(block('doPasteOn')); + blocks.push(block('doCutFrom')); blocks.push('='); blocks.push(this.makeBlockButton(cat)); @@ -4450,7 +4456,7 @@ SpriteMorph.prototype.changeSize = function (delta) { // SpriteMorph printing on another sprite: -SpriteMorph.prototype.pasteOn = function (target) { +SpriteMorph.prototype.blitOn = function (target, mask = 'source-atop') { // draw my costume onto a copy of the target's costume scaled and rotated // so it appears as though I'm "stamped" onto it. @@ -4549,7 +4555,7 @@ SpriteMorph.prototype.pasteOn = function (target) { ctx = targetCostume.contents.getContext('2d'); ctx.rotate(radians(relRot)); ctx.scale(relScale, relScale); - ctx.globalCompositeOperation = 'source-atop'; + ctx.globalCompositeOperation = mask; ctx.drawImage(sourceCostume.contents, pos.x, pos.y); // make the target wear the new costume @@ -8427,6 +8433,7 @@ StageMorph.prototype.blockTemplates = function (category) { blocks.push(block('reportPenTrailsAsCostume')); blocks.push('-'); blocks.push(block('doPasteOn')); + blocks.push(block('doCutFrom')); blocks.push('='); blocks.push(this.makeBlockButton(cat)); diff --git a/src/threads.js b/src/threads.js index cf9561c9..bd16b266 100644 --- a/src/threads.js +++ b/src/threads.js @@ -61,7 +61,7 @@ StageMorph, SpriteMorph, StagePrompterMorph, Note, modules, isString, copy, Map, isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph, BLACK, TableFrameMorph, ColorSlotMorph, isSnapObject, newCanvas, Symbol, SVG_Costume*/ -modules.threads = '2020-October-08'; +modules.threads = '2020-November-02'; var ThreadManager; var Process; @@ -4374,9 +4374,17 @@ Process.prototype.changePenHSVA = Process.prototype.changeHSVA; Process.prototype.setBackgroundHSVA = Process.prototype.setHSVA; Process.prototype.changeBackgroundHSVA = Process.prototype.changeHSVA; -// Process pasting primitives +// Process cutting & pasting primitives -Process.prototype.doPasteOn = function (name, thisObj, stage) { +Process.prototype.doPasteOn = function (name) { + this.blitOn(name, 'source-atop'); +}; + +Process.prototype.doCutFrom = function (name) { + this.blitOn(name, 'destination-out'); +}; + +Process.prototype.blitOn = function (name, mask, thisObj, stage) { // allow for lists of sprites and also check for temparary clones, // as in Scratch 2.0, var those; @@ -4386,7 +4394,7 @@ Process.prototype.doPasteOn = function (name, thisObj, stage) { name = stage; } if (isSnapObject(name)) { - return thisObj.pasteOn(name); + return thisObj.blitOn(name, mask); } if (name instanceof List) { // assume all elements to be sprites those = name.itemsArray(); @@ -4394,7 +4402,7 @@ Process.prototype.doPasteOn = function (name, thisObj, stage) { those = this.getObjectsNamed(name, thisObj, stage); // clones } those.forEach(each => - this.doPasteOn(each, thisObj, stage) + this.blitOn(each, mask, thisObj, stage) ); };