Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/yokobond/scratch-vm into…
Browse files Browse the repository at this point in the history
… extension/microbit-more

* 'develop' of https://github.com/yokobond/scratch-vm: (79 commits)
  Revert "Update gh-pages to the latest version 🚀"
  chore(package): update lockfile package-lock.json
  chore(package): update gh-pages to version 2.1.0
  Fixed issue where port A motor position was not being reported because the port number was false-y
  Corrected old port mapping! Thanks for catching that @EricR.
  Adjusted portmapping variables to match firmware versions correctly
  This commit addresses a discussion in scratchfoundation#2229 around backward compatibility.
  Add port mappings to support older firmware version 2.0.00.0016 and later as well as newer firmware version 2.0.00.0017 or newer
  Revert "Raise params to the next frame when pushing"
  fix stopThisScript inside procedures
  Added START_POWER enum to BoostOutputSubCommand which allows the extension to use unregulated motor commands with the Move Hub. Changed BoostMotor.turnOff() to use unregulated motor commands since it seems like a more reliable way of turning the motor off
  Add case to onMessage to catch responses from the LED
  Changed port-mapping to reflect firmware update.
  chore(package): update lockfile package-lock.json
  chore(package): update lodash.defaultsdeep to version 4.6.1
  Lint (remove logs, add spaces)
  test stopThisScript in procedures
  Making constants decimals.
  Fixing enum var name again.
  Adding 'byte to follow' comments back.
  ...
  • Loading branch information
yokobond committed Aug 14, 2019
2 parents fb83245 + 33ef283 commit acffb51
Show file tree
Hide file tree
Showing 26 changed files with 1,253 additions and 696 deletions.
133 changes: 132 additions & 1 deletion docs/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,124 @@ class SomeBlocks {
}
```

### Defining a Menu

To display a drop-down menu for a block argument, specify the `menu` property of that argument and a matching item in
the `menus` section of your extension's definition:

```js
return {
// ...
blocks: [
{
// ...
arguments: {
FOO: {
type: ArgumentType.NUMBER,
menu: 'fooMenu'
}
}
}
],
menus: {
fooMenu: {
items: ['a', 'b', 'c']
}
}
}
```

The items in a menu may be specified with an array or with the name of a function which returns an array. The two
simplest forms for menu definitions are:

```js
getInfo () {
return {
menus: {
staticMenu: ['static 1', 'static 2', 'static 3'],
dynamicMenu: 'getDynamicMenuItems'
}
};
}
// this member function will be called each time the menu opens
getDynamicMenuItems () {
return ['dynamic 1', 'dynamic 2', 'dynamic 3'];
}
```

The examples above are shorthand for these equivalent definitions:

```js
getInfo () {
return {
menus: {
staticMenu: {
items: ['static 1', 'static 2', 'static 3']
},
dynamicMenu: {
items: 'getDynamicMenuItems'
}
}
};
}
// this member function will be called each time the menu opens
getDynamicMenuItems () {
return ['dynamic 1', 'dynamic 2', 'dynamic 3'];
}
```

If a menu item needs a label that doesn't match its value -- for example, if the label needs to be displayed in the
user's language but the value needs to stay constant -- the menu item may be an object instead of a string. This works
for both static and dynamic menu items:

```js
menus: {
staticMenu: [
{
text: formatMessage(/* ... */),
value: 42
}
]
}
```

#### Accepting reporters ("droppable" menus)

By default it is not possible to specify the value of a dropdown menu by inserting a reporter block. While we
encourage extension authors to make their menus accept reporters when possible, doing so requires careful
consideration to avoid confusion and frustration on the part of those using the extension.

A few of these considerations include:

* The valid values for the menu should not change when the user changes the Scratch language setting.
* In particular, changing languages should never break a working project.
* The average Scratch user should be able to figure out the valid values for this input without referring to extension
documentation.
* One way to ensure this is to make an item's text match or include the item's value. For example, the official Music
extension contains menu items with names like "(1) Piano" with value 1, "(8) Cello" with value 8, and so on.
* The block should accept any value as input, even "invalid" values.
* Scratch has no concept of a runtime error!
* For a command block, sometimes the best option is to do nothing.
* For a reporter, returning zero or the empty string might make sense.
* The block should be forgiving in its interpretation of inputs.
* For example, if the block expects a string and receives a number it may make sense to interpret the number as a
string instead of treating it as invalid input.

The `acceptReporters` flag indicates that the user can drop a reporter onto the menu input:

```js
menus: {
staticMenu: {
acceptReporters: true,
items: [/*...*/]
},
dynamicMenu: {
acceptReporters: true,
items: 'getDynamicMenuItems'
}
}
```

## Annotated Example

```js
Expand Down Expand Up @@ -152,6 +270,10 @@ class SomeBlocks {
// Will be used as the extension's namespace.
id: 'someBlocks',

// Core extensions only: override the default extension block colors.
color1: '#FF8C1A',
color2: '#DB6E00',

// Optional: the human-readable name of this extension as string.
// This and any other string to be displayed in the Scratch UI may either be
// a string or a call to `formatMessage`; a plain string will not be
Expand Down Expand Up @@ -307,7 +429,16 @@ class SomeBlocks {

// Dynamic menu: returns an array as above.
// Called each time the menu is opened.
menuB: 'getItemsForMenuB'
menuB: 'getItemsForMenuB',

// The examples above are shorthand for setting only the `items` property in this full form:
menuC: {
// This flag makes a "droppable" menu: the menu will allow dropping a reporter in for the input.
acceptReporters: true,

// The `item` property may be an array or function name as in previous menu examples.
items: [/*...*/] || 'getItemsForMenuC'
}
},

// Optional: translations (UNSTABLE - NOT YET SUPPORTED)
Expand Down
38 changes: 19 additions & 19 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"in-publish": "^2.0.0",
"jsdoc": "^3.5.5",
"json": "^9.0.4",
"lodash.defaultsdeep": "4.6.0",
"lodash.defaultsdeep": "4.6.1",
"pngjs": "^3.3.2",
"scratch-audio": "latest",
"scratch-blocks": "latest",
Expand Down
8 changes: 7 additions & 1 deletion src/engine/blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -1116,8 +1116,14 @@ class Blocks {
let mutationString = `<${mutation.tagName}`;
for (const prop in mutation) {
if (prop === 'children' || prop === 'tagName') continue;
const mutationValue = (typeof mutation[prop] === 'string') ?
let mutationValue = (typeof mutation[prop] === 'string') ?
xmlEscape(mutation[prop]) : mutation[prop];

// Handle dynamic extension blocks
if (prop === 'blockInfo') {
mutationValue = xmlEscape(JSON.stringify(mutation[prop]));
}

mutationString += ` ${prop}="${mutationValue}"`;
}
mutationString += '>';
Expand Down
6 changes: 6 additions & 0 deletions src/engine/mutation-adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ const mutatorTagToObject = function (dom) {
for (const prop in dom.attribs) {
if (prop === 'xmlns') continue;
obj[prop] = decodeHtml(dom.attribs[prop]);
// Note: the capitalization of block info in the following lines is important.
// The lowercase is read in from xml which normalizes case. The VM uses camel case everywhere else.
if (prop === 'blockinfo') {
obj.blockInfo = JSON.parse(obj.blockinfo);
delete obj.blockinfo;
}
}
for (let i = 0; i < dom.children.length; i++) {
obj.children.push(
Expand Down

0 comments on commit acffb51

Please sign in to comment.