diff --git a/src/engine/blocks.js b/src/engine/blocks.js index 9e4a4c9ed..fb6634838 100644 --- a/src/engine/blocks.js +++ b/src/engine/blocks.js @@ -357,7 +357,7 @@ class Blocks { Object.keys(this._blocks).forEach(blockId => { if (this.getBlock(blockId).isMonitored) { // @todo handle specific targets (e.g. apple x position) - runtime.toggleScript(blockId); + runtime.toggleScript(blockId, {updateMonitor: true}); } }); } diff --git a/src/engine/execute.js b/src/engine/execute.js index 2b66c5e73..b9e978749 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -60,6 +60,8 @@ const execute = function (sequencer, thread) { * or after a promise resolves. * @param {*} resolvedValue Value eventually returned from the primitive. */ + // @todo move this to callback attached to the thread when we have performance + // metrics (dd) const handleReport = function (resolvedValue) { thread.pushReportedValue(resolvedValue); if (isHat) { @@ -85,8 +87,22 @@ const execute = function (sequencer, thread) { } else { // In a non-hat, report the value visually if necessary if // at the top of the thread stack. - if (typeof resolvedValue !== 'undefined' && thread.showVisualReport && thread.atStackTop()) { - runtime.visualReport(currentBlockId, resolvedValue); + + if (typeof resolvedValue !== 'undefined' && thread.atStackTop()) { + if (thread.showVisualReport) { + runtime.visualReport(currentBlockId, resolvedValue); + } + + if (thread.updateMonitor) { + runtime.updateMonitors([{ + id: currentBlockId, // @todo(dd) this will collide if multiple sprites use same block + category: 'data', + label: blockContainer.getOpcode(blockContainer.getBlock(currentBlockId)), // @todo(dd) how to handle translation here? + value: String(resolvedValue), + x: 0, // @todo(dd) place below the last monitor instead + y: 0 + }]); + } } // Finished any yields. thread.status = Thread.STATUS_RUNNING; diff --git a/src/engine/runtime.js b/src/engine/runtime.js index ae0295f88..c51333e50 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -377,13 +377,22 @@ class Runtime extends EventEmitter { * Create a thread and push it to the list of threads. * @param {!string} id ID of block that starts the stack. * @param {!Target} target Target to run thread on. - * @param {?boolean} optShowVisualReport true if the script should show speech bubble for its value + * @param {?object} opts optional arguments + * @param {?boolean} opts.optShowVisualReport true if the script should show speech bubble for its value + * @param {?boolean} opts.optUpdateMonitor true if the script should show and update a monitor with its value * @return {!Thread} The newly created thread. */ - _pushThread (id, target, optShowVisualReport) { + _pushThread (id, target, opts) { + opts = Object.assign({ + showVisualReport: false, + updateMonitor: false + }, opts); + const thread = new Thread(id); thread.target = target; - thread.showVisualReport = optShowVisualReport; + thread.showVisualReport = opts.optShowVisualReport; + thread.updateMonitor = opts.updateMonitor; + thread.pushStack(id); this.threads.push(thread); return thread; @@ -436,8 +445,14 @@ class Runtime extends EventEmitter { * @param {?object} opts optional arguments to toggle script * @param {?string} opts.target target ID for target to run script on. If not supplied, uses editing target. * @param {?boolean} opts.showVisualReport true if the speech bubble should pop up on the block, false if not. + * @param {?boolean} opts.updateMonitor true if the monitor for this block should show and get updated. */ toggleScript (topBlockId, opts) { + opts = Object.assign({ + target: this._editingTarget, + showVisualReport: false, + updateMonitor: false + }, opts); // Remove any existing thread. for (let i = 0; i < this.threads.length; i++) { if (this.threads[i].topBlock === topBlockId) { @@ -446,10 +461,7 @@ class Runtime extends EventEmitter { } } // Otherwise add it. - this._pushThread( - topBlockId, - opts && opts.target ? opts.target : this._editingTarget, - opts ? opts.showVisualReport : false); + this._pushThread(topBlockId, opts.target, opts); } /** @@ -828,10 +840,10 @@ class Runtime extends EventEmitter { } /** - * Emit a monitor update. + * Emit a monitor update which adds or updates if exists the given monitors. * @param {!Array} monitors Array of all monitors */ - monitorsUpdate (monitors) { + updateMonitors (monitors) { this.emit(Runtime.MONITORS_UPDATE, monitors); } diff --git a/src/virtual-machine.js b/src/virtual-machine.js index ed1ab98af..223620cb3 100644 --- a/src/virtual-machine.js +++ b/src/virtual-machine.js @@ -55,8 +55,8 @@ class VirtualMachine extends EventEmitter { instance.runtime.on(Runtime.SPRITE_INFO_REPORT, spriteInfo => { instance.emit(Runtime.SPRITE_INFO_REPORT, spriteInfo); }); - instance.runtime.on(Runtime.MONITORS_UPDATE, spriteInfo => { - instance.emit(Runtime.MONITORS_UPDATE, spriteInfo); + instance.runtime.on(Runtime.MONITORS_UPDATE, data => { + instance.emit(Runtime.MONITORS_UPDATE, data); }); this.blockListener = this.blockListener.bind(this);