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