diff --git a/playground/index.html b/playground/index.html index 0d4903d3d..82535807b 100644 --- a/playground/index.html +++ b/playground/index.html @@ -79,12 +79,6 @@ - - - - - - diff --git a/src/blocks/scratch3_control.js b/src/blocks/scratch3_control.js index 1d05a8c7a..e13edefd9 100644 --- a/src/blocks/scratch3_control.js +++ b/src/blocks/scratch3_control.js @@ -1,3 +1,5 @@ +var Promise = require('promise'); + function Scratch3ControlBlocks(runtime) { /** * The runtime instantiating this block package. @@ -38,11 +40,12 @@ Scratch3ControlBlocks.prototype.forever = function(args, util) { util.startSubstack(); }; -Scratch3ControlBlocks.prototype.wait = function(args, util) { - util.yield(); - util.timeout(function() { - util.done(); - }, 1000 * args.DURATION); +Scratch3ControlBlocks.prototype.wait = function(args) { + return new Promise(function(resolve) { + setTimeout(function() { + resolve(); + }, 1000 * args.DURATION); + }); }; Scratch3ControlBlocks.prototype.if = function(args, util) { diff --git a/src/blocks/wedo2.js b/src/blocks/wedo2.js deleted file mode 100644 index d7516bc18..000000000 --- a/src/blocks/wedo2.js +++ /dev/null @@ -1,152 +0,0 @@ - -var YieldTimers = require('../util/yieldtimers.js'); - -function WeDo2Blocks(runtime) { - /** - * The runtime instantiating this block package. - * @type {Runtime} - */ - this.runtime = runtime; - - /** - * Current motor speed, as a percentage (100 = full speed). - * @type {number} - * @private - */ - this._motorSpeed = 100; - - /** - * The timeout ID for a pending motor action. - * @type {?int} - * @private - */ - this._motorTimeout = null; -} - -/** - * Retrieve the block primitives implemented by this package. - * @return {Object.} Mapping of opcode to Function. - */ -WeDo2Blocks.prototype.getPrimitives = function() { - return { - 'wedo_motorclockwise': this.motorClockwise, - 'wedo_motorcounterclockwise': this.motorCounterClockwise, - 'wedo_motorspeed': this.motorSpeed, - 'wedo_setcolor': this.setColor, - 'wedo_whendistanceclose': this.whenDistanceClose, - 'wedo_whentilt': this.whenTilt - }; -}; - -/** - * Clamp a value between a minimum and maximum value. - * @todo move this to a common utility class. - * @param {number} val The value to clamp. - * @param {number} min The minimum return value. - * @param {number} max The maximum return value. - * @returns {number} The clamped value. - * @private - */ -WeDo2Blocks.prototype._clamp = function(val, min, max) { - return Math.max(min, Math.min(val, max)); -}; - -/** - * Common implementation for motor blocks. - * @param {string} direction The direction to turn ('left' or 'right'). - * @param {number} durationSeconds The number of seconds to run. - * @param {Object} util The util instance to use for yielding and finishing. - * @private - */ -WeDo2Blocks.prototype._motorOnFor = function(direction, durationSeconds, util) { - if (this._motorTimeout > 0) { - // @todo maybe this should go through util - YieldTimers.resolve(this._motorTimeout); - this._motorTimeout = null; - } - if (typeof window !== 'undefined' && window.native) { - window.native.motorRun(direction, this._motorSpeed); - } - - var instance = this; - var myTimeout = this._motorTimeout = util.timeout(function() { - if (instance._motorTimeout == myTimeout) { - instance._motorTimeout = null; - } - if (typeof window !== 'undefined' && window.native) { - window.native.motorStop(); - } - util.done(); - }, 1000 * durationSeconds); - - util.yield(); -}; - -WeDo2Blocks.prototype.motorClockwise = function(argValues, util) { - this._motorOnFor('right', parseFloat(argValues[0]), util); -}; - -WeDo2Blocks.prototype.motorCounterClockwise = function(argValues, util) { - this._motorOnFor('left', parseFloat(argValues[0]), util); -}; - -WeDo2Blocks.prototype.motorSpeed = function(argValues) { - var speed = argValues[0]; - switch (speed) { - case 'slow': - this._motorSpeed = 20; - break; - case 'medium': - this._motorSpeed = 50; - break; - case 'fast': - this._motorSpeed = 100; - break; - } -}; - -/** - * Convert a color name to a WeDo color index. - * Supports 'mystery' for a random hue. - * @param {string} colorName The color to retrieve. - * @returns {number} The WeDo color index. - * @private - */ -WeDo2Blocks.prototype._getColor = function(colorName) { - var colors = { - 'yellow': 7, - 'orange': 8, - 'coral': 9, - 'magenta': 1, - 'purple': 2, - 'blue': 3, - 'green': 6, - 'white': 10 - }; - - if (colorName == 'mystery') { - return Math.floor((Math.random() * 10) + 1); - } - - return colors[colorName]; -}; - -WeDo2Blocks.prototype.setColor = function(argValues, util) { - if (typeof window !== 'undefined' && window.native) { - var colorIndex = this._getColor(argValues[0]); - window.native.setLedColor(colorIndex); - } - // Pause for quarter second - util.yield(); - util.timeout(function() { - util.done(); - }, 250); -}; - -WeDo2Blocks.prototype.whenDistanceClose = function() { -}; - -WeDo2Blocks.prototype.whenTilt = function() { -}; - -module.exports = WeDo2Blocks; diff --git a/src/engine/execute.js b/src/engine/execute.js index 8fbb73dfc..acff32585 100644 --- a/src/engine/execute.js +++ b/src/engine/execute.js @@ -77,7 +77,6 @@ var execute = function (sequencer, thread) { done: function() { sequencer.proceedThread(thread); }, - timeout: thread.addTimeout.bind(thread), stackFrame: currentStackFrame.executionContext, startSubstack: function (substackNum) { sequencer.stepToSubstack(thread, substackNum); diff --git a/src/engine/runtime.js b/src/engine/runtime.js index f6ad79f0b..8c4c862e1 100644 --- a/src/engine/runtime.js +++ b/src/engine/runtime.js @@ -6,8 +6,7 @@ var util = require('util'); var defaultBlockPackages = { 'scratch3_control': require('../blocks/scratch3_control'), 'scratch3_event': require('../blocks/scratch3_event'), - 'scratch3_operators': require('../blocks/scratch3_operators'), - 'wedo2': require('../blocks/wedo2') + 'scratch3_operators': require('../blocks/scratch3_operators') }; /** diff --git a/src/engine/sequencer.js b/src/engine/sequencer.js index 81813a141..5eca9c202 100644 --- a/src/engine/sequencer.js +++ b/src/engine/sequencer.js @@ -52,16 +52,8 @@ Sequencer.prototype.stepThreads = function (threads) { // Normal-mode thread: step. this.startThread(activeThread); } else if (activeThread.status === Thread.STATUS_YIELD) { - // Yield-mode thread: resolve timers. - activeThread.resolveTimeouts(); - if (activeThread.status === Thread.STATUS_YIELD) { - // Still yielding. - numYieldingThreads++; - } - } else if (activeThread.status === Thread.STATUS_DONE) { - // Moved to a done state - finish up - activeThread.status = Thread.STATUS_RUNNING; - // @todo Deal with the return value + // Yielding thread: do nothing for this step. + continue; } if (activeThread.stack.length === 0 && activeThread.status === Thread.STATUS_DONE) { diff --git a/src/engine/thread.js b/src/engine/thread.js index 746d7dcc6..d14d83f90 100644 --- a/src/engine/thread.js +++ b/src/engine/thread.js @@ -1,5 +1,3 @@ -var YieldTimers = require('../util/yieldtimers.js'); - /** * A thread is a running stack context and all the metadata needed. * @param {?string} firstBlock First block to execute in the thread. @@ -30,12 +28,6 @@ function Thread (firstBlock) { * @type {number} */ this.status = 0; /* Thread.STATUS_RUNNING */ - - /** - * Execution-synced timeouts. - * @type {number} - */ - this.timeoutIds = []; } /** @@ -131,29 +123,4 @@ Thread.prototype.yield = function () { this.status = Thread.STATUS_YIELD; }; -/** - * Add an execution-synced timeouts for this thread. - * See also: util/yieldtimers.js:timeout - * @param {!Function} callback To be called when the timer is done. - * @param {number} timeDelta Time to wait, in ms. - */ -Thread.prototype.addTimeout = function (callback, timeDelta) { - var timeoutId = YieldTimers.timeout(callback, timeDelta); - this.timeoutIds.push(timeoutId); -}; - -/** - * Attempt to resolve all execution-synced timeouts on this thread. - */ -Thread.prototype.resolveTimeouts = function () { - var newTimeouts = []; - for (var i = 0; i < this.timeoutIds.length; i++) { - var resolved = YieldTimers.resolve(this.timeoutIds[i]); - if (!resolved) { - newTimeouts.push(this.timeoutIds[i]); - } - } - this.timeoutIds = newTimeouts; -}; - module.exports = Thread; diff --git a/src/util/yieldtimers.js b/src/util/yieldtimers.js deleted file mode 100644 index 84c6d3259..000000000 --- a/src/util/yieldtimers.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @fileoverview Timers that are synchronized with the Scratch sequencer. - */ -var Timer = require('./timer'); - -function YieldTimers () {} - -/** - * Shared collection of timers. - * Each timer is a [Function, number] with the callback - * and absolute time for it to run. - * @type {Object.} - */ -YieldTimers.timers = {}; - -/** - * Monotonically increasing timer ID. - * @type {number} - */ -YieldTimers.timerId = 0; - -/** - * Utility for measuring time. - * @type {!Timer} - */ -YieldTimers.globalTimer = new Timer(); - -/** - * The timeout function is passed to primitives and is intended - * as a convenient replacement for window.setTimeout. - * The sequencer will attempt to resolve the timer every time - * the yielded thread would have been stepped. - * @param {!Function} callback To be called when the timer is done. - * @param {number} timeDelta Time to wait, in ms. - * @return {number} Timer ID to be used with other methods. - */ -YieldTimers.timeout = function (callback, timeDelta) { - var id = ++YieldTimers.timerId; - YieldTimers.timers[id] = [ - callback, - YieldTimers.globalTimer.time() + timeDelta - ]; - return id; -}; - -/** - * Attempt to resolve a timeout. - * If the time has passed, call the callback. - * Otherwise, do nothing. - * @param {number} id Timer ID to resolve. - * @return {boolean} True if the timer has resolved. - */ -YieldTimers.resolve = function (id) { - var timer = YieldTimers.timers[id]; - if (!timer) { - // No such timer. - return false; - } - var callback = timer[0]; - var time = timer[1]; - if (YieldTimers.globalTimer.time() < time) { - // Not done yet. - return false; - } - // Execute the callback and remove the timer. - callback(); - delete YieldTimers.timers[id]; - return true; -}; - -module.exports = YieldTimers;