playground.html 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>Blockly Playground</title>
  6. <script src="../blockly_uncompressed.js"></script>
  7. <script src="../generators/javascript.js"></script>
  8. <script src="../generators/javascript/logic.js"></script>
  9. <script src="../generators/javascript/loops.js"></script>
  10. <script src="../generators/javascript/math.js"></script>
  11. <script src="../generators/javascript/text.js"></script>
  12. <script src="../generators/javascript/lists.js"></script>
  13. <script src="../generators/javascript/colour.js"></script>
  14. <script src="../generators/javascript/variables.js"></script>
  15. <script src="../generators/javascript/procedures.js"></script>
  16. <script src="../generators/python.js"></script>
  17. <script src="../generators/python/logic.js"></script>
  18. <script src="../generators/python/loops.js"></script>
  19. <script src="../generators/python/math.js"></script>
  20. <script src="../generators/python/text.js"></script>
  21. <script src="../generators/python/lists.js"></script>
  22. <script src="../generators/python/colour.js"></script>
  23. <script src="../generators/python/variables.js"></script>
  24. <script src="../generators/python/procedures.js"></script>
  25. <script src="../generators/php.js"></script>
  26. <script src="../generators/php/logic.js"></script>
  27. <script src="../generators/php/loops.js"></script>
  28. <script src="../generators/php/math.js"></script>
  29. <script src="../generators/php/text.js"></script>
  30. <script src="../generators/php/lists.js"></script>
  31. <script src="../generators/php/colour.js"></script>
  32. <script src="../generators/php/variables.js"></script>
  33. <script src="../generators/php/procedures.js"></script>
  34. <script src="../generators/lua.js"></script>
  35. <script src="../generators/lua/logic.js"></script>
  36. <script src="../generators/lua/loops.js"></script>
  37. <script src="../generators/lua/math.js"></script>
  38. <script src="../generators/lua/text.js"></script>
  39. <script src="../generators/lua/lists.js"></script>
  40. <script src="../generators/lua/colour.js"></script>
  41. <script src="../generators/lua/variables.js"></script>
  42. <script src="../generators/lua/procedures.js"></script>
  43. <script src="../generators/dart.js"></script>
  44. <script src="../generators/dart/logic.js"></script>
  45. <script src="../generators/dart/loops.js"></script>
  46. <script src="../generators/dart/math.js"></script>
  47. <script src="../generators/dart/text.js"></script>
  48. <script src="../generators/dart/lists.js"></script>
  49. <script src="../generators/dart/colour.js"></script>
  50. <script src="../generators/dart/variables.js"></script>
  51. <script src="../generators/dart/procedures.js"></script>
  52. <script src="../msg/messages.js"></script>
  53. <script src="../blocks/logic.js"></script>
  54. <script src="../blocks/loops.js"></script>
  55. <script src="../blocks/math.js"></script>
  56. <script src="../blocks/text.js"></script>
  57. <script src="../blocks/lists.js"></script>
  58. <script src="../blocks/colour.js"></script>
  59. <script src="../blocks/variables.js"></script>
  60. <script src="../blocks/procedures.js"></script>
  61. <script>
  62. 'use strict';
  63. var workspace = null;
  64. var fakeDragStack = [];
  65. function start() {
  66. // Parse the URL arguments.
  67. var match = location.search.match(/dir=([^&]+)/);
  68. var rtl = match && match[1] == 'rtl';
  69. document.forms.options.elements.dir.selectedIndex = Number(rtl);
  70. var toolbox = getToolboxElement();
  71. document.forms.options.elements.toolbox.selectedIndex =
  72. Number(toolbox.getElementsByTagName('category').length == 0);
  73. match = location.search.match(/side=([^&]+)/);
  74. var side = match ? match[1] : 'start';
  75. document.forms.options.elements.side.value = side;
  76. // Create main workspace.
  77. workspace = Blockly.inject('blocklyDiv',
  78. {comments: true,
  79. collapse: true,
  80. disable: true,
  81. grid:
  82. {spacing: 25,
  83. length: 3,
  84. colour: '#ccc',
  85. snap: true},
  86. horizontalLayout: side == 'top' || side == 'bottom',
  87. maxBlocks: Infinity,
  88. media: '../media/',
  89. oneBasedIndex: true,
  90. readOnly: false,
  91. rtl: rtl,
  92. scrollbars: true,
  93. toolbox: toolbox,
  94. toolboxPosition: side == 'top' || side == 'start' ? 'start' : 'end',
  95. zoom:
  96. {controls: true,
  97. wheel: true,
  98. startScale: 1.0,
  99. maxScale: 4,
  100. minScale: .25,
  101. scaleSpeed: 1.1}
  102. });
  103. // Restore previously displayed text.
  104. if (sessionStorage) {
  105. var text = sessionStorage.getItem('textarea');
  106. if (text) {
  107. document.getElementById('importExport').value = text;
  108. }
  109. // Restore event logging state.
  110. var state = sessionStorage.getItem('logEvents');
  111. logEvents(Boolean(Number(state)));
  112. } else {
  113. // MSIE 11 does not support sessionStorage on file:// URLs.
  114. logEvents(false);
  115. }
  116. taChange();
  117. }
  118. function getToolboxElement() {
  119. var match = location.search.match(/toolbox=([^&]+)/);
  120. return document.getElementById('toolbox-' + (match ? match[1] : 'categories'));
  121. }
  122. function toXml() {
  123. var output = document.getElementById('importExport');
  124. var xml = Blockly.Xml.workspaceToDom(workspace);
  125. output.value = Blockly.Xml.domToPrettyText(xml);
  126. output.focus();
  127. output.select();
  128. taChange();
  129. }
  130. function fromXml() {
  131. var input = document.getElementById('importExport');
  132. var xml = Blockly.Xml.textToDom(input.value);
  133. Blockly.Xml.domToWorkspace(xml, workspace);
  134. taChange();
  135. }
  136. function toCode(lang) {
  137. var output = document.getElementById('importExport');
  138. output.value = Blockly[lang].workspaceToCode(workspace);
  139. taChange();
  140. }
  141. // Disable the "Import from XML" button if the XML is invalid.
  142. // Preserve text between page reloads.
  143. function taChange() {
  144. var textarea = document.getElementById('importExport');
  145. if (sessionStorage) {
  146. sessionStorage.setItem('textarea', textarea.value);
  147. }
  148. var valid = true;
  149. try {
  150. Blockly.Xml.textToDom(textarea.value);
  151. } catch (e) {
  152. valid = false;
  153. }
  154. document.getElementById('import').disabled = !valid;
  155. }
  156. function logEvents(state) {
  157. var checkbox = document.getElementById('logCheck');
  158. checkbox.checked = state;
  159. if (sessionStorage) {
  160. sessionStorage.setItem('logEvents', Number(state));
  161. }
  162. if (state) {
  163. workspace.addChangeListener(logger);
  164. } else {
  165. workspace.removeChangeListener(logger);
  166. }
  167. }
  168. function logger(e) {
  169. console.log(e);
  170. }
  171. function airstrike(n) {
  172. var prototypes = [];
  173. var toolbox = getToolboxElement();
  174. var blocks = toolbox.getElementsByTagName('block');
  175. for (var i = 0, block; block = blocks[i]; i++) {
  176. prototypes.push(block.getAttribute('type'));
  177. }
  178. for (var i = 0; i < n; i++) {
  179. var prototype = prototypes[Math.floor(Math.random() * prototypes.length)];
  180. var block = workspace.newBlock(prototype);
  181. block.initSvg();
  182. block.getSvgRoot().setAttribute('transform', 'translate(' +
  183. Math.round(Math.random() * 450 + 40) + ', ' +
  184. Math.round(Math.random() * 600 + 40) + ')');
  185. block.render();
  186. }
  187. }
  188. function fakeDrag(id, dx, dy, opt_workspace) {
  189. var ws = opt_workspace || Blockly.getMainWorkspace();
  190. var blockToDrag = ws.getBlockById(id);
  191. if (!blockToDrag) {
  192. fakeDragWrapper();
  193. return;
  194. }
  195. var blockTop = blockToDrag.svgGroup_.getBoundingClientRect().top;
  196. var blockLeft = blockToDrag.svgGroup_.getBoundingClientRect().left;
  197. // Click somewhere on the block.
  198. var mouseDownEvent = new MouseEvent('mousedown',
  199. {clientX: blockLeft + 5, clientY: blockTop + 5});
  200. blockToDrag.onMouseDown_(mouseDownEvent);
  201. // Throw in a move for good measure.
  202. setTimeout(
  203. function() {
  204. var mouseMoveEvent = new MouseEvent('mousemove',
  205. {clientX: blockLeft + dx,
  206. clientY: blockTop + dy});
  207. blockToDrag.onMouseMove_(mouseMoveEvent);
  208. // Drop at dx, dy.
  209. setTimeout(
  210. function() {
  211. var mouseUpEvent = new MouseEvent('mouseup',
  212. {clientX: blockLeft + dx,
  213. clientY: blockTop + dy});
  214. blockToDrag.onMouseUp_(mouseUpEvent);
  215. setTimeout(fakeDragWrapper(), 100);
  216. }, 30);
  217. }, 30);
  218. };
  219. function fakeDragWrapper() {
  220. var dragInfo = fakeDragStack.pop();
  221. if (dragInfo) {
  222. fakeDrag(dragInfo.id, dragInfo.dx, dragInfo.dy, dragInfo.workspace);
  223. }
  224. }
  225. function fakeManyDrags() {
  226. var blockList = workspace.getAllBlocks();
  227. for (var i = 0; i < 2 * blockList.length; i++) {
  228. fakeDragStack.push(
  229. {
  230. id: blockList[Math.round(Math.random() * (blockList.length - 1))].id,
  231. // Move some blocks up and to the left, but mostly down and to the right.
  232. dx: Math.round((Math.random() - 0.25) * 200),
  233. dy: Math.round((Math.random() - 0.25) * 200),
  234. workspace: workspace
  235. });
  236. }
  237. fakeDragWrapper();
  238. }
  239. function spaghetti(n) {
  240. var xml = spaghettiXml;
  241. for(var i = 0; i < n; i++) {
  242. xml = xml.replace(/(<(statement|next)( name="DO0")?>)<\//g,
  243. '$1' + spaghettiXml + '</');
  244. }
  245. xml = '<xml xmlns="http://www.w3.org/1999/xhtml">' + xml + '</xml>';
  246. var dom = Blockly.Xml.textToDom(xml);
  247. console.time('Spaghetti domToWorkspace');
  248. Blockly.Xml.domToWorkspace(dom, workspace);
  249. console.timeEnd('Spaghetti domToWorkspace');
  250. }
  251. var spaghettiXml = [
  252. ' <block type="controls_if">',
  253. ' <value name="IF0">',
  254. ' <block type="logic_compare">',
  255. ' <field name="OP">EQ</field>',
  256. ' <value name="A">',
  257. ' <block type="math_arithmetic">',
  258. ' <field name="OP">MULTIPLY</field>',
  259. ' <value name="A">',
  260. ' <block type="math_number">',
  261. ' <field name="NUM">6</field>',
  262. ' </block>',
  263. ' </value>',
  264. ' <value name="B">',
  265. ' <block type="math_number">',
  266. ' <field name="NUM">7</field>',
  267. ' </block>',
  268. ' </value>',
  269. ' </block>',
  270. ' </value>',
  271. ' <value name="B">',
  272. ' <block type="math_number">',
  273. ' <field name="NUM">42</field>',
  274. ' </block>',
  275. ' </value>',
  276. ' </block>',
  277. ' </value>',
  278. ' <statement name="DO0"></statement>',
  279. ' <next></next>',
  280. ' </block>'].join('\n');
  281. </script>
  282. <style>
  283. html, body {
  284. height: 100%;
  285. }
  286. body {
  287. background-color: #fff;
  288. font-family: sans-serif;
  289. overflow: hidden;
  290. }
  291. h1 {
  292. font-weight: normal;
  293. font-size: 140%;
  294. }
  295. #blocklyDiv {
  296. float: right;
  297. height: 95%;
  298. width: 70%;
  299. }
  300. #importExport {
  301. font-family: monospace;
  302. }
  303. </style>
  304. </head>
  305. <body onload="start()">
  306. <div id="blocklyDiv"></div>
  307. <h1>Blockly Playground</h1>
  308. <p><a href="javascript:void(workspace.setVisible(true))">Show</a>
  309. - <a href="javascript:void(workspace.setVisible(false))">Hide</a></p>
  310. <form id="options">
  311. <select name="dir" onchange="document.forms.options.submit()">
  312. <option value="ltr">LTR</option>
  313. <option value="rtl">RTL</option>
  314. </select>
  315. <select name="toolbox" onchange="document.forms.options.submit()">
  316. <option value="categories">Categories</option>
  317. <option value="simple">Simple</option>
  318. </select>
  319. <select name="side" onchange="document.forms.options.submit()">
  320. <option value="start">Start</option>
  321. <option value="end">End</option>
  322. <option value="top">Top</option>
  323. <option value="bottom">Bottom</option>
  324. </select>
  325. </form>
  326. <p>
  327. <input type="button" value="Export to XML" onclick="toXml()">
  328. &nbsp;
  329. <input type="button" value="Import from XML" onclick="fromXml()" id="import">
  330. <br>
  331. <input type="button" value="To JavaScript" onclick="toCode('JavaScript')">
  332. &nbsp;
  333. <input type="button" value="To Python" onclick="toCode('Python')">
  334. &nbsp;
  335. <input type="button" value="To PHP" onclick="toCode('PHP')">
  336. &nbsp;
  337. <input type="button" value="To Lua" onclick="toCode('Lua')">
  338. &nbsp;
  339. <input type="button" value="To Dart" onclick="toCode('Dart')">
  340. <br>
  341. <textarea id="importExport" style="width: 26%; height: 12em"
  342. onchange="taChange();" onkeyup="taChange()"></textarea>
  343. </p>
  344. <p>
  345. Stress test: &nbsp;
  346. <input type="button" value="Airstrike!" onclick="airstrike(100)">
  347. <input type="button" value="Spaghetti!" onclick="spaghetti(8)">
  348. <input type="button" value="Fake some drags!" onclick="fakeManyDrags()">
  349. </p>
  350. <p>
  351. Log events: &nbsp;
  352. <input type="checkbox" onclick="logEvents(this.checked)" id="logCheck">
  353. </p>
  354. <xml id="toolbox-simple" style="display: none">
  355. <block type="controls_if"></block>
  356. <block type="logic_compare"></block>
  357. <!-- <block type="control_repeat"></block> -->
  358. <block type="logic_operation"></block>
  359. <block type="controls_repeat_ext">
  360. <value name="TIMES">
  361. <shadow type="math_number">
  362. <field name="NUM">10</field>
  363. </shadow>
  364. </value>
  365. </block>
  366. <block type="logic_operation"></block>
  367. <block type="logic_negate"></block>
  368. <block type="logic_boolean"></block>
  369. <block type="logic_null" disabled="true"></block>
  370. <block type="logic_ternary"></block>
  371. </xml>
  372. <xml id="toolbox-categories" style="display: none">
  373. <category name="Logic" colour="210">
  374. <block type="controls_if"></block>
  375. <block type="logic_compare"></block>
  376. <block type="logic_operation"></block>
  377. <block type="logic_negate"></block>
  378. <block type="logic_boolean"></block>
  379. <block type="logic_null" disabled="true"></block>
  380. <block type="logic_ternary"></block>
  381. </category>
  382. <category name="Loops" colour="120">
  383. <block type="controls_repeat_ext">
  384. <value name="TIMES">
  385. <shadow type="math_number">
  386. <field name="NUM">10</field>
  387. </shadow>
  388. </value>
  389. </block>
  390. <block type="controls_repeat" disabled="true"></block>
  391. <block type="controls_whileUntil"></block>
  392. <block type="controls_for">
  393. <value name="FROM">
  394. <shadow type="math_number">
  395. <field name="NUM">1</field>
  396. </shadow>
  397. </value>
  398. <value name="TO">
  399. <shadow type="math_number">
  400. <field name="NUM">10</field>
  401. </shadow>
  402. </value>
  403. <value name="BY">
  404. <shadow type="math_number">
  405. <field name="NUM">1</field>
  406. </shadow>
  407. </value>
  408. </block>
  409. <block type="controls_forEach"></block>
  410. <block type="controls_flow_statements"></block>
  411. </category>
  412. <category name="Math" colour="230">
  413. <block type="math_number" gap="32"></block>
  414. <block type="math_arithmetic">
  415. <value name="A">
  416. <shadow type="math_number">
  417. <field name="NUM">1</field>
  418. </shadow>
  419. </value>
  420. <value name="B">
  421. <shadow type="math_number">
  422. <field name="NUM">1</field>
  423. </shadow>
  424. </value>
  425. </block>
  426. <block type="math_single">
  427. <value name="NUM">
  428. <shadow type="math_number">
  429. <field name="NUM">9</field>
  430. </shadow>
  431. </value>
  432. </block>
  433. <block type="math_trig">
  434. <value name="NUM">
  435. <shadow type="math_number">
  436. <field name="NUM">45</field>
  437. </shadow>
  438. </value>
  439. </block>
  440. <block type="math_constant"></block>
  441. <block type="math_number_property">
  442. <value name="NUMBER_TO_CHECK">
  443. <shadow type="math_number">
  444. <field name="NUM">0</field>
  445. </shadow>
  446. </value>
  447. </block>
  448. <block type="math_round">
  449. <value name="NUM">
  450. <shadow type="math_number">
  451. <field name="NUM">3.1</field>
  452. </shadow>
  453. </value>
  454. </block>
  455. <block type="math_on_list"></block>
  456. <block type="math_modulo">
  457. <value name="DIVIDEND">
  458. <shadow type="math_number">
  459. <field name="NUM">64</field>
  460. </shadow>
  461. </value>
  462. <value name="DIVISOR">
  463. <shadow type="math_number">
  464. <field name="NUM">10</field>
  465. </shadow>
  466. </value>
  467. </block>
  468. <block type="math_constrain">
  469. <value name="VALUE">
  470. <shadow type="math_number">
  471. <field name="NUM">50</field>
  472. </shadow>
  473. </value>
  474. <value name="LOW">
  475. <shadow type="math_number">
  476. <field name="NUM">1</field>
  477. </shadow>
  478. </value>
  479. <value name="HIGH">
  480. <shadow type="math_number">
  481. <field name="NUM">100</field>
  482. </shadow>
  483. </value>
  484. </block>
  485. <block type="math_random_int">
  486. <value name="FROM">
  487. <shadow type="math_number">
  488. <field name="NUM">1</field>
  489. </shadow>
  490. </value>
  491. <value name="TO">
  492. <shadow type="math_number">
  493. <field name="NUM">100</field>
  494. </shadow>
  495. </value>
  496. </block>
  497. <block type="math_random_float"></block>
  498. </category>
  499. <category name="Text" colour="160">
  500. <block type="text"></block>
  501. <block type="text_join"></block>
  502. <block type="text_append">
  503. <value name="TEXT">
  504. <shadow type="text"></shadow>
  505. </value>
  506. </block>
  507. <block type="text_length">
  508. <value name="VALUE">
  509. <shadow type="text">
  510. <field name="TEXT">abc</field>
  511. </shadow>
  512. </value>
  513. </block>
  514. <block type="text_isEmpty">
  515. <value name="VALUE">
  516. <shadow type="text">
  517. <field name="TEXT"></field>
  518. </shadow>
  519. </value>
  520. </block>
  521. <block type="text_indexOf">
  522. <value name="VALUE">
  523. <block type="variables_get">
  524. <field name="VAR">text</field>
  525. </block>
  526. </value>
  527. <value name="FIND">
  528. <shadow type="text">
  529. <field name="TEXT">abc</field>
  530. </shadow>
  531. </value>
  532. </block>
  533. <block type="text_charAt">
  534. <value name="VALUE">
  535. <block type="variables_get">
  536. <field name="VAR">text</field>
  537. </block>
  538. </value>
  539. </block>
  540. <block type="text_getSubstring">
  541. <value name="STRING">
  542. <block type="variables_get">
  543. <field name="VAR">text</field>
  544. </block>
  545. </value>
  546. </block>
  547. <block type="text_changeCase">
  548. <value name="TEXT">
  549. <shadow type="text">
  550. <field name="TEXT">abc</field>
  551. </shadow>
  552. </value>
  553. </block>
  554. <block type="text_trim">
  555. <value name="TEXT">
  556. <shadow type="text">
  557. <field name="TEXT">abc</field>
  558. </shadow>
  559. </value>
  560. </block>
  561. <block type="text_print">
  562. <value name="TEXT">
  563. <shadow type="text">
  564. <field name="TEXT">abc</field>
  565. </shadow>
  566. </value>
  567. </block>
  568. <block type="text_prompt_ext">
  569. <value name="TEXT">
  570. <shadow type="text">
  571. <field name="TEXT">abc</field>
  572. </shadow>
  573. </value>
  574. </block>
  575. </category>
  576. <category name="Lists" colour="260">
  577. <block type="lists_create_with">
  578. <mutation items="0"></mutation>
  579. </block>
  580. <block type="lists_create_with"></block>
  581. <block type="lists_repeat">
  582. <value name="NUM">
  583. <shadow type="math_number">
  584. <field name="NUM">5</field>
  585. </shadow>
  586. </value>
  587. </block>
  588. <block type="lists_length"></block>
  589. <block type="lists_isEmpty"></block>
  590. <block type="lists_indexOf">
  591. <value name="VALUE">
  592. <block type="variables_get">
  593. <field name="VAR">list</field>
  594. </block>
  595. </value>
  596. </block>
  597. <block type="lists_getIndex">
  598. <value name="VALUE">
  599. <block type="variables_get">
  600. <field name="VAR">list</field>
  601. </block>
  602. </value>
  603. </block>
  604. <block type="lists_setIndex">
  605. <value name="LIST">
  606. <block type="variables_get">
  607. <field name="VAR">list</field>
  608. </block>
  609. </value>
  610. </block>
  611. <block type="lists_getSublist">
  612. <value name="LIST">
  613. <block type="variables_get">
  614. <field name="VAR">list</field>
  615. </block>
  616. </value>
  617. </block>
  618. <block type="lists_split">
  619. <value name="DELIM">
  620. <shadow type="text">
  621. <field name="TEXT">,</field>
  622. </shadow>
  623. </value>
  624. </block>
  625. <block type="lists_sort"></block>
  626. </category>
  627. <category name="Colour" colour="20">
  628. <block type="colour_picker"></block>
  629. <block type="colour_random"></block>
  630. <block type="colour_rgb">
  631. <value name="RED">
  632. <shadow type="math_number">
  633. <field name="NUM">100</field>
  634. </shadow>
  635. </value>
  636. <value name="GREEN">
  637. <shadow type="math_number">
  638. <field name="NUM">50</field>
  639. </shadow>
  640. </value>
  641. <value name="BLUE">
  642. <shadow type="math_number">
  643. <field name="NUM">0</field>
  644. </shadow>
  645. </value>
  646. </block>
  647. <block type="colour_blend">
  648. <value name="COLOUR1">
  649. <shadow type="colour_picker">
  650. <field name="COLOUR">#ff0000</field>
  651. </shadow>
  652. </value>
  653. <value name="COLOUR2">
  654. <shadow type="colour_picker">
  655. <field name="COLOUR">#3333ff</field>
  656. </shadow>
  657. </value>
  658. <value name="RATIO">
  659. <shadow type="math_number">
  660. <field name="NUM">0.5</field>
  661. </shadow>
  662. </value>
  663. </block>
  664. </category>
  665. <sep></sep>
  666. <category name="Variables" colour="330" custom="VARIABLE"></category>
  667. <category name="Functions" colour="290" custom="PROCEDURE"></category>
  668. </xml>
  669. </body>
  670. </html>