VM changes for the sensing_of block. This handles lists properly (by ignoring them like Scratch2 and makes the attribute menu update based on what was chosen in the target menu.

This commit is contained in:
picklesrus 2018-11-20 16:32:08 -05:00
parent 631d44a061
commit f214d3a191
5 changed files with 59 additions and 5 deletions

View file

@ -313,12 +313,11 @@ class Scratch3SensingBlocks {
} }
} }
// Variables // Local variables (not lists).
const varName = args.PROPERTY; const varName = args.PROPERTY;
for (const id in attrTarget.variables) { const variable = attrTarget.lookupVariableByNameAndType(varName, '', true);
if (attrTarget.variables[id].name === varName) { if (variable) {
return attrTarget.variables[id].value; return variable.value;
}
} }
// Otherwise, 0 // Otherwise, 0

View file

@ -567,6 +567,16 @@ class Blocks {
if (!optRuntime){ if (!optRuntime){
break; break;
} }
// The selected item in the sensing of block menu needs to change based on the
// selected target. Set it to the first item in the menu list.
if (block.opcode === 'sensing_of_object_menu') {
if (block.fields.OBJECT.value === '_stage_') {
this._blocks[block.parent].fields.PROPERTY.value = 'backdrop #';
} else {
this._blocks[block.parent].fields.PROPERTY.value = 'x position';
}
optRuntime.requestBlocksUpdate();
}
const flyoutBlock = block.shadow && block.parent ? this._blocks[block.parent] : block; const flyoutBlock = block.shadow && block.parent ? this._blocks[block.parent] : block;
if (flyoutBlock.isMonitored) { if (flyoutBlock.isMonitored) {

View file

@ -613,6 +613,14 @@ class Runtime extends EventEmitter {
return 'RUNTIME_STARTED'; return 'RUNTIME_STARTED';
} }
/**
* Event name for reporting that a block was updated and needs to be rerendered.
* @const {string}
*/
static get BLOCKS_NEED_UPDATE () {
return 'BLOCKS_NEED_UPDATE';
}
/** /**
* How rapidly we try to step threads by default, in ms. * How rapidly we try to step threads by default, in ms.
*/ */
@ -2169,6 +2177,13 @@ class Runtime extends EventEmitter {
this._refreshTargets = true; this._refreshTargets = true;
} }
/**
* Emit an event that indicate that the blocks on the workspace need updating.
*/
requestBlocksUpdate () {
this.emit(Runtime.BLOCK_NEED_UPDATE);
}
/** /**
* Set up timers to repeatedly step in a browser. * Set up timers to repeatedly step in a browser.
*/ */

View file

@ -108,6 +108,9 @@ class VirtualMachine extends EventEmitter {
this.runtime.on(Runtime.BLOCKSINFO_UPDATE, blocksInfo => { this.runtime.on(Runtime.BLOCKSINFO_UPDATE, blocksInfo => {
this.emit(Runtime.BLOCKSINFO_UPDATE, blocksInfo); this.emit(Runtime.BLOCKSINFO_UPDATE, blocksInfo);
}); });
this.runtime.on(Runtime.BLOCKS_NEED_UPDATE, () => {
this.emitWorkspaceUpdate();
});
this.runtime.on(Runtime.PERIPHERAL_LIST_UPDATE, info => { this.runtime.on(Runtime.PERIPHERAL_LIST_UPDATE, info => {
this.emit(Runtime.PERIPHERAL_LIST_UPDATE, info); this.emit(Runtime.PERIPHERAL_LIST_UPDATE, info);
}); });

View file

@ -229,6 +229,33 @@ test('loud? boolean', t => {
t.end(); t.end();
}); });
test('get attribute of sprite variable', t => {
const rt = new Runtime();
const sensing = new Sensing(rt);
const s = new Sprite();
const target = new RenderedTarget(s, rt);
const thing = {
name: 'cars',
value: 'trucks'
};
rt.getSpriteTargetByName = () => target;
target.lookupVariableByNameAndType = () => thing;
t.equal(sensing.getAttributeOf({PROPERTY: 'cars'}), 'trucks');
t.end();
});
test('get attribute of variable that does not exist', t => {
const rt = new Runtime();
const sensing = new Sensing(rt);
const s = new Sprite();
const stage = new RenderedTarget(s, rt);
rt.getTargetForStage = () => stage;
stage.lookupVariableByNameAndType = () => null;
t.equal(sensing.getAttributeOf({PROPERTY: 'stage'}), 0);
t.end();
});
test('username block', t => { test('username block', t => {
const rt = new Runtime(); const rt = new Runtime();
const sensing = new Sensing(rt); const sensing = new Sensing(rt);