Add EVENT extension block type

An EVENT block is like a HAT block but it has no implementation
function. Its stack runs when the VM emits the corresponding event.
This commit is contained in:
Christopher Willis-Ford 2018-03-27 14:35:04 -07:00
parent af058b8146
commit de9e2be265
4 changed files with 33 additions and 29 deletions

View file

@ -562,10 +562,14 @@ class Runtime extends EventEmitter {
const convertedBlock = this._convertForScratchBlocks(blockInfo, categoryInfo); const convertedBlock = this._convertForScratchBlocks(blockInfo, categoryInfo);
const opcode = convertedBlock.json.type; const opcode = convertedBlock.json.type;
categoryInfo.blocks.push(convertedBlock); categoryInfo.blocks.push(convertedBlock);
if (blockInfo.blockType !== BlockType.EVENT) {
this._primitives[opcode] = convertedBlock.info.func; this._primitives[opcode] = convertedBlock.info.func;
if (blockInfo.blockType === BlockType.HAT) { }
this._hats[opcode] = {edgeActivated: true}; if (blockInfo.blockType === BlockType.EVENT || blockInfo.blockType === BlockType.HAT) {
/** @TODO let extension specify this */ this._hats[opcode] = {
edgeActivated: blockInfo.isEdgeActivated,
restartExistingThreads: blockInfo.shouldRestartExistingThreads
};
} }
} catch (e) { } catch (e) {
log.error('Error parsing block: ', {block: blockInfo, error: e}); log.error('Error parsing block: ', {block: blockInfo, error: e});
@ -620,8 +624,8 @@ class Runtime extends EventEmitter {
} }
/** /**
* Convert BlockInfo into scratch-blocks JSON & XML, and generate a proxy function. * Convert ExtensionBlockMetadata into scratch-blocks JSON & XML, and generate a proxy function.
* @param {BlockInfo} blockInfo - the block to convert * @param {ExtensionBlockMetadata} blockInfo - the block to convert
* @param {CategoryInfo} categoryInfo - the category for this block * @param {CategoryInfo} categoryInfo - the category for this block
* @returns {ConvertedBlockInfo} - the converted & original block information * @returns {ConvertedBlockInfo} - the converted & original block information
* @private * @private
@ -685,6 +689,11 @@ class Runtime extends EventEmitter {
blockJSON.outputShape = ScratchBlocksConstants.OUTPUT_SHAPE_HEXAGONAL; blockJSON.outputShape = ScratchBlocksConstants.OUTPUT_SHAPE_HEXAGONAL;
break; break;
case BlockType.HAT: case BlockType.HAT:
case BlockType.EVENT:
if (!blockInfo.hasOwnProperty('isEdgeActivated')) {
// if absent, this property defaults to true
blockInfo.isEdgeActivated = true;
}
blockJSON.outputShape = ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE; blockJSON.outputShape = ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE;
blockJSON.nextStatement = null; // null = available connection; undefined = terminal blockJSON.nextStatement = null; // null = available connection; undefined = terminal
break; break;

View file

@ -19,6 +19,12 @@ const BlockType = {
*/ */
CONDITIONAL: 'conditional', CONDITIONAL: 'conditional',
/**
* Specialized hat block with no implementation function
* This stack only runs if the corresponding event is emitted by other code.
*/
EVENT: 'event',
/** /**
* Hat block which conditionally starts a block stack * Hat block which conditionally starts a block stack
*/ */

View file

@ -21,23 +21,9 @@ const builtinExtensions = {
* @property {*|undefined} default - the default value of this argument (default: blank) * @property {*|undefined} default - the default value of this argument (default: blank)
*/ */
/**
* @typedef {object} BlockInfo - Information about an extension block
* @property {string} opcode - the block opcode
* @property {string|object} text - the human-readable text on this block
* @property {BlockType|undefined} blockType - the type of block (default: BlockType.COMMAND)
* @property {int|undefined} branchCount - the number of branches this block controls, if conditional (default: 0)
* @property {Boolean|undefined} isTerminal - true if this block ends a stack (default: false)
* @property {Boolean|undefined} blockAllThreads - true if all threads must wait for this block to run (default: false)
* @property {object.<string,ArgumentInfo>|undefined} arguments - information about this block's arguments, if any
* @property {string|Function|undefined} func - the method for this block on the extension service (default: opcode)
* @property {Array.<string>|undefined} filter - the list of targets for which this block should appear (default: all)
* @property {Boolean|undefined} hideFromPalette - true if should not be appear in the palette. (default false)
*/
/** /**
* @typedef {object} ConvertedBlockInfo - Raw extension block data paired with processed data ready for scratch-blocks * @typedef {object} ConvertedBlockInfo - Raw extension block data paired with processed data ready for scratch-blocks
* @property {BlockInfo} info - the raw block info * @property {ExtensionBlockMetadata} info - the raw block info
* @property {object} json - the scratch-blocks JSON definition for this block * @property {object} json - the scratch-blocks JSON definition for this block
* @property {string} xml - the scratch-blocks XML definition for this block * @property {string} xml - the scratch-blocks XML definition for this block
*/ */
@ -250,7 +236,7 @@ class ExtensionManager {
case '---': // separator case '---': // separator
result = '---'; result = '---';
break; break;
default: // a BlockInfo object default: // an ExtensionBlockMetadata object
result = this._prepareBlockInfo(serviceName, blockInfo); result = this._prepareBlockInfo(serviceName, blockInfo);
break; break;
} }
@ -316,8 +302,8 @@ class ExtensionManager {
/** /**
* Apply defaults for optional block fields. * Apply defaults for optional block fields.
* @param {string} serviceName - the name of the service hosting this extension block * @param {string} serviceName - the name of the service hosting this extension block
* @param {BlockInfo} blockInfo - the block info from the extension * @param {ExtensionBlockMetadata} blockInfo - the block info from the extension
* @returns {BlockInfo} - a new block info object which has values for all relevant optional fields. * @returns {ExtensionBlockMetadata} - a new block info object which has values for all relevant optional fields.
* @private * @private
*/ */
_prepareBlockInfo (serviceName, blockInfo) { _prepareBlockInfo (serviceName, blockInfo) {

View file

@ -14,13 +14,16 @@
* @typedef {object} ExtensionBlockMetadata * @typedef {object} ExtensionBlockMetadata
* All the metadata needed to register an extension block. * All the metadata needed to register an extension block.
* @property {string} opcode - a unique alphanumeric identifier for this block. No special characters allowed. * @property {string} opcode - a unique alphanumeric identifier for this block. No special characters allowed.
* @property {string} [func] - the name of the function implementing this block. Can be shared by other blocks/opcodes.
* @property {BlockType} blockType - the type of block (command, reporter, etc.) being described. * @property {BlockType} blockType - the type of block (command, reporter, etc.) being described.
* @property {string} func - the name of the function implementing this block. Can be shared with other blocks/opcodes.
* @property {Boolean} hideFromPalette - true if this block should not appear in the block palette.
* @property {ReporterScope} reporterScope - if this block is a reporter, this is the scope/context for its value.
* @property {Boolean} terminal - true if the block ends a stack - no blocks can be connected after it.
* @property {string} text - the text on the block, with [PLACEHOLDERS] for arguments. * @property {string} text - the text on the block, with [PLACEHOLDERS] for arguments.
* @property {Object.<ExtensionArgumentMetadata>} arguments - map of argument placeholder to metadata about each arg. * @property {Boolean} [hideFromPalette] - true if this block should not appear in the block palette.
* @property {Boolean} [isTerminal] - true if the block ends a stack - no blocks can be connected after it.
* @property {ReporterScope} [reporterScope] - if this block is a reporter, this is the scope/context for its value.
* @property {Boolean} [isEdgeActivated] - sets whether a hat block is edge-activated.
* @property {Boolean} [shouldRestartExistingThreads] - sets whether a hat/event block should restart existing threads.
* @property {int} [branchCount] - for flow control blocks, the number of branches/substacks for this block.
* @property {Object.<ExtensionArgumentMetadata>} [arguments] - map of argument placeholder to metadata about each arg.
*/ */
/** /**