diff --git a/src/blocks/scratch3_sensing.js b/src/blocks/scratch3_sensing.js index 6307b4c6a..9f3ed7420 100644 --- a/src/blocks/scratch3_sensing.js +++ b/src/blocks/scratch3_sensing.js @@ -313,12 +313,11 @@ class Scratch3SensingBlocks { } } - // Variables + // Local variables (not lists). const varName = args.PROPERTY; - for (const id in attrTarget.variables) { - if (attrTarget.variables[id].name === varName) { - return attrTarget.variables[id].value; - } + const variable = attrTarget.lookupVariableByNameAndType(varName, '', true); + if (variable) { + return variable.value; } // Otherwise, 0 diff --git a/src/engine/blocks.js b/src/engine/blocks.js index f2d792d6b..abb706538 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -567,6 +567,16 @@ class Blocks { if (!optRuntime){ 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; if (flyoutBlock.isMonitored) { diff --git a/src/engine/runtime.js b/src/engine/runtime.js index c1f9c90fc..f59b5dd59 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -613,6 +613,14 @@ class Runtime extends EventEmitter { 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. */ @@ -2169,6 +2177,13 @@ class Runtime extends EventEmitter { 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. */ diff --git a/src/virtual-machine.js b/src/virtual-machine.js index 29b0be289..757e351c8 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -108,6 +108,9 @@ class VirtualMachine extends EventEmitter { this.runtime.on(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.emit(Runtime.PERIPHERAL_LIST_UPDATE, info); }); diff --git a/test/unit/blocks_sensing.js b/test/unit/blocks_sensing.js index 58b9510c8..d60b8fa68 100644 --- a/test/unit/blocks_sensing.js +++ b/test/unit/blocks_sensing.js @@ -229,6 +229,33 @@ test('loud? boolean', t => { 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 => { const rt = new Runtime(); const sensing = new Sensing(rt);