const categorySeparator = '<sep gap="36"/>'; const blockSeparator = '<sep gap="36"/>'; // At default scale, about 28px const motion = function (isStage, targetId) { return ` <category name="Motion" colour="#4C97FF" secondaryColour="#3373CC"> ${isStage ? ` <label text="Stage selected: no motion blocks"></label> ` : ` <block type="motion_movesteps"> <value name="STEPS"> <shadow type="math_number"> <field name="NUM">10</field> </shadow> </value> </block> <block type="motion_turnright"> <value name="DEGREES"> <shadow type="math_number"> <field name="NUM">15</field> </shadow> </value> </block> <block type="motion_turnleft"> <value name="DEGREES"> <shadow type="math_number"> <field name="NUM">15</field> </shadow> </value> </block> ${blockSeparator} <block type="motion_pointindirection"> <value name="DIRECTION"> <shadow type="math_angle"> <field name="NUM">90</field> </shadow> </value> </block> <block type="motion_pointtowards"> <value name="TOWARDS"> <shadow type="motion_pointtowards_menu"> </shadow> </value> </block> ${blockSeparator} <block type="motion_gotoxy"> <value name="X"> <shadow id="movex" type="math_number"> <field name="NUM">0</field> </shadow> </value> <value name="Y"> <shadow id="movey" type="math_number"> <field name="NUM">0</field> </shadow> </value> </block> <block type="motion_goto"> <value name="TO"> <shadow type="motion_goto_menu"> </shadow> </value> </block> <block type="motion_glidesecstoxy"> <value name="SECS"> <shadow type="math_number"> <field name="NUM">1</field> </shadow> </value> <value name="X"> <shadow id="glidex" type="math_number"> <field name="NUM">0</field> </shadow> </value> <value name="Y"> <shadow id="glidey" type="math_number"> <field name="NUM">0</field> </shadow> </value> </block> <block type="motion_glideto" id="motion_glideto"> <value name="SECS"> <shadow type="math_number"> <field name="NUM">1</field> </shadow> </value> <value name="TO"> <shadow type="motion_glideto_menu"> </shadow> </value> </block> ${blockSeparator} <block type="motion_changexby"> <value name="DX"> <shadow type="math_number"> <field name="NUM">10</field> </shadow> </value> </block> <block type="motion_setx"> <value name="X"> <shadow id="setx" type="math_number"> <field name="NUM">0</field> </shadow> </value> </block> <block type="motion_changeyby"> <value name="DY"> <shadow type="math_number"> <field name="NUM">10</field> </shadow> </value> </block> <block type="motion_sety"> <value name="Y"> <shadow id="sety" type="math_number"> <field name="NUM">0</field> </shadow> </value> </block> ${blockSeparator} <block type="motion_ifonedgebounce"/> ${blockSeparator} <block type="motion_setrotationstyle"/> ${blockSeparator} <block id="${targetId}_xposition" type="motion_xposition"/> <block id="${targetId}_yposition" type="motion_yposition"/> <block id="${targetId}_direction" type="motion_direction"/>`} ${categorySeparator} </category> `; }; const looks = function (isStage, targetId) { return ` <category name="Looks" colour="#9966FF" secondaryColour="#774DCB"> ${isStage ? '' : ` <block type="looks_sayforsecs"> <value name="MESSAGE"> <shadow type="text"> <field name="TEXT">Hello!</field> </shadow> </value> <value name="SECS"> <shadow type="math_number"> <field name="NUM">2</field> </shadow> </value> </block> <block type="looks_say"> <value name="MESSAGE"> <shadow type="text"> <field name="TEXT">Hello!</field> </shadow> </value> </block> <block type="looks_thinkforsecs"> <value name="MESSAGE"> <shadow type="text"> <field name="TEXT">Hmm...</field> </shadow> </value> <value name="SECS"> <shadow type="math_number"> <field name="NUM">2</field> </shadow> </value> </block> <block type="looks_think"> <value name="MESSAGE"> <shadow type="text"> <field name="TEXT">Hmm...</field> </shadow> </value> </block> ${blockSeparator} <block type="looks_show"/> <block type="looks_hide"/> ${blockSeparator} `} ${isStage ? ` <block type="looks_switchbackdropto"> <value name="BACKDROP"> <shadow type="looks_backdrops"/> </value> </block> <block type="looks_switchbackdroptoandwait"> <value name="BACKDROP"> <shadow type="looks_backdrops"/> </value> </block> <block type="looks_nextbackdrop"/> ` : ` <block type="looks_switchcostumeto"> <value name="COSTUME"> <shadow type="looks_costume"/> </value> </block> <block type="looks_nextcostume"/> <block type="looks_switchbackdropto"> <value name="BACKDROP"> <shadow type="looks_backdrops"/> </value> </block> `} ${blockSeparator} <block type="looks_changeeffectby"> <value name="CHANGE"> <shadow type="math_number"> <field name="NUM">10</field> </shadow> </value> </block> <block type="looks_seteffectto"> <value name="VALUE"> <shadow type="math_number"> <field name="NUM">10</field> </shadow> </value> </block> <block type="looks_cleargraphiceffects"/> ${blockSeparator} ${isStage ? '' : ` <block type="looks_changesizeby"> <value name="CHANGE"> <shadow type="math_number"> <field name="NUM">10</field> </shadow> </value> </block> <block type="looks_setsizeto"> <value name="SIZE"> <shadow type="math_number"> <field name="NUM">100</field> </shadow> </value> </block> ${blockSeparator} <block type="looks_gotofront"/> <block type="looks_gobacklayers"> <value name="NUM"> <shadow type="math_integer"> <field name="NUM">1</field> </shadow> </value> </block> ${blockSeparator} `} ${isStage ? ` <block id="backdroporder" type="looks_backdroporder"/> <block id="backdropname" type="looks_backdropname"/> ` : ` <block id="${targetId}_costumeorder" type="looks_costumeorder"/> <block id="backdropname" type="looks_backdropname"/> <block id="${targetId}_size" type="looks_size"/> `} ${categorySeparator} </category> `; }; const sound = function () { return ` <category name="Sound" colour="#D65CD6" secondaryColour="#BD42BD"> <block type="sound_play"> <value name="SOUND_MENU"> <shadow type="sound_sounds_menu"/> </value> </block> <block type="sound_playuntildone"> <value name="SOUND_MENU"> <shadow type="sound_sounds_menu"/> </value> </block> <block type="sound_stopallsounds"/> ${blockSeparator} <block type="sound_changeeffectby"> <value name="VALUE"> <shadow type="math_number"> <field name="NUM">10</field> </shadow> </value> </block> <block type="sound_seteffectto"> <value name="VALUE"> <shadow type="math_number"> <field name="NUM">100</field> </shadow> </value> </block> <block type="sound_cleareffects"/> ${blockSeparator} <block type="sound_changevolumeby"> <value name="VOLUME"> <shadow type="math_number"> <field name="NUM">-10</field> </shadow> </value> </block> <block type="sound_setvolumeto"> <value name="VOLUME"> <shadow type="math_number"> <field name="NUM">100</field> </shadow> </value> </block> <block id="volume" type="sound_volume"/> ${categorySeparator} </category> `; }; const events = function () { return ` <category name="Events" colour="#FFD500" secondaryColour="#CC9900"> <block type="event_whenflagclicked"/> <block type="event_whenkeypressed"> </block> <block type="event_whenthisspriteclicked"/> <block type="event_whenbackdropswitchesto"> </block> ${blockSeparator} <block type="event_whengreaterthan"> <value name="VALUE"> <shadow type="math_number"> <field name="NUM">10</field> </shadow> </value> </block> ${blockSeparator} <block type="event_whenbroadcastreceived"> </block> <block type="event_broadcast"> </block> <block type="event_broadcastandwait"> </block> ${categorySeparator} </category> `; }; const control = function (isStage) { return ` <category name="Control" colour="#FFAB19" secondaryColour="#CF8B17"> <block type="control_wait"> <value name="DURATION"> <shadow type="math_positive_number"> <field name="NUM">1</field> </shadow> </value> </block> ${blockSeparator} <block type="control_repeat"> <value name="TIMES"> <shadow type="math_whole_number"> <field name="NUM">10</field> </shadow> </value> </block> <block id="forever" type="control_forever"/> ${blockSeparator} <block type="control_if"/> <block type="control_if_else"/> <block id="wait_until" type="control_wait_until"/> <block id="repeat_until" type="control_repeat_until"/> ${blockSeparator} <block type="control_stop"/> ${blockSeparator} ${isStage ? ` <block type="control_create_clone_of"> <value name="CLONE_OPTION"> <shadow type="control_create_clone_of_menu"/> </value> </block> ` : ` <block type="control_start_as_clone"/> <block type="control_create_clone_of"> <value name="CLONE_OPTION"> <shadow type="control_create_clone_of_menu"/> </value> </block> <block type="control_delete_this_clone"/> `} ${categorySeparator} </category> `; }; const sensing = function (isStage) { return ` <category name="Sensing" colour="#4CBFE6" secondaryColour="#2E8EB8"> ${isStage ? '' : ` <block type="sensing_touchingobject"> <value name="TOUCHINGOBJECTMENU"> <shadow type="sensing_touchingobjectmenu"/> </value> </block> <block type="sensing_touchingcolor"> <value name="COLOR"> <shadow type="colour_picker"/> </value> </block> <block type="sensing_coloristouchingcolor"> <value name="COLOR"> <shadow type="colour_picker"/> </value> <value name="COLOR2"> <shadow type="colour_picker"/> </value> </block> <block type="sensing_distanceto"> <value name="DISTANCETOMENU"> <shadow type="sensing_distancetomenu"/> </value> </block> ${blockSeparator} `} <block id="askandwait" type="sensing_askandwait"> <value name="QUESTION"> <shadow type="text"> <field name="TEXT">What's your name?</field> </shadow> </value> </block> <block id="answer" type="sensing_answer"/> ${blockSeparator} <block type="sensing_keypressed"> <value name="KEY_OPTION"> <shadow type="sensing_keyoptions"/> </value> </block> <block type="sensing_mousedown"/> <block type="sensing_mousex"/> <block type="sensing_mousey"/> ${blockSeparator} <block id="loudness" type="sensing_loudness"/> ${blockSeparator} <block id="timer" type="sensing_timer"/> <block type="sensing_resettimer"/> ${blockSeparator} <block id="of" type="sensing_of"> <value name="PROPERTY"> <shadow id="sensing_of_property_menu" type="sensing_of_property_menu"/> </value> <value name="OBJECT"> <shadow id="sensing_of_object_menu" type="sensing_of_object_menu"/> </value> </block> ${blockSeparator} <block id="current" type="sensing_current"> <value name="CURRENTMENU"> <shadow id="sensing_currentmenu" type="sensing_currentmenu"/> </value> </block> <block type="sensing_dayssince2000"/> ${categorySeparator} </category> `; }; const operators = function () { return ` <category name="Operators" colour="#40BF4A" secondaryColour="#389438"> <block type="operator_add"> <value name="NUM1"> <shadow type="math_number"> <field name="NUM"/> </shadow> </value> <value name="NUM2"> <shadow type="math_number"> <field name="NUM"/> </shadow> </value> </block> <block type="operator_subtract"> <value name="NUM1"> <shadow type="math_number"> <field name="NUM"/> </shadow> </value> <value name="NUM2"> <shadow type="math_number"> <field name="NUM"/> </shadow> </value> </block> <block type="operator_multiply"> <value name="NUM1"> <shadow type="math_number"> <field name="NUM"/> </shadow> </value> <value name="NUM2"> <shadow type="math_number"> <field name="NUM"/> </shadow> </value> </block> <block type="operator_divide"> <value name="NUM1"> <shadow type="math_number"> <field name="NUM"/> </shadow> </value> <value name="NUM2"> <shadow type="math_number"> <field name="NUM"/> </shadow> </value> </block> ${blockSeparator} <block type="operator_random"> <value name="FROM"> <shadow type="math_number"> <field name="NUM">1</field> </shadow> </value> <value name="TO"> <shadow type="math_number"> <field name="NUM">10</field> </shadow> </value> </block> ${blockSeparator} <block type="operator_lt"> <value name="OPERAND1"> <shadow type="text"> <field name="TEXT"/> </shadow> </value> <value name="OPERAND2"> <shadow type="text"> <field name="TEXT"/> </shadow> </value> </block> <block type="operator_equals"> <value name="OPERAND1"> <shadow type="text"> <field name="TEXT"/> </shadow> </value> <value name="OPERAND2"> <shadow type="text"> <field name="TEXT"/> </shadow> </value> </block> <block type="operator_gt"> <value name="OPERAND1"> <shadow type="text"> <field name="TEXT"/> </shadow> </value> <value name="OPERAND2"> <shadow type="text"> <field name="TEXT"/> </shadow> </value> </block> ${blockSeparator} <block type="operator_and"/> <block type="operator_or"/> <block type="operator_not"/> ${blockSeparator} <block type="operator_join"> <value name="STRING1"> <shadow type="text"> <field name="TEXT">hello</field> </shadow> </value> <value name="STRING2"> <shadow type="text"> <field name="TEXT">world</field> </shadow> </value> </block> <block type="operator_letter_of"> <value name="LETTER"> <shadow type="math_whole_number"> <field name="NUM">1</field> </shadow> </value> <value name="STRING"> <shadow type="text"> <field name="TEXT">world</field> </shadow> </value> </block> <block type="operator_length"> <value name="STRING"> <shadow type="text"> <field name="TEXT">world</field> </shadow> </value> </block> <block type="operator_contains" id="operator_contains"> <value name="STRING1"> <shadow type="text"> <field name="TEXT">hello</field> </shadow> </value> <value name="STRING2"> <shadow type="text"> <field name="TEXT">world</field> </shadow> </value> </block> ${blockSeparator} <block type="operator_mod"> <value name="NUM1"> <shadow type="math_number"> <field name="NUM"/> </shadow> </value> <value name="NUM2"> <shadow type="math_number"> <field name="NUM"/> </shadow> </value> </block> <block type="operator_round"> <value name="NUM"> <shadow type="math_number"> <field name="NUM"/> </shadow> </value> </block> ${blockSeparator} <block type="operator_mathop"> <value name="NUM"> <shadow type="math_number"> <field name="NUM"/> </shadow> </value> </block> ${categorySeparator} </category> `; }; const variables = function () { return ` <category name="Variables" colour="#FF8C1A" secondaryColour="#DB6E00" custom="VARIABLE"> </category> `; }; const myBlocks = function () { return ` <category name="My Blocks" colour="#FF6680" secondaryColour="#FF4D6A" custom="PROCEDURE"> </category> `; }; const xmlOpen = '<xml style="display: none">'; const xmlClose = '</xml>'; /** * @param {!boolean} isStage - Whether the toolbox is for a stage-type target. * @param {?string} targetId - The current editing target * @param {string?} categoriesXML - null for default toolbox, or an XML string with <category> elements. * @returns {string} - a ScratchBlocks-style XML document for the contents of the toolbox. */ const makeToolboxXML = function (isStage, targetId, categoriesXML) { const gap = [categorySeparator]; const everything = [ xmlOpen, motion(isStage, targetId), gap, looks(isStage, targetId), gap, sound(isStage, targetId), gap, events(isStage, targetId), gap, control(isStage, targetId), gap, sensing(isStage, targetId), gap, operators(isStage, targetId), gap, variables(isStage, targetId), gap, myBlocks(isStage, targetId) ]; if (categoriesXML) { everything.push(gap, categoriesXML); } everything.push(xmlClose); return everything.join('\n'); }; export default makeToolboxXML;