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 opcode = convertedBlock.json.type;
categoryInfo.blocks.push(convertedBlock);
if (blockInfo.blockType !== BlockType.EVENT) {
this._primitives[opcode] = convertedBlock.info.func;
if (blockInfo.blockType === BlockType.HAT) {
this._hats[opcode] = {edgeActivated: true};
/** @TODO let extension specify this */
}
if (blockInfo.blockType === BlockType.EVENT || blockInfo.blockType === BlockType.HAT) {
this._hats[opcode] = {
edgeActivated: blockInfo.isEdgeActivated,
restartExistingThreads: blockInfo.shouldRestartExistingThreads
};
}
} catch (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.
* @param {BlockInfo} blockInfo - the block to convert
* Convert ExtensionBlockMetadata into scratch-blocks JSON & XML, and generate a proxy function.
* @param {ExtensionBlockMetadata} blockInfo - the block to convert
* @param {CategoryInfo} categoryInfo - the category for this block
* @returns {ConvertedBlockInfo} - the converted & original block information
* @private
@ -685,6 +689,11 @@ class Runtime extends EventEmitter {
blockJSON.outputShape = ScratchBlocksConstants.OUTPUT_SHAPE_HEXAGONAL;
break;
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.nextStatement = null; // null = available connection; undefined = terminal
break;

View file

@ -19,6 +19,12 @@ const BlockType = {
*/
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
*/

View file

@ -21,23 +21,9 @@ const builtinExtensions = {
* @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
* @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 {string} xml - the scratch-blocks XML definition for this block
*/
@ -250,7 +236,7 @@ class ExtensionManager {
case '---': // separator
result = '---';
break;
default: // a BlockInfo object
default: // an ExtensionBlockMetadata object
result = this._prepareBlockInfo(serviceName, blockInfo);
break;
}
@ -316,8 +302,8 @@ class ExtensionManager {
/**
* Apply defaults for optional block fields.
* @param {string} serviceName - the name of the service hosting this extension block
* @param {BlockInfo} blockInfo - the block info from the extension
* @returns {BlockInfo} - a new block info object which has values for all relevant optional fields.
* @param {ExtensionBlockMetadata} blockInfo - the block info from the extension
* @returns {ExtensionBlockMetadata} - a new block info object which has values for all relevant optional fields.
* @private
*/
_prepareBlockInfo (serviceName, blockInfo) {

View file

@ -14,13 +14,16 @@
* @typedef {object} ExtensionBlockMetadata
* 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} [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 {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 {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.
*/
/**