mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-24 15:02:52 -05:00
Merge pull request #992 from paulkaplan/stage-clicked
Make "when clicked" blocks target dependent.
This commit is contained in:
commit
a27ed888d2
8 changed files with 82 additions and 0 deletions
|
@ -32,6 +32,9 @@ class Scratch3EventBlocks {
|
||||||
event_whenthisspriteclicked: {
|
event_whenthisspriteclicked: {
|
||||||
restartExistingThreads: true
|
restartExistingThreads: true
|
||||||
},
|
},
|
||||||
|
event_whenstageclicked: {
|
||||||
|
restartExistingThreads: true
|
||||||
|
},
|
||||||
event_whenbackdropswitchesto: {
|
event_whenbackdropswitchesto: {
|
||||||
restartExistingThreads: true
|
restartExistingThreads: true
|
||||||
},
|
},
|
||||||
|
|
|
@ -593,6 +593,21 @@ class Blocks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep blocks up to date after they are shared between targets.
|
||||||
|
* @param {boolean} isStage If the new target is a stage.
|
||||||
|
*/
|
||||||
|
updateTargetSpecificBlocks (isStage) {
|
||||||
|
const blocks = this._blocks;
|
||||||
|
for (const blockId in blocks) {
|
||||||
|
if (isStage && blocks[blockId].opcode === 'event_whenthisspriteclicked') {
|
||||||
|
blocks[blockId].opcode = 'event_whenstageclicked';
|
||||||
|
} else if (!isStage && blocks[blockId].opcode === 'event_whenstageclicked') {
|
||||||
|
blocks[blockId].opcode = 'event_whenthisspriteclicked';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update blocks after a sound, costume, or backdrop gets renamed.
|
* Update blocks after a sound, costume, or backdrop gets renamed.
|
||||||
* Any block referring to the old name of the asset should get updated
|
* Any block referring to the old name of the asset should get updated
|
||||||
|
|
|
@ -31,8 +31,15 @@ class Mouse {
|
||||||
// only activate click hat if the mouse up event wasn't
|
// only activate click hat if the mouse up event wasn't
|
||||||
// the result of a drag ending
|
// the result of a drag ending
|
||||||
if (!wasDragged) {
|
if (!wasDragged) {
|
||||||
|
// Activate both "this sprite clicked" and "stage clicked"
|
||||||
|
// They were separated into two opcodes for labeling,
|
||||||
|
// but should act the same way.
|
||||||
|
// Intentionally not checking isStage to make it work when sharing blocks.
|
||||||
|
// @todo the blocks should be converted from one to another when shared
|
||||||
this.runtime.startHats('event_whenthisspriteclicked',
|
this.runtime.startHats('event_whenthisspriteclicked',
|
||||||
null, target);
|
null, target);
|
||||||
|
this.runtime.startHats('event_whenstageclicked',
|
||||||
|
null, target);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -275,6 +275,9 @@ const parseScratchObject = function (object, runtime, extensions, topLevel) {
|
||||||
parseScripts(object.scripts, blocks, addBroadcastMsg, getVariableId, extensions);
|
parseScripts(object.scripts, blocks, addBroadcastMsg, getVariableId, extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update stage specific blocks (e.g. sprite clicked <=> stage clicked)
|
||||||
|
blocks.updateTargetSpecificBlocks(topLevel); // topLevel = isStage
|
||||||
|
|
||||||
if (object.hasOwnProperty('lists')) {
|
if (object.hasOwnProperty('lists')) {
|
||||||
for (let k = 0; k < object.lists.length; k++) {
|
for (let k = 0; k < object.lists.length; k++) {
|
||||||
const list = object.lists[k];
|
const list = object.lists[k];
|
||||||
|
|
|
@ -778,6 +778,7 @@ class VirtualMachine extends EventEmitter {
|
||||||
for (let i = 0; i < blocks.length; i++) {
|
for (let i = 0; i < blocks.length; i++) {
|
||||||
target.blocks.createBlock(blocks[i]);
|
target.blocks.createBlock(blocks[i]);
|
||||||
}
|
}
|
||||||
|
target.blocks.updateTargetSpecificBlocks(target.isStage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
BIN
test/fixtures/when-clicked.sb2
vendored
Normal file
BIN
test/fixtures/when-clicked.sb2
vendored
Normal file
Binary file not shown.
|
@ -746,3 +746,33 @@ test('updateAssetName doesn\'t update name if name isn\'t being used', t => {
|
||||||
t.equals(b.getBlock('id1').fields.BACKDROP.value, 'foo');
|
t.equals(b.getBlock('id1').fields.BACKDROP.value, 'foo');
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('updateTargetSpecificBlocks changes sprite clicked hat to stage clicked for stage', t => {
|
||||||
|
const b = new Blocks();
|
||||||
|
b.createBlock({
|
||||||
|
id: 'originallySpriteClicked',
|
||||||
|
opcode: 'event_whenthisspriteclicked'
|
||||||
|
});
|
||||||
|
b.createBlock({
|
||||||
|
id: 'originallyStageClicked',
|
||||||
|
opcode: 'event_whenstageclicked'
|
||||||
|
});
|
||||||
|
|
||||||
|
// originallySpriteClicked does not update when on a non-stage target
|
||||||
|
b.updateTargetSpecificBlocks(false /* isStage */);
|
||||||
|
t.equals(b.getBlock('originallySpriteClicked').opcode, 'event_whenthisspriteclicked');
|
||||||
|
|
||||||
|
// originallySpriteClicked does update when on a stage target
|
||||||
|
b.updateTargetSpecificBlocks(true /* isStage */);
|
||||||
|
t.equals(b.getBlock('originallySpriteClicked').opcode, 'event_whenstageclicked');
|
||||||
|
|
||||||
|
// originallyStageClicked does not update when on a stage target
|
||||||
|
b.updateTargetSpecificBlocks(true /* isStage */);
|
||||||
|
t.equals(b.getBlock('originallyStageClicked').opcode, 'event_whenstageclicked');
|
||||||
|
|
||||||
|
// originallyStageClicked does update when on a non-stage target
|
||||||
|
b.updateTargetSpecificBlocks(false/* isStage */);
|
||||||
|
t.equals(b.getBlock('originallyStageClicked').opcode, 'event_whenthisspriteclicked');
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
|
@ -68,3 +68,26 @@ test('data scoping', t => {
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('whenclicked blocks imported separately', t => {
|
||||||
|
// This sb2 fixture has a single "whenClicked" block on both sprite and stage
|
||||||
|
const uri = path.resolve(__dirname, '../fixtures/when-clicked.sb2');
|
||||||
|
const file = extract(uri);
|
||||||
|
const json = JSON.parse(file);
|
||||||
|
|
||||||
|
// Create runtime instance & load SB2 into it
|
||||||
|
const rt = new Runtime();
|
||||||
|
sb2.deserialize(json, rt).then(({targets}) => {
|
||||||
|
const stage = targets[0];
|
||||||
|
t.equal(stage.isStage, true); // Make sure we have the correct target
|
||||||
|
const stageOpcode = stage.blocks.getBlock(stage.blocks.getScripts()[0]).opcode;
|
||||||
|
t.equal(stageOpcode, 'event_whenstageclicked');
|
||||||
|
|
||||||
|
const sprite = targets[1];
|
||||||
|
t.equal(sprite.isStage, false); // Make sure we have the correct target
|
||||||
|
const spriteOpcode = sprite.blocks.getBlock(sprite.blocks.getScripts()[0]).opcode;
|
||||||
|
t.equal(spriteOpcode, 'event_whenthisspriteclicked');
|
||||||
|
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue