@scratch/scratch-vm 11.0.0-UEPR-176

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/LICENSE +12 -0
  2. package/README.md +120 -0
  3. package/dist/node/extension-worker.js +2 -0
  4. package/dist/node/extension-worker.js.map +1 -0
  5. package/dist/node/scratch-vm.js +3 -0
  6. package/dist/node/scratch-vm.js.LICENSE.txt +205 -0
  7. package/dist/node/scratch-vm.js.map +1 -0
  8. package/dist/web/extension-worker.js +2 -0
  9. package/dist/web/extension-worker.js.map +1 -0
  10. package/dist/web/scratch-vm.js +3 -0
  11. package/dist/web/scratch-vm.js.LICENSE.txt +42 -0
  12. package/dist/web/scratch-vm.js.map +1 -0
  13. package/package.json +108 -0
  14. package/src/.eslintrc.js +7 -0
  15. package/src/blocks/scratch3_control.js +206 -0
  16. package/src/blocks/scratch3_core_example.js +69 -0
  17. package/src/blocks/scratch3_data.js +257 -0
  18. package/src/blocks/scratch3_event.js +137 -0
  19. package/src/blocks/scratch3_looks.js +612 -0
  20. package/src/blocks/scratch3_motion.js +288 -0
  21. package/src/blocks/scratch3_operators.js +154 -0
  22. package/src/blocks/scratch3_procedures.js +79 -0
  23. package/src/blocks/scratch3_sensing.js +336 -0
  24. package/src/blocks/scratch3_sound.js +350 -0
  25. package/src/dispatch/central-dispatch.js +143 -0
  26. package/src/dispatch/shared-dispatch.js +235 -0
  27. package/src/dispatch/worker-dispatch.js +110 -0
  28. package/src/engine/adapter.js +176 -0
  29. package/src/engine/block-utility.js +242 -0
  30. package/src/engine/blocks-execute-cache.js +19 -0
  31. package/src/engine/blocks-runtime-cache.js +78 -0
  32. package/src/engine/blocks.js +1299 -0
  33. package/src/engine/comment.js +56 -0
  34. package/src/engine/execute.js +580 -0
  35. package/src/engine/monitor-record.js +23 -0
  36. package/src/engine/mutation-adapter.js +48 -0
  37. package/src/engine/profiler.js +390 -0
  38. package/src/engine/runtime.js +2686 -0
  39. package/src/engine/scratch-blocks-constants.js +27 -0
  40. package/src/engine/sequencer.js +361 -0
  41. package/src/engine/stage-layering.js +29 -0
  42. package/src/engine/target.js +799 -0
  43. package/src/engine/thread.js +404 -0
  44. package/src/engine/variable.js +70 -0
  45. package/src/extension-support/argument-type.js +47 -0
  46. package/src/extension-support/block-type.js +50 -0
  47. package/src/extension-support/define-messages.js +18 -0
  48. package/src/extension-support/extension-manager.js +440 -0
  49. package/src/extension-support/extension-metadata.js +64 -0
  50. package/src/extension-support/extension-worker.js +59 -0
  51. package/src/extension-support/reporter-scope.js +18 -0
  52. package/src/extension-support/target-type.js +17 -0
  53. package/src/extensions/scratch3_boost/index.js +2113 -0
  54. package/src/extensions/scratch3_ev3/index.js +1355 -0
  55. package/src/extensions/scratch3_gdx_for/index.js +981 -0
  56. package/src/extensions/scratch3_gdx_for/scratch-link-device-adapter.js +44 -0
  57. package/src/extensions/scratch3_makeymakey/index.js +396 -0
  58. package/src/extensions/scratch3_microbit/index.js +984 -0
  59. package/src/extensions/scratch3_music/assets/drums/1-snare.mp3 +0 -0
  60. package/src/extensions/scratch3_music/assets/drums/10-wood-block.mp3 +0 -0
  61. package/src/extensions/scratch3_music/assets/drums/11-cowbell.mp3 +0 -0
  62. package/src/extensions/scratch3_music/assets/drums/12-triangle.mp3 +0 -0
  63. package/src/extensions/scratch3_music/assets/drums/13-bongo.mp3 +0 -0
  64. package/src/extensions/scratch3_music/assets/drums/14-conga.mp3 +0 -0
  65. package/src/extensions/scratch3_music/assets/drums/15-cabasa.mp3 +0 -0
  66. package/src/extensions/scratch3_music/assets/drums/16-guiro.mp3 +0 -0
  67. package/src/extensions/scratch3_music/assets/drums/17-vibraslap.mp3 +0 -0
  68. package/src/extensions/scratch3_music/assets/drums/18-cuica.mp3 +0 -0
  69. package/src/extensions/scratch3_music/assets/drums/2-bass-drum.mp3 +0 -0
  70. package/src/extensions/scratch3_music/assets/drums/3-side-stick.mp3 +0 -0
  71. package/src/extensions/scratch3_music/assets/drums/4-crash-cymbal.mp3 +0 -0
  72. package/src/extensions/scratch3_music/assets/drums/5-open-hi-hat.mp3 +0 -0
  73. package/src/extensions/scratch3_music/assets/drums/6-closed-hi-hat.mp3 +0 -0
  74. package/src/extensions/scratch3_music/assets/drums/7-tambourine.mp3 +0 -0
  75. package/src/extensions/scratch3_music/assets/drums/8-hand-clap.mp3 +0 -0
  76. package/src/extensions/scratch3_music/assets/drums/9-claves.mp3 +0 -0
  77. package/src/extensions/scratch3_music/assets/instruments/1-piano/108.mp3 +0 -0
  78. package/src/extensions/scratch3_music/assets/instruments/1-piano/24.mp3 +0 -0
  79. package/src/extensions/scratch3_music/assets/instruments/1-piano/36.mp3 +0 -0
  80. package/src/extensions/scratch3_music/assets/instruments/1-piano/48.mp3 +0 -0
  81. package/src/extensions/scratch3_music/assets/instruments/1-piano/60.mp3 +0 -0
  82. package/src/extensions/scratch3_music/assets/instruments/1-piano/72.mp3 +0 -0
  83. package/src/extensions/scratch3_music/assets/instruments/1-piano/84.mp3 +0 -0
  84. package/src/extensions/scratch3_music/assets/instruments/1-piano/96.mp3 +0 -0
  85. package/src/extensions/scratch3_music/assets/instruments/10-clarinet/48.mp3 +0 -0
  86. package/src/extensions/scratch3_music/assets/instruments/10-clarinet/60.mp3 +0 -0
  87. package/src/extensions/scratch3_music/assets/instruments/11-saxophone/36.mp3 +0 -0
  88. package/src/extensions/scratch3_music/assets/instruments/11-saxophone/60.mp3 +0 -0
  89. package/src/extensions/scratch3_music/assets/instruments/11-saxophone/84.mp3 +0 -0
  90. package/src/extensions/scratch3_music/assets/instruments/12-flute/60.mp3 +0 -0
  91. package/src/extensions/scratch3_music/assets/instruments/12-flute/72.mp3 +0 -0
  92. package/src/extensions/scratch3_music/assets/instruments/13-wooden-flute/60.mp3 +0 -0
  93. package/src/extensions/scratch3_music/assets/instruments/13-wooden-flute/72.mp3 +0 -0
  94. package/src/extensions/scratch3_music/assets/instruments/14-bassoon/36.mp3 +0 -0
  95. package/src/extensions/scratch3_music/assets/instruments/14-bassoon/48.mp3 +0 -0
  96. package/src/extensions/scratch3_music/assets/instruments/14-bassoon/60.mp3 +0 -0
  97. package/src/extensions/scratch3_music/assets/instruments/15-choir/48.mp3 +0 -0
  98. package/src/extensions/scratch3_music/assets/instruments/15-choir/60.mp3 +0 -0
  99. package/src/extensions/scratch3_music/assets/instruments/15-choir/72.mp3 +0 -0
  100. package/src/extensions/scratch3_music/assets/instruments/16-vibraphone/60.mp3 +0 -0
  101. package/src/extensions/scratch3_music/assets/instruments/16-vibraphone/72.mp3 +0 -0
  102. package/src/extensions/scratch3_music/assets/instruments/17-music-box/60.mp3 +0 -0
  103. package/src/extensions/scratch3_music/assets/instruments/18-steel-drum/60.mp3 +0 -0
  104. package/src/extensions/scratch3_music/assets/instruments/19-marimba/60.mp3 +0 -0
  105. package/src/extensions/scratch3_music/assets/instruments/2-electric-piano/60.mp3 +0 -0
  106. package/src/extensions/scratch3_music/assets/instruments/20-synth-lead/60.mp3 +0 -0
  107. package/src/extensions/scratch3_music/assets/instruments/21-synth-pad/60.mp3 +0 -0
  108. package/src/extensions/scratch3_music/assets/instruments/3-organ/60.mp3 +0 -0
  109. package/src/extensions/scratch3_music/assets/instruments/4-guitar/60.mp3 +0 -0
  110. package/src/extensions/scratch3_music/assets/instruments/5-electric-guitar/60.mp3 +0 -0
  111. package/src/extensions/scratch3_music/assets/instruments/6-bass/36.mp3 +0 -0
  112. package/src/extensions/scratch3_music/assets/instruments/6-bass/48.mp3 +0 -0
  113. package/src/extensions/scratch3_music/assets/instruments/7-pizzicato/60.mp3 +0 -0
  114. package/src/extensions/scratch3_music/assets/instruments/8-cello/36.mp3 +0 -0
  115. package/src/extensions/scratch3_music/assets/instruments/8-cello/48.mp3 +0 -0
  116. package/src/extensions/scratch3_music/assets/instruments/8-cello/60.mp3 +0 -0
  117. package/src/extensions/scratch3_music/assets/instruments/9-trombone/36.mp3 +0 -0
  118. package/src/extensions/scratch3_music/assets/instruments/9-trombone/48.mp3 +0 -0
  119. package/src/extensions/scratch3_music/assets/instruments/9-trombone/60.mp3 +0 -0
  120. package/src/extensions/scratch3_music/index.js +1333 -0
  121. package/src/extensions/scratch3_music/manifest.js +63 -0
  122. package/src/extensions/scratch3_pen/index.js +770 -0
  123. package/src/extensions/scratch3_speech2text/index.js +700 -0
  124. package/src/extensions/scratch3_text2speech/index.js +766 -0
  125. package/src/extensions/scratch3_translate/index.js +286 -0
  126. package/src/extensions/scratch3_video_sensing/debug.js +13 -0
  127. package/src/extensions/scratch3_video_sensing/index.js +594 -0
  128. package/src/extensions/scratch3_video_sensing/library.js +384 -0
  129. package/src/extensions/scratch3_video_sensing/math.js +76 -0
  130. package/src/extensions/scratch3_video_sensing/view.js +509 -0
  131. package/src/extensions/scratch3_wedo2/index.js +1616 -0
  132. package/src/import/load-costume.js +416 -0
  133. package/src/import/load-sound.js +116 -0
  134. package/src/index.js +10 -0
  135. package/src/io/ble.js +256 -0
  136. package/src/io/bt.js +202 -0
  137. package/src/io/clock.js +39 -0
  138. package/src/io/cloud.js +169 -0
  139. package/src/io/keyboard.js +146 -0
  140. package/src/io/mouse.js +145 -0
  141. package/src/io/mouseWheel.js +28 -0
  142. package/src/io/userData.js +24 -0
  143. package/src/io/video.js +210 -0
  144. package/src/playground/benchmark.css +83 -0
  145. package/src/playground/benchmark.js +753 -0
  146. package/src/playground/index.html +111 -0
  147. package/src/playground/suite.css +78 -0
  148. package/src/playground/suite.html +25 -0
  149. package/src/playground/suite.js +544 -0
  150. package/src/playground/video-sensing.html +18 -0
  151. package/src/playground/video-sensing.js +133 -0
  152. package/src/serialization/deserialize-assets.js +178 -0
  153. package/src/serialization/sb2.js +1295 -0
  154. package/src/serialization/sb2_specmap.js +1818 -0
  155. package/src/serialization/sb3.js +1320 -0
  156. package/src/serialization/serialize-assets.js +60 -0
  157. package/src/sprites/rendered-target.js +1115 -0
  158. package/src/sprites/sprite.js +177 -0
  159. package/src/util/base64-util.js +48 -0
  160. package/src/util/cast.js +218 -0
  161. package/src/util/clone.js +17 -0
  162. package/src/util/color.js +204 -0
  163. package/src/util/fetch-with-timeout.js +53 -0
  164. package/src/util/get-monitor-id.js +33 -0
  165. package/src/util/jsonrpc.js +114 -0
  166. package/src/util/log.js +4 -0
  167. package/src/util/math-util.js +122 -0
  168. package/src/util/maybe-format-message.js +18 -0
  169. package/src/util/new-block-ids.js +33 -0
  170. package/src/util/rateLimiter.js +73 -0
  171. package/src/util/scratch-link-websocket.js +133 -0
  172. package/src/util/string-util.js +94 -0
  173. package/src/util/task-queue.js +203 -0
  174. package/src/util/timer.js +103 -0
  175. package/src/util/uid.js +29 -0
  176. package/src/util/variable-util.js +48 -0
  177. package/src/util/xml-escape.js +33 -0
  178. package/src/virtual-machine.js +1586 -0
@@ -0,0 +1,1818 @@
1
+ /**
2
+ * @fileoverview
3
+ * The specMap below handles a few pieces of "translation" work between
4
+ * the SB2 JSON format and the data we need to run a project
5
+ * in the Scratch 3.0 VM.
6
+ * Notably:
7
+ * - Map 2.0 and 1.4 opcodes (forward:) into 3.0-format (motion_movesteps).
8
+ * - Map ordered, unnamed args to unordered, named inputs and fields.
9
+ * Keep this up-to-date as 3.0 blocks are renamed, changed, etc.
10
+ * Originally this was generated largely by a hand-guided scripting process.
11
+ * The relevant data lives here:
12
+ * https://github.com/scratchfoundation/scratch-flash/blob/master/src/Specs.as
13
+ * (for the old opcode and argument order).
14
+ * and here:
15
+ * https://github.com/scratchfoundation/scratch-blocks/tree/develop/blocks_vertical
16
+ * (for the new opcodes and argument names).
17
+ * and here:
18
+ * https://github.com/scratchfoundation/scratch-blocks/blob/develop/tests/
19
+ * (for the shadow blocks created for each block).
20
+ * I started with the `commands` array in Specs.as, and discarded irrelevant
21
+ * properties. By hand, I matched the opcode name to the 3.0 opcode.
22
+ * Finally, I filled in the expected arguments as below.
23
+ */
24
+
25
+ const Variable = require('../engine/variable');
26
+
27
+ /**
28
+ * @typedef {object} SB2SpecMap_blockInfo
29
+ * @property {string} opcode - the Scratch 3.0 block opcode. Use 'extensionID.opcode' for extension opcodes.
30
+ * @property {Array.<SB2SpecMap_argInfo>} argMap - metadata for this block's arguments.
31
+ */
32
+
33
+ /**
34
+ * @typedef {object} SB2SpecMap_argInfo
35
+ * @property {string} type - the type of this arg (such as 'input' or 'field')
36
+ * @property {string} inputOp - the scratch-blocks shadow type for this arg
37
+ * @property {string} inputName - the name this argument will take when provided to the block implementation
38
+ */
39
+
40
+ /**
41
+ * Mapping of Scratch 2.0 opcode to Scratch 3.0 block metadata.
42
+ * @type {object.<SB2SpecMap_blockInfo>}
43
+ */
44
+ const specMap = {
45
+ 'forward:': {
46
+ opcode: 'motion_movesteps',
47
+ argMap: [
48
+ {
49
+ type: 'input',
50
+ inputOp: 'math_number',
51
+ inputName: 'STEPS'
52
+ }
53
+ ]
54
+ },
55
+ 'turnRight:': {
56
+ opcode: 'motion_turnright',
57
+ argMap: [
58
+ {
59
+ type: 'input',
60
+ inputOp: 'math_number',
61
+ inputName: 'DEGREES'
62
+ }
63
+ ]
64
+ },
65
+ 'turnLeft:': {
66
+ opcode: 'motion_turnleft',
67
+ argMap: [
68
+ {
69
+ type: 'input',
70
+ inputOp: 'math_number',
71
+ inputName: 'DEGREES'
72
+ }
73
+ ]
74
+ },
75
+ 'heading:': {
76
+ opcode: 'motion_pointindirection',
77
+ argMap: [
78
+ {
79
+ type: 'input',
80
+ inputOp: 'math_angle',
81
+ inputName: 'DIRECTION'
82
+ }
83
+ ]
84
+ },
85
+ 'pointTowards:': {
86
+ opcode: 'motion_pointtowards',
87
+ argMap: [
88
+ {
89
+ type: 'input',
90
+ inputOp: 'motion_pointtowards_menu',
91
+ inputName: 'TOWARDS'
92
+ }
93
+ ]
94
+ },
95
+ 'gotoX:y:': {
96
+ opcode: 'motion_gotoxy',
97
+ argMap: [
98
+ {
99
+ type: 'input',
100
+ inputOp: 'math_number',
101
+ inputName: 'X'
102
+ },
103
+ {
104
+ type: 'input',
105
+ inputOp: 'math_number',
106
+ inputName: 'Y'
107
+ }
108
+ ]
109
+ },
110
+ 'gotoSpriteOrMouse:': {
111
+ opcode: 'motion_goto',
112
+ argMap: [
113
+ {
114
+ type: 'input',
115
+ inputOp: 'motion_goto_menu',
116
+ inputName: 'TO'
117
+ }
118
+ ]
119
+ },
120
+ 'glideSecs:toX:y:elapsed:from:': {
121
+ opcode: 'motion_glidesecstoxy',
122
+ argMap: [
123
+ {
124
+ type: 'input',
125
+ inputOp: 'math_number',
126
+ inputName: 'SECS'
127
+ },
128
+ {
129
+ type: 'input',
130
+ inputOp: 'math_number',
131
+ inputName: 'X'
132
+ },
133
+ {
134
+ type: 'input',
135
+ inputOp: 'math_number',
136
+ inputName: 'Y'
137
+ }
138
+ ]
139
+ },
140
+ 'changeXposBy:': {
141
+ opcode: 'motion_changexby',
142
+ argMap: [
143
+ {
144
+ type: 'input',
145
+ inputOp: 'math_number',
146
+ inputName: 'DX'
147
+ }
148
+ ]
149
+ },
150
+ 'xpos:': {
151
+ opcode: 'motion_setx',
152
+ argMap: [
153
+ {
154
+ type: 'input',
155
+ inputOp: 'math_number',
156
+ inputName: 'X'
157
+ }
158
+ ]
159
+ },
160
+ 'changeYposBy:': {
161
+ opcode: 'motion_changeyby',
162
+ argMap: [
163
+ {
164
+ type: 'input',
165
+ inputOp: 'math_number',
166
+ inputName: 'DY'
167
+ }
168
+ ]
169
+ },
170
+ 'ypos:': {
171
+ opcode: 'motion_sety',
172
+ argMap: [
173
+ {
174
+ type: 'input',
175
+ inputOp: 'math_number',
176
+ inputName: 'Y'
177
+ }
178
+ ]
179
+ },
180
+ 'bounceOffEdge': {
181
+ opcode: 'motion_ifonedgebounce',
182
+ argMap: [
183
+ ]
184
+ },
185
+ 'setRotationStyle': {
186
+ opcode: 'motion_setrotationstyle',
187
+ argMap: [
188
+ {
189
+ type: 'field',
190
+ fieldName: 'STYLE'
191
+ }
192
+ ]
193
+ },
194
+ 'xpos': {
195
+ opcode: 'motion_xposition',
196
+ argMap: [
197
+ ]
198
+ },
199
+ 'ypos': {
200
+ opcode: 'motion_yposition',
201
+ argMap: [
202
+ ]
203
+ },
204
+ 'heading': {
205
+ opcode: 'motion_direction',
206
+ argMap: [
207
+ ]
208
+ },
209
+ 'scrollRight': {
210
+ opcode: 'motion_scroll_right',
211
+ argMap: [
212
+ {
213
+ type: 'input',
214
+ inputOp: 'math_number',
215
+ inputName: 'DISTANCE'
216
+ }
217
+ ]
218
+ },
219
+ 'scrollUp': {
220
+ opcode: 'motion_scroll_up',
221
+ argMap: [
222
+ {
223
+ type: 'input',
224
+ inputOp: 'math_number',
225
+ inputName: 'DISTANCE'
226
+ }
227
+ ]
228
+ },
229
+ 'scrollAlign': {
230
+ opcode: 'motion_align_scene',
231
+ argMap: [
232
+ {
233
+ type: 'field',
234
+ fieldName: 'ALIGNMENT'
235
+ }
236
+ ]
237
+ },
238
+ 'xScroll': {
239
+ opcode: 'motion_xscroll',
240
+ argMap: [
241
+ ]
242
+ },
243
+ 'yScroll': {
244
+ opcode: 'motion_yscroll',
245
+ argMap: [
246
+ ]
247
+ },
248
+ 'say:duration:elapsed:from:': {
249
+ opcode: 'looks_sayforsecs',
250
+ argMap: [
251
+ {
252
+ type: 'input',
253
+ inputOp: 'text',
254
+ inputName: 'MESSAGE'
255
+ },
256
+ {
257
+ type: 'input',
258
+ inputOp: 'math_number',
259
+ inputName: 'SECS'
260
+ }
261
+ ]
262
+ },
263
+ 'say:': {
264
+ opcode: 'looks_say',
265
+ argMap: [
266
+ {
267
+ type: 'input',
268
+ inputOp: 'text',
269
+ inputName: 'MESSAGE'
270
+ }
271
+ ]
272
+ },
273
+ 'think:duration:elapsed:from:': {
274
+ opcode: 'looks_thinkforsecs',
275
+ argMap: [
276
+ {
277
+ type: 'input',
278
+ inputOp: 'text',
279
+ inputName: 'MESSAGE'
280
+ },
281
+ {
282
+ type: 'input',
283
+ inputOp: 'math_number',
284
+ inputName: 'SECS'
285
+ }
286
+ ]
287
+ },
288
+ 'think:': {
289
+ opcode: 'looks_think',
290
+ argMap: [
291
+ {
292
+ type: 'input',
293
+ inputOp: 'text',
294
+ inputName: 'MESSAGE'
295
+ }
296
+ ]
297
+ },
298
+ 'show': {
299
+ opcode: 'looks_show',
300
+ argMap: [
301
+ ]
302
+ },
303
+ 'hide': {
304
+ opcode: 'looks_hide',
305
+ argMap: [
306
+ ]
307
+ },
308
+ 'hideAll': {
309
+ opcode: 'looks_hideallsprites',
310
+ argMap: [
311
+ ]
312
+ },
313
+ 'lookLike:': {
314
+ opcode: 'looks_switchcostumeto',
315
+ argMap: [
316
+ {
317
+ type: 'input',
318
+ inputOp: 'looks_costume',
319
+ inputName: 'COSTUME'
320
+ }
321
+ ]
322
+ },
323
+ 'nextCostume': {
324
+ opcode: 'looks_nextcostume',
325
+ argMap: [
326
+ ]
327
+ },
328
+ 'startScene': {
329
+ opcode: 'looks_switchbackdropto',
330
+ argMap: [
331
+ {
332
+ type: 'input',
333
+ inputOp: 'looks_backdrops',
334
+ inputName: 'BACKDROP'
335
+ }
336
+ ]
337
+ },
338
+ 'changeGraphicEffect:by:': {
339
+ opcode: 'looks_changeeffectby',
340
+ argMap: [
341
+ {
342
+ type: 'field',
343
+ fieldName: 'EFFECT'
344
+ },
345
+ {
346
+ type: 'input',
347
+ inputOp: 'math_number',
348
+ inputName: 'CHANGE'
349
+ }
350
+ ]
351
+ },
352
+ 'setGraphicEffect:to:': {
353
+ opcode: 'looks_seteffectto',
354
+ argMap: [
355
+ {
356
+ type: 'field',
357
+ fieldName: 'EFFECT'
358
+ },
359
+ {
360
+ type: 'input',
361
+ inputOp: 'math_number',
362
+ inputName: 'VALUE'
363
+ }
364
+ ]
365
+ },
366
+ 'filterReset': {
367
+ opcode: 'looks_cleargraphiceffects',
368
+ argMap: [
369
+ ]
370
+ },
371
+ 'changeSizeBy:': {
372
+ opcode: 'looks_changesizeby',
373
+ argMap: [
374
+ {
375
+ type: 'input',
376
+ inputOp: 'math_number',
377
+ inputName: 'CHANGE'
378
+ }
379
+ ]
380
+ },
381
+ 'setSizeTo:': {
382
+ opcode: 'looks_setsizeto',
383
+ argMap: [
384
+ {
385
+ type: 'input',
386
+ inputOp: 'math_number',
387
+ inputName: 'SIZE'
388
+ }
389
+ ]
390
+ },
391
+ 'changeStretchBy:': {
392
+ opcode: 'looks_changestretchby',
393
+ argMap: [
394
+ {
395
+ type: 'input',
396
+ inputOp: 'math_number',
397
+ inputName: 'CHANGE'
398
+ }
399
+ ]
400
+ },
401
+ 'setStretchTo:': {
402
+ opcode: 'looks_setstretchto',
403
+ argMap: [
404
+ {
405
+ type: 'input',
406
+ inputOp: 'math_number',
407
+ inputName: 'STRETCH'
408
+ }
409
+ ]
410
+ },
411
+ 'comeToFront': {
412
+ opcode: 'looks_gotofrontback',
413
+ argMap: [
414
+ ]
415
+ },
416
+ 'goBackByLayers:': {
417
+ opcode: 'looks_goforwardbackwardlayers',
418
+ argMap: [
419
+ {
420
+ type: 'input',
421
+ inputOp: 'math_integer',
422
+ inputName: 'NUM'
423
+ }
424
+ ]
425
+ },
426
+ 'costumeIndex': {
427
+ opcode: 'looks_costumenumbername',
428
+ argMap: [
429
+ ]
430
+ },
431
+ 'costumeName': {
432
+ opcode: 'looks_costumenumbername',
433
+ argMap: [
434
+ ]
435
+ },
436
+ 'sceneName': {
437
+ opcode: 'looks_backdropnumbername',
438
+ argMap: [
439
+ ]
440
+ },
441
+ 'scale': {
442
+ opcode: 'looks_size',
443
+ argMap: [
444
+ ]
445
+ },
446
+ 'startSceneAndWait': {
447
+ opcode: 'looks_switchbackdroptoandwait',
448
+ argMap: [
449
+ {
450
+ type: 'input',
451
+ inputOp: 'looks_backdrops',
452
+ inputName: 'BACKDROP'
453
+ }
454
+ ]
455
+ },
456
+ 'nextScene': {
457
+ opcode: 'looks_nextbackdrop',
458
+ argMap: [
459
+ ]
460
+ },
461
+ 'backgroundIndex': {
462
+ opcode: 'looks_backdropnumbername',
463
+ argMap: [
464
+ ]
465
+ },
466
+ 'playSound:': {
467
+ opcode: 'sound_play',
468
+ argMap: [
469
+ {
470
+ type: 'input',
471
+ inputOp: 'sound_sounds_menu',
472
+ inputName: 'SOUND_MENU'
473
+ }
474
+ ]
475
+ },
476
+ 'doPlaySoundAndWait': {
477
+ opcode: 'sound_playuntildone',
478
+ argMap: [
479
+ {
480
+ type: 'input',
481
+ inputOp: 'sound_sounds_menu',
482
+ inputName: 'SOUND_MENU'
483
+ }
484
+ ]
485
+ },
486
+ 'stopAllSounds': {
487
+ opcode: 'sound_stopallsounds',
488
+ argMap: [
489
+ ]
490
+ },
491
+ 'playDrum': {
492
+ opcode: 'music_playDrumForBeats',
493
+ argMap: [
494
+ {
495
+ type: 'input',
496
+ inputOp: 'music_menu_DRUM',
497
+ inputName: 'DRUM'
498
+ },
499
+ {
500
+ type: 'input',
501
+ inputOp: 'math_number',
502
+ inputName: 'BEATS'
503
+ }
504
+ ]
505
+ },
506
+ 'drum:duration:elapsed:from:': {
507
+ opcode: 'music_midiPlayDrumForBeats',
508
+ argMap: [
509
+ {
510
+ type: 'input',
511
+ inputOp: 'math_number',
512
+ inputName: 'DRUM'
513
+ },
514
+ {
515
+ type: 'input',
516
+ inputOp: 'math_number',
517
+ inputName: 'BEATS'
518
+ }
519
+ ]
520
+ },
521
+ 'rest:elapsed:from:': {
522
+ opcode: 'music_restForBeats',
523
+ argMap: [
524
+ {
525
+ type: 'input',
526
+ inputOp: 'math_number',
527
+ inputName: 'BEATS'
528
+ }
529
+ ]
530
+ },
531
+ 'noteOn:duration:elapsed:from:': {
532
+ opcode: 'music_playNoteForBeats',
533
+ argMap: [
534
+ {
535
+ type: 'input',
536
+ inputOp: 'note',
537
+ inputName: 'NOTE'
538
+ },
539
+ {
540
+ type: 'input',
541
+ inputOp: 'math_number',
542
+ inputName: 'BEATS'
543
+ }
544
+ ]
545
+ },
546
+ 'instrument:': {
547
+ opcode: 'music_setInstrument',
548
+ argMap: [
549
+ {
550
+ type: 'input',
551
+ inputOp: 'music_menu_INSTRUMENT',
552
+ inputName: 'INSTRUMENT'
553
+ }
554
+ ]
555
+ },
556
+ 'midiInstrument:': {
557
+ opcode: 'music_midiSetInstrument',
558
+ argMap: [
559
+ {
560
+ type: 'input',
561
+ inputOp: 'math_number',
562
+ inputName: 'INSTRUMENT'
563
+ }
564
+ ]
565
+ },
566
+ 'changeVolumeBy:': {
567
+ opcode: 'sound_changevolumeby',
568
+ argMap: [
569
+ {
570
+ type: 'input',
571
+ inputOp: 'math_number',
572
+ inputName: 'VOLUME'
573
+ }
574
+ ]
575
+ },
576
+ 'setVolumeTo:': {
577
+ opcode: 'sound_setvolumeto',
578
+ argMap: [
579
+ {
580
+ type: 'input',
581
+ inputOp: 'math_number',
582
+ inputName: 'VOLUME'
583
+ }
584
+ ]
585
+ },
586
+ 'volume': {
587
+ opcode: 'sound_volume',
588
+ argMap: [
589
+ ]
590
+ },
591
+ 'changeTempoBy:': {
592
+ opcode: 'music_changeTempo',
593
+ argMap: [
594
+ {
595
+ type: 'input',
596
+ inputOp: 'math_number',
597
+ inputName: 'TEMPO'
598
+ }
599
+ ]
600
+ },
601
+ 'setTempoTo:': {
602
+ opcode: 'music_setTempo',
603
+ argMap: [
604
+ {
605
+ type: 'input',
606
+ inputOp: 'math_number',
607
+ inputName: 'TEMPO'
608
+ }
609
+ ]
610
+ },
611
+ 'tempo': {
612
+ opcode: 'music_getTempo',
613
+ argMap: [
614
+ ]
615
+ },
616
+ 'clearPenTrails': {
617
+ opcode: 'pen_clear',
618
+ argMap: [
619
+ ]
620
+ },
621
+ 'stampCostume': {
622
+ opcode: 'pen_stamp',
623
+ argMap: [
624
+ ]
625
+ },
626
+ 'putPenDown': {
627
+ opcode: 'pen_penDown',
628
+ argMap: [
629
+ ]
630
+ },
631
+ 'putPenUp': {
632
+ opcode: 'pen_penUp',
633
+ argMap: [
634
+ ]
635
+ },
636
+ 'penColor:': {
637
+ opcode: 'pen_setPenColorToColor',
638
+ argMap: [
639
+ {
640
+ type: 'input',
641
+ inputOp: 'colour_picker',
642
+ inputName: 'COLOR'
643
+ }
644
+ ]
645
+ },
646
+ 'changePenHueBy:': {
647
+ opcode: 'pen_changePenHueBy',
648
+ argMap: [
649
+ {
650
+ type: 'input',
651
+ inputOp: 'math_number',
652
+ inputName: 'HUE'
653
+ }
654
+ ]
655
+ },
656
+ 'setPenHueTo:': {
657
+ opcode: 'pen_setPenHueToNumber',
658
+ argMap: [
659
+ {
660
+ type: 'input',
661
+ inputOp: 'math_number',
662
+ inputName: 'HUE'
663
+ }
664
+ ]
665
+ },
666
+ 'changePenShadeBy:': {
667
+ opcode: 'pen_changePenShadeBy',
668
+ argMap: [
669
+ {
670
+ type: 'input',
671
+ inputOp: 'math_number',
672
+ inputName: 'SHADE'
673
+ }
674
+ ]
675
+ },
676
+ 'setPenShadeTo:': {
677
+ opcode: 'pen_setPenShadeToNumber',
678
+ argMap: [
679
+ {
680
+ type: 'input',
681
+ inputOp: 'math_number',
682
+ inputName: 'SHADE'
683
+ }
684
+ ]
685
+ },
686
+ 'changePenSizeBy:': {
687
+ opcode: 'pen_changePenSizeBy',
688
+ argMap: [
689
+ {
690
+ type: 'input',
691
+ inputOp: 'math_number',
692
+ inputName: 'SIZE'
693
+ }
694
+ ]
695
+ },
696
+ 'penSize:': {
697
+ opcode: 'pen_setPenSizeTo',
698
+ argMap: [
699
+ {
700
+ type: 'input',
701
+ inputOp: 'math_number',
702
+ inputName: 'SIZE'
703
+ }
704
+ ]
705
+ },
706
+ 'senseVideoMotion': {
707
+ opcode: 'videoSensing_videoOn',
708
+ argMap: [
709
+ {
710
+ type: 'input',
711
+ inputOp: 'videoSensing_menu_ATTRIBUTE',
712
+ inputName: 'ATTRIBUTE'
713
+ },
714
+ {
715
+ type: 'input',
716
+ inputOp: 'videoSensing_menu_SUBJECT',
717
+ inputName: 'SUBJECT'
718
+ }
719
+ ]
720
+ },
721
+ 'whenGreenFlag': {
722
+ opcode: 'event_whenflagclicked',
723
+ argMap: [
724
+ ]
725
+ },
726
+ 'whenKeyPressed': {
727
+ opcode: 'event_whenkeypressed',
728
+ argMap: [
729
+ {
730
+ type: 'field',
731
+ fieldName: 'KEY_OPTION'
732
+ }
733
+ ]
734
+ },
735
+ 'whenClicked': {
736
+ opcode: 'event_whenthisspriteclicked',
737
+ argMap: [
738
+ ]
739
+ },
740
+ 'whenSceneStarts': {
741
+ opcode: 'event_whenbackdropswitchesto',
742
+ argMap: [
743
+ {
744
+ type: 'field',
745
+ fieldName: 'BACKDROP'
746
+ }
747
+ ]
748
+ },
749
+ 'whenSensorGreaterThan': ([, sensor]) => {
750
+ if (sensor === 'video motion') {
751
+ return {
752
+ opcode: 'videoSensing_whenMotionGreaterThan',
753
+ argMap: [
754
+ // skip the first arg, since we converted to a video specific sensing block
755
+ {},
756
+ {
757
+ type: 'input',
758
+ inputOp: 'math_number',
759
+ inputName: 'REFERENCE'
760
+ }
761
+ ]
762
+ };
763
+ }
764
+ return {
765
+ opcode: 'event_whengreaterthan',
766
+ argMap: [
767
+ {
768
+ type: 'field',
769
+ fieldName: 'WHENGREATERTHANMENU'
770
+ },
771
+ {
772
+ type: 'input',
773
+ inputOp: 'math_number',
774
+ inputName: 'VALUE'
775
+ }
776
+ ]
777
+ };
778
+ },
779
+ 'whenIReceive': {
780
+ opcode: 'event_whenbroadcastreceived',
781
+ argMap: [
782
+ {
783
+ type: 'field',
784
+ fieldName: 'BROADCAST_OPTION',
785
+ variableType: Variable.BROADCAST_MESSAGE_TYPE
786
+ }
787
+ ]
788
+ },
789
+ 'broadcast:': {
790
+ opcode: 'event_broadcast',
791
+ argMap: [
792
+ {
793
+ type: 'input',
794
+ inputOp: 'event_broadcast_menu',
795
+ inputName: 'BROADCAST_INPUT',
796
+ variableType: Variable.BROADCAST_MESSAGE_TYPE
797
+ }
798
+ ]
799
+ },
800
+ 'doBroadcastAndWait': {
801
+ opcode: 'event_broadcastandwait',
802
+ argMap: [
803
+ {
804
+ type: 'input',
805
+ inputOp: 'event_broadcast_menu',
806
+ inputName: 'BROADCAST_INPUT',
807
+ variableType: Variable.BROADCAST_MESSAGE_TYPE
808
+ }
809
+ ]
810
+ },
811
+ 'wait:elapsed:from:': {
812
+ opcode: 'control_wait',
813
+ argMap: [
814
+ {
815
+ type: 'input',
816
+ inputOp: 'math_positive_number',
817
+ inputName: 'DURATION'
818
+ }
819
+ ]
820
+ },
821
+ 'doRepeat': {
822
+ opcode: 'control_repeat',
823
+ argMap: [
824
+ {
825
+ type: 'input',
826
+ inputOp: 'math_whole_number',
827
+ inputName: 'TIMES'
828
+ },
829
+ {
830
+ type: 'input',
831
+ inputOp: 'substack',
832
+ inputName: 'SUBSTACK'
833
+ }
834
+ ]
835
+ },
836
+ 'doForever': {
837
+ opcode: 'control_forever',
838
+ argMap: [
839
+ {
840
+ type: 'input',
841
+ inputOp: 'substack',
842
+ inputName: 'SUBSTACK'
843
+ }
844
+ ]
845
+ },
846
+ 'doIf': {
847
+ opcode: 'control_if',
848
+ argMap: [
849
+ {
850
+ type: 'input',
851
+ inputOp: 'boolean',
852
+ inputName: 'CONDITION'
853
+ },
854
+ {
855
+ type: 'input',
856
+ inputOp: 'substack',
857
+ inputName: 'SUBSTACK'
858
+ }
859
+ ]
860
+ },
861
+ 'doIfElse': {
862
+ opcode: 'control_if_else',
863
+ argMap: [
864
+ {
865
+ type: 'input',
866
+ inputOp: 'boolean',
867
+ inputName: 'CONDITION'
868
+ },
869
+ {
870
+ type: 'input',
871
+ inputOp: 'substack',
872
+ inputName: 'SUBSTACK'
873
+ },
874
+ {
875
+ type: 'input',
876
+ inputOp: 'substack',
877
+ inputName: 'SUBSTACK2'
878
+ }
879
+ ]
880
+ },
881
+ 'doWaitUntil': {
882
+ opcode: 'control_wait_until',
883
+ argMap: [
884
+ {
885
+ type: 'input',
886
+ inputOp: 'boolean',
887
+ inputName: 'CONDITION'
888
+ }
889
+ ]
890
+ },
891
+ 'doUntil': {
892
+ opcode: 'control_repeat_until',
893
+ argMap: [
894
+ {
895
+ type: 'input',
896
+ inputOp: 'boolean',
897
+ inputName: 'CONDITION'
898
+ },
899
+ {
900
+ type: 'input',
901
+ inputOp: 'substack',
902
+ inputName: 'SUBSTACK'
903
+ }
904
+ ]
905
+ },
906
+ 'doWhile': {
907
+ opcode: 'control_while',
908
+ argMap: [
909
+ {
910
+ type: 'input',
911
+ inputOp: 'boolean',
912
+ inputName: 'CONDITION'
913
+ },
914
+ {
915
+ type: 'input',
916
+ inputOp: 'substack',
917
+ inputName: 'SUBSTACK'
918
+ }
919
+ ]
920
+ },
921
+ 'doForLoop': {
922
+ opcode: 'control_for_each',
923
+ argMap: [
924
+ {
925
+ type: 'field',
926
+ fieldName: 'VARIABLE'
927
+ },
928
+ {
929
+ type: 'input',
930
+ inputOp: 'text',
931
+ inputName: 'VALUE'
932
+ },
933
+ {
934
+ type: 'input',
935
+ inputOp: 'substack',
936
+ inputName: 'SUBSTACK'
937
+ }
938
+ ]
939
+ },
940
+ 'stopScripts': {
941
+ opcode: 'control_stop',
942
+ argMap: [
943
+ {
944
+ type: 'field',
945
+ fieldName: 'STOP_OPTION'
946
+ }
947
+ ]
948
+ },
949
+ 'whenCloned': {
950
+ opcode: 'control_start_as_clone',
951
+ argMap: [
952
+ ]
953
+ },
954
+ 'createCloneOf': {
955
+ opcode: 'control_create_clone_of',
956
+ argMap: [
957
+ {
958
+ type: 'input',
959
+ inputOp: 'control_create_clone_of_menu',
960
+ inputName: 'CLONE_OPTION'
961
+ }
962
+ ]
963
+ },
964
+ 'deleteClone': {
965
+ opcode: 'control_delete_this_clone',
966
+ argMap: [
967
+ ]
968
+ },
969
+ 'COUNT': {
970
+ opcode: 'control_get_counter',
971
+ argMap: [
972
+ ]
973
+ },
974
+ 'INCR_COUNT': {
975
+ opcode: 'control_incr_counter',
976
+ argMap: [
977
+ ]
978
+ },
979
+ 'CLR_COUNT': {
980
+ opcode: 'control_clear_counter',
981
+ argMap: [
982
+ ]
983
+ },
984
+ 'warpSpeed': {
985
+ opcode: 'control_all_at_once',
986
+ argMap: [
987
+ {
988
+ type: 'input',
989
+ inputOp: 'substack',
990
+ inputName: 'SUBSTACK'
991
+ }
992
+ ]
993
+ },
994
+ 'touching:': {
995
+ opcode: 'sensing_touchingobject',
996
+ argMap: [
997
+ {
998
+ type: 'input',
999
+ inputOp: 'sensing_touchingobjectmenu',
1000
+ inputName: 'TOUCHINGOBJECTMENU'
1001
+ }
1002
+ ]
1003
+ },
1004
+ 'touchingColor:': {
1005
+ opcode: 'sensing_touchingcolor',
1006
+ argMap: [
1007
+ {
1008
+ type: 'input',
1009
+ inputOp: 'colour_picker',
1010
+ inputName: 'COLOR'
1011
+ }
1012
+ ]
1013
+ },
1014
+ 'color:sees:': {
1015
+ opcode: 'sensing_coloristouchingcolor',
1016
+ argMap: [
1017
+ {
1018
+ type: 'input',
1019
+ inputOp: 'colour_picker',
1020
+ inputName: 'COLOR'
1021
+ },
1022
+ {
1023
+ type: 'input',
1024
+ inputOp: 'colour_picker',
1025
+ inputName: 'COLOR2'
1026
+ }
1027
+ ]
1028
+ },
1029
+ 'distanceTo:': {
1030
+ opcode: 'sensing_distanceto',
1031
+ argMap: [
1032
+ {
1033
+ type: 'input',
1034
+ inputOp: 'sensing_distancetomenu',
1035
+ inputName: 'DISTANCETOMENU'
1036
+ }
1037
+ ]
1038
+ },
1039
+ 'doAsk': {
1040
+ opcode: 'sensing_askandwait',
1041
+ argMap: [
1042
+ {
1043
+ type: 'input',
1044
+ inputOp: 'text',
1045
+ inputName: 'QUESTION'
1046
+ }
1047
+ ]
1048
+ },
1049
+ 'answer': {
1050
+ opcode: 'sensing_answer',
1051
+ argMap: [
1052
+ ]
1053
+ },
1054
+ 'keyPressed:': {
1055
+ opcode: 'sensing_keypressed',
1056
+ argMap: [
1057
+ {
1058
+ type: 'input',
1059
+ inputOp: 'sensing_keyoptions',
1060
+ inputName: 'KEY_OPTION'
1061
+ }
1062
+ ]
1063
+ },
1064
+ 'mousePressed': {
1065
+ opcode: 'sensing_mousedown',
1066
+ argMap: [
1067
+ ]
1068
+ },
1069
+ 'mouseX': {
1070
+ opcode: 'sensing_mousex',
1071
+ argMap: [
1072
+ ]
1073
+ },
1074
+ 'mouseY': {
1075
+ opcode: 'sensing_mousey',
1076
+ argMap: [
1077
+ ]
1078
+ },
1079
+ 'soundLevel': {
1080
+ opcode: 'sensing_loudness',
1081
+ argMap: [
1082
+ ]
1083
+ },
1084
+ 'isLoud': {
1085
+ opcode: 'sensing_loud',
1086
+ argMap: [
1087
+ ]
1088
+ },
1089
+ // 'senseVideoMotion': {
1090
+ // opcode: 'sensing_videoon',
1091
+ // argMap: [
1092
+ // {
1093
+ // type: 'input',
1094
+ // inputOp: 'sensing_videoonmenuone',
1095
+ // inputName: 'VIDEOONMENU1'
1096
+ // },
1097
+ // {
1098
+ // type: 'input',
1099
+ // inputOp: 'sensing_videoonmenutwo',
1100
+ // inputName: 'VIDEOONMENU2'
1101
+ // }
1102
+ // ]
1103
+ // },
1104
+ 'setVideoState': {
1105
+ opcode: 'videoSensing_videoToggle',
1106
+ argMap: [
1107
+ {
1108
+ type: 'input',
1109
+ inputOp: 'videoSensing_menu_VIDEO_STATE',
1110
+ inputName: 'VIDEO_STATE'
1111
+ }
1112
+ ]
1113
+ },
1114
+ 'setVideoTransparency': {
1115
+ opcode: 'videoSensing_setVideoTransparency',
1116
+ argMap: [
1117
+ {
1118
+ type: 'input',
1119
+ inputOp: 'math_number',
1120
+ inputName: 'TRANSPARENCY'
1121
+ }
1122
+ ]
1123
+ },
1124
+ 'timer': {
1125
+ opcode: 'sensing_timer',
1126
+ argMap: [
1127
+ ]
1128
+ },
1129
+ 'timerReset': {
1130
+ opcode: 'sensing_resettimer',
1131
+ argMap: [
1132
+ ]
1133
+ },
1134
+ 'getAttribute:of:': {
1135
+ opcode: 'sensing_of',
1136
+ argMap: [
1137
+ {
1138
+ type: 'field',
1139
+ fieldName: 'PROPERTY'
1140
+ },
1141
+ {
1142
+ type: 'input',
1143
+ inputOp: 'sensing_of_object_menu',
1144
+ inputName: 'OBJECT'
1145
+ }
1146
+ ]
1147
+ },
1148
+ 'timeAndDate': {
1149
+ opcode: 'sensing_current',
1150
+ argMap: [
1151
+ {
1152
+ type: 'field',
1153
+ fieldName: 'CURRENTMENU'
1154
+ }
1155
+ ]
1156
+ },
1157
+ 'timestamp': {
1158
+ opcode: 'sensing_dayssince2000',
1159
+ argMap: [
1160
+ ]
1161
+ },
1162
+ 'getUserName': {
1163
+ opcode: 'sensing_username',
1164
+ argMap: [
1165
+ ]
1166
+ },
1167
+ 'getUserId': {
1168
+ opcode: 'sensing_userid',
1169
+ argMap: [
1170
+ ]
1171
+ },
1172
+ '+': {
1173
+ opcode: 'operator_add',
1174
+ argMap: [
1175
+ {
1176
+ type: 'input',
1177
+ inputOp: 'math_number',
1178
+ inputName: 'NUM1'
1179
+ },
1180
+ {
1181
+ type: 'input',
1182
+ inputOp: 'math_number',
1183
+ inputName: 'NUM2'
1184
+ }
1185
+ ]
1186
+ },
1187
+ '-': {
1188
+ opcode: 'operator_subtract',
1189
+ argMap: [
1190
+ {
1191
+ type: 'input',
1192
+ inputOp: 'math_number',
1193
+ inputName: 'NUM1'
1194
+ },
1195
+ {
1196
+ type: 'input',
1197
+ inputOp: 'math_number',
1198
+ inputName: 'NUM2'
1199
+ }
1200
+ ]
1201
+ },
1202
+ '*': {
1203
+ opcode: 'operator_multiply',
1204
+ argMap: [
1205
+ {
1206
+ type: 'input',
1207
+ inputOp: 'math_number',
1208
+ inputName: 'NUM1'
1209
+ },
1210
+ {
1211
+ type: 'input',
1212
+ inputOp: 'math_number',
1213
+ inputName: 'NUM2'
1214
+ }
1215
+ ]
1216
+ },
1217
+ '/': {
1218
+ opcode: 'operator_divide',
1219
+ argMap: [
1220
+ {
1221
+ type: 'input',
1222
+ inputOp: 'math_number',
1223
+ inputName: 'NUM1'
1224
+ },
1225
+ {
1226
+ type: 'input',
1227
+ inputOp: 'math_number',
1228
+ inputName: 'NUM2'
1229
+ }
1230
+ ]
1231
+ },
1232
+ 'randomFrom:to:': {
1233
+ opcode: 'operator_random',
1234
+ argMap: [
1235
+ {
1236
+ type: 'input',
1237
+ inputOp: 'math_number',
1238
+ inputName: 'FROM'
1239
+ },
1240
+ {
1241
+ type: 'input',
1242
+ inputOp: 'math_number',
1243
+ inputName: 'TO'
1244
+ }
1245
+ ]
1246
+ },
1247
+ '<': {
1248
+ opcode: 'operator_lt',
1249
+ argMap: [
1250
+ {
1251
+ type: 'input',
1252
+ inputOp: 'text',
1253
+ inputName: 'OPERAND1'
1254
+ },
1255
+ {
1256
+ type: 'input',
1257
+ inputOp: 'text',
1258
+ inputName: 'OPERAND2'
1259
+ }
1260
+ ]
1261
+ },
1262
+ '=': {
1263
+ opcode: 'operator_equals',
1264
+ argMap: [
1265
+ {
1266
+ type: 'input',
1267
+ inputOp: 'text',
1268
+ inputName: 'OPERAND1'
1269
+ },
1270
+ {
1271
+ type: 'input',
1272
+ inputOp: 'text',
1273
+ inputName: 'OPERAND2'
1274
+ }
1275
+ ]
1276
+ },
1277
+ '>': {
1278
+ opcode: 'operator_gt',
1279
+ argMap: [
1280
+ {
1281
+ type: 'input',
1282
+ inputOp: 'text',
1283
+ inputName: 'OPERAND1'
1284
+ },
1285
+ {
1286
+ type: 'input',
1287
+ inputOp: 'text',
1288
+ inputName: 'OPERAND2'
1289
+ }
1290
+ ]
1291
+ },
1292
+ '&': {
1293
+ opcode: 'operator_and',
1294
+ argMap: [
1295
+ {
1296
+ type: 'input',
1297
+ inputOp: 'boolean',
1298
+ inputName: 'OPERAND1'
1299
+ },
1300
+ {
1301
+ type: 'input',
1302
+ inputOp: 'boolean',
1303
+ inputName: 'OPERAND2'
1304
+ }
1305
+ ]
1306
+ },
1307
+ '|': {
1308
+ opcode: 'operator_or',
1309
+ argMap: [
1310
+ {
1311
+ type: 'input',
1312
+ inputOp: 'boolean',
1313
+ inputName: 'OPERAND1'
1314
+ },
1315
+ {
1316
+ type: 'input',
1317
+ inputOp: 'boolean',
1318
+ inputName: 'OPERAND2'
1319
+ }
1320
+ ]
1321
+ },
1322
+ 'not': {
1323
+ opcode: 'operator_not',
1324
+ argMap: [
1325
+ {
1326
+ type: 'input',
1327
+ inputOp: 'boolean',
1328
+ inputName: 'OPERAND'
1329
+ }
1330
+ ]
1331
+ },
1332
+ 'concatenate:with:': {
1333
+ opcode: 'operator_join',
1334
+ argMap: [
1335
+ {
1336
+ type: 'input',
1337
+ inputOp: 'text',
1338
+ inputName: 'STRING1'
1339
+ },
1340
+ {
1341
+ type: 'input',
1342
+ inputOp: 'text',
1343
+ inputName: 'STRING2'
1344
+ }
1345
+ ]
1346
+ },
1347
+ 'letter:of:': {
1348
+ opcode: 'operator_letter_of',
1349
+ argMap: [
1350
+ {
1351
+ type: 'input',
1352
+ inputOp: 'math_whole_number',
1353
+ inputName: 'LETTER'
1354
+ },
1355
+ {
1356
+ type: 'input',
1357
+ inputOp: 'text',
1358
+ inputName: 'STRING'
1359
+ }
1360
+ ]
1361
+ },
1362
+ 'stringLength:': {
1363
+ opcode: 'operator_length',
1364
+ argMap: [
1365
+ {
1366
+ type: 'input',
1367
+ inputOp: 'text',
1368
+ inputName: 'STRING'
1369
+ }
1370
+ ]
1371
+ },
1372
+ '%': {
1373
+ opcode: 'operator_mod',
1374
+ argMap: [
1375
+ {
1376
+ type: 'input',
1377
+ inputOp: 'math_number',
1378
+ inputName: 'NUM1'
1379
+ },
1380
+ {
1381
+ type: 'input',
1382
+ inputOp: 'math_number',
1383
+ inputName: 'NUM2'
1384
+ }
1385
+ ]
1386
+ },
1387
+ 'rounded': {
1388
+ opcode: 'operator_round',
1389
+ argMap: [
1390
+ {
1391
+ type: 'input',
1392
+ inputOp: 'math_number',
1393
+ inputName: 'NUM'
1394
+ }
1395
+ ]
1396
+ },
1397
+ 'computeFunction:of:': {
1398
+ opcode: 'operator_mathop',
1399
+ argMap: [
1400
+ {
1401
+ type: 'field',
1402
+ fieldName: 'OPERATOR'
1403
+ },
1404
+ {
1405
+ type: 'input',
1406
+ inputOp: 'math_number',
1407
+ inputName: 'NUM'
1408
+ }
1409
+ ]
1410
+ },
1411
+ 'readVariable': {
1412
+ opcode: 'data_variable',
1413
+ argMap: [
1414
+ {
1415
+ type: 'field',
1416
+ fieldName: 'VARIABLE',
1417
+ variableType: Variable.SCALAR_TYPE
1418
+ }
1419
+ ]
1420
+ },
1421
+ // Scratch 2 uses this alternative variable getter opcode only in monitors,
1422
+ // blocks use the `readVariable` opcode above.
1423
+ 'getVar:': {
1424
+ opcode: 'data_variable',
1425
+ argMap: [
1426
+ {
1427
+ type: 'field',
1428
+ fieldName: 'VARIABLE',
1429
+ variableType: Variable.SCALAR_TYPE
1430
+ }
1431
+ ]
1432
+ },
1433
+ 'setVar:to:': {
1434
+ opcode: 'data_setvariableto',
1435
+ argMap: [
1436
+ {
1437
+ type: 'field',
1438
+ fieldName: 'VARIABLE',
1439
+ variableType: Variable.SCALAR_TYPE
1440
+ },
1441
+ {
1442
+ type: 'input',
1443
+ inputOp: 'text',
1444
+ inputName: 'VALUE'
1445
+ }
1446
+ ]
1447
+ },
1448
+ 'changeVar:by:': {
1449
+ opcode: 'data_changevariableby',
1450
+ argMap: [
1451
+ {
1452
+ type: 'field',
1453
+ fieldName: 'VARIABLE',
1454
+ variableType: Variable.SCALAR_TYPE
1455
+ },
1456
+ {
1457
+ type: 'input',
1458
+ inputOp: 'math_number',
1459
+ inputName: 'VALUE'
1460
+ }
1461
+ ]
1462
+ },
1463
+ 'showVariable:': {
1464
+ opcode: 'data_showvariable',
1465
+ argMap: [
1466
+ {
1467
+ type: 'field',
1468
+ fieldName: 'VARIABLE',
1469
+ variableType: Variable.SCALAR_TYPE
1470
+ }
1471
+ ]
1472
+ },
1473
+ 'hideVariable:': {
1474
+ opcode: 'data_hidevariable',
1475
+ argMap: [
1476
+ {
1477
+ type: 'field',
1478
+ fieldName: 'VARIABLE',
1479
+ variableType: Variable.SCALAR_TYPE
1480
+ }
1481
+ ]
1482
+ },
1483
+ 'contentsOfList:': {
1484
+ opcode: 'data_listcontents',
1485
+ argMap: [
1486
+ {
1487
+ type: 'field',
1488
+ fieldName: 'LIST',
1489
+ variableType: Variable.LIST_TYPE
1490
+ }
1491
+ ]
1492
+ },
1493
+ 'append:toList:': {
1494
+ opcode: 'data_addtolist',
1495
+ argMap: [
1496
+ {
1497
+ type: 'input',
1498
+ inputOp: 'text',
1499
+ inputName: 'ITEM'
1500
+ },
1501
+ {
1502
+ type: 'field',
1503
+ fieldName: 'LIST',
1504
+ variableType: Variable.LIST_TYPE
1505
+ }
1506
+ ]
1507
+ },
1508
+ 'deleteLine:ofList:': {
1509
+ opcode: 'data_deleteoflist',
1510
+ argMap: [
1511
+ {
1512
+ type: 'input',
1513
+ inputOp: 'math_integer',
1514
+ inputName: 'INDEX'
1515
+ },
1516
+ {
1517
+ type: 'field',
1518
+ fieldName: 'LIST',
1519
+ variableType: Variable.LIST_TYPE
1520
+ }
1521
+ ]
1522
+ },
1523
+ 'insert:at:ofList:': {
1524
+ opcode: 'data_insertatlist',
1525
+ argMap: [
1526
+ {
1527
+ type: 'input',
1528
+ inputOp: 'text',
1529
+ inputName: 'ITEM'
1530
+ },
1531
+ {
1532
+ type: 'input',
1533
+ inputOp: 'math_integer',
1534
+ inputName: 'INDEX'
1535
+ },
1536
+ {
1537
+ type: 'field',
1538
+ fieldName: 'LIST',
1539
+ variableType: Variable.LIST_TYPE
1540
+ }
1541
+ ]
1542
+ },
1543
+ 'setLine:ofList:to:': {
1544
+ opcode: 'data_replaceitemoflist',
1545
+ argMap: [
1546
+ {
1547
+ type: 'input',
1548
+ inputOp: 'math_integer',
1549
+ inputName: 'INDEX'
1550
+ },
1551
+ {
1552
+ type: 'field',
1553
+ fieldName: 'LIST',
1554
+ variableType: Variable.LIST_TYPE
1555
+ },
1556
+ {
1557
+ type: 'input',
1558
+ inputOp: 'text',
1559
+ inputName: 'ITEM'
1560
+ }
1561
+ ]
1562
+ },
1563
+ 'getLine:ofList:': {
1564
+ opcode: 'data_itemoflist',
1565
+ argMap: [
1566
+ {
1567
+ type: 'input',
1568
+ inputOp: 'math_integer',
1569
+ inputName: 'INDEX'
1570
+ },
1571
+ {
1572
+ type: 'field',
1573
+ fieldName: 'LIST',
1574
+ variableType: Variable.LIST_TYPE
1575
+ }
1576
+ ]
1577
+ },
1578
+ 'lineCountOfList:': {
1579
+ opcode: 'data_lengthoflist',
1580
+ argMap: [
1581
+ {
1582
+ type: 'field',
1583
+ fieldName: 'LIST',
1584
+ variableType: Variable.LIST_TYPE
1585
+ }
1586
+ ]
1587
+ },
1588
+ 'list:contains:': {
1589
+ opcode: 'data_listcontainsitem',
1590
+ argMap: [
1591
+ {
1592
+ type: 'field',
1593
+ fieldName: 'LIST',
1594
+ variableType: Variable.LIST_TYPE
1595
+ },
1596
+ {
1597
+ type: 'input',
1598
+ inputOp: 'text',
1599
+ inputName: 'ITEM'
1600
+ }
1601
+ ]
1602
+ },
1603
+ 'showList:': {
1604
+ opcode: 'data_showlist',
1605
+ argMap: [
1606
+ {
1607
+ type: 'field',
1608
+ fieldName: 'LIST',
1609
+ variableType: Variable.LIST_TYPE
1610
+ }
1611
+ ]
1612
+ },
1613
+ 'hideList:': {
1614
+ opcode: 'data_hidelist',
1615
+ argMap: [
1616
+ {
1617
+ type: 'field',
1618
+ fieldName: 'LIST',
1619
+ variableType: Variable.LIST_TYPE
1620
+ }
1621
+ ]
1622
+ },
1623
+ 'procDef': {
1624
+ opcode: 'procedures_definition',
1625
+ argMap: []
1626
+ },
1627
+ 'getParam': {
1628
+ // Doesn't map to single opcode. Import step assigns final correct opcode.
1629
+ opcode: 'argument_reporter_string_number',
1630
+ argMap: [
1631
+ {
1632
+ type: 'field',
1633
+ fieldName: 'VALUE'
1634
+ }
1635
+ ]
1636
+ },
1637
+ 'call': {
1638
+ opcode: 'procedures_call',
1639
+ argMap: []
1640
+ }
1641
+ };
1642
+
1643
+ /**
1644
+ * Add to the specMap entries for an opcode from a Scratch 2.0 extension. Two entries will be made with the same
1645
+ * metadata; this is done to support projects saved by both older and newer versions of the Scratch 2.0 editor.
1646
+ * @param {string} sb2Extension - the Scratch 2.0 name of the extension
1647
+ * @param {string} sb2Opcode - the Scratch 2.0 opcode
1648
+ * @param {SB2SpecMap_blockInfo} blockInfo - the Scratch 3.0 block info
1649
+ */
1650
+ const addExtensionOp = function (sb2Extension, sb2Opcode, blockInfo) {
1651
+ /**
1652
+ * This string separates the name of an extension and the name of an opcode in more recent Scratch 2.0 projects.
1653
+ * Earlier projects used '.' as a separator, up until we added the 'LEGO WeDo 2.0' extension...
1654
+ * @type {string}
1655
+ */
1656
+ const sep = '\u001F'; // Unicode Unit Separator
1657
+
1658
+ // make one entry for projects saved by recent versions of the Scratch 2.0 editor
1659
+ specMap[`${sb2Extension}${sep}${sb2Opcode}`] = blockInfo;
1660
+
1661
+ // make a second for projects saved by older versions of the Scratch 2.0 editor
1662
+ specMap[`${sb2Extension}.${sb2Opcode}`] = blockInfo;
1663
+ };
1664
+
1665
+ const weDo2 = 'LEGO WeDo 2.0';
1666
+
1667
+ addExtensionOp(weDo2, 'motorOnFor', {
1668
+ opcode: 'wedo2_motorOnFor',
1669
+ argMap: [
1670
+ {
1671
+ type: 'input',
1672
+ inputOp: 'wedo2_menu_MOTOR_ID',
1673
+ inputName: 'MOTOR_ID'
1674
+ },
1675
+ {
1676
+ type: 'input',
1677
+ inputOp: 'math_number',
1678
+ inputName: 'DURATION'
1679
+ }
1680
+ ]
1681
+ });
1682
+
1683
+ addExtensionOp(weDo2, 'motorOn', {
1684
+ opcode: 'wedo2_motorOn',
1685
+ argMap: [
1686
+ {
1687
+ type: 'input',
1688
+ inputOp: 'wedo2_menu_MOTOR_ID',
1689
+ inputName: 'MOTOR_ID'
1690
+ }
1691
+ ]
1692
+ });
1693
+
1694
+ addExtensionOp(weDo2, 'motorOff', {
1695
+ opcode: 'wedo2_motorOff',
1696
+ argMap: [
1697
+ {
1698
+ type: 'input',
1699
+ inputOp: 'wedo2_menu_MOTOR_ID',
1700
+ inputName: 'MOTOR_ID'
1701
+ }
1702
+ ]
1703
+ });
1704
+
1705
+ addExtensionOp(weDo2, 'startMotorPower', {
1706
+ opcode: 'wedo2_startMotorPower',
1707
+ argMap: [
1708
+ {
1709
+ type: 'input',
1710
+ inputOp: 'wedo2_menu_MOTOR_ID',
1711
+ inputName: 'MOTOR_ID'
1712
+ },
1713
+ {
1714
+ type: 'input',
1715
+ inputOp: 'math_number',
1716
+ inputName: 'POWER'
1717
+ }
1718
+ ]
1719
+ });
1720
+
1721
+ addExtensionOp(weDo2, 'setMotorDirection', {
1722
+ opcode: 'wedo2_setMotorDirection',
1723
+ argMap: [
1724
+ {
1725
+ type: 'input',
1726
+ inputOp: 'wedo2_menu_MOTOR_ID',
1727
+ inputName: 'MOTOR_ID'
1728
+ },
1729
+ {
1730
+ type: 'input',
1731
+ inputOp: 'wedo2_menu_MOTOR_DIRECTION',
1732
+ inputName: 'MOTOR_DIRECTION'
1733
+ }
1734
+ ]
1735
+ });
1736
+
1737
+ addExtensionOp(weDo2, 'setLED', {
1738
+ opcode: 'wedo2_setLightHue',
1739
+ argMap: [
1740
+ {
1741
+ type: 'input',
1742
+ inputOp: 'math_number',
1743
+ inputName: 'HUE'
1744
+ }
1745
+ ]
1746
+ });
1747
+
1748
+ addExtensionOp(weDo2, 'playNote', {
1749
+ opcode: 'wedo2_playNoteFor',
1750
+ argMap: [
1751
+ {
1752
+ type: 'input',
1753
+ inputOp: 'math_number',
1754
+ inputName: 'NOTE'
1755
+ },
1756
+ {
1757
+ type: 'input',
1758
+ inputOp: 'math_number',
1759
+ inputName: 'DURATION'
1760
+ }
1761
+ ]
1762
+ });
1763
+
1764
+ addExtensionOp(weDo2, 'whenDistance', {
1765
+ opcode: 'wedo2_whenDistance',
1766
+ argMap: [
1767
+ {
1768
+ type: 'input',
1769
+ inputOp: 'wedo2_menu_OP',
1770
+ inputName: 'OP'
1771
+ },
1772
+ {
1773
+ type: 'input',
1774
+ inputOp: 'math_number',
1775
+ inputName: 'REFERENCE'
1776
+ }
1777
+ ]
1778
+ });
1779
+
1780
+ addExtensionOp(weDo2, 'whenTilted', {
1781
+ opcode: 'wedo2_whenTilted',
1782
+ argMap: [
1783
+ {
1784
+ type: 'input',
1785
+ inputOp: 'wedo2_menu_TILT_DIRECTION_ANY',
1786
+ inputName: 'TILT_DIRECTION_ANY'
1787
+ }
1788
+ ]
1789
+ });
1790
+
1791
+ addExtensionOp(weDo2, 'getDistance', {
1792
+ opcode: 'wedo2_getDistance',
1793
+ argMap: []
1794
+ });
1795
+
1796
+ addExtensionOp(weDo2, 'isTilted', {
1797
+ opcode: 'wedo2_isTilted',
1798
+ argMap: [
1799
+ {
1800
+ type: 'input',
1801
+ inputOp: 'wedo2_menu_TILT_DIRECTION_ANY',
1802
+ inputName: 'TILT_DIRECTION_ANY'
1803
+ }
1804
+ ]
1805
+ });
1806
+
1807
+ addExtensionOp(weDo2, 'getTilt', {
1808
+ opcode: 'wedo2_getTiltAngle',
1809
+ argMap: [
1810
+ {
1811
+ type: 'input',
1812
+ inputOp: 'wedo2_menu_TILT_DIRECTION',
1813
+ inputName: 'TILT_DIRECTION'
1814
+ }
1815
+ ]
1816
+ });
1817
+
1818
+ module.exports = specMap;