@@ -27,9 +27,14 @@ import { ExtendedPythonGenerator } from '../editor/extended_python_generator';
2727import { createStepFieldFlydown } from '../fields/field_flydown' ;
2828import { BLOCK_NAME as MRC_JUMP_TO_STEP } from './mrc_jump_to_step' ;
2929import * as stepContainer from './mrc_step_container'
30+ import * as value from './utils/value' ;
31+ import * as toolboxItems from '../toolbox/items' ;
3032
3133export const BLOCK_NAME = 'mrc_steps' ;
3234
35+ const INPUT_CONDITION_PREFIX = 'CONDITION_' ;
36+ const INPUT_STEP_PREFIX = 'STEP_' ;
37+
3338/** Extra state for serialising mrc_steps blocks. */
3439type StepsExtraState = {
3540 /**
@@ -49,7 +54,7 @@ const STEPS = {
4954 * Block initialization.
5055 */
5156 init : function ( this : StepsBlock ) : void {
52- this . mrcStepNames = [ "0" ] ;
57+ this . mrcStepNames = [ ] ;
5358 this . appendDummyInput ( )
5459 . appendField ( Blockly . Msg . STEPS ) ;
5560 this . setInputsInline ( false ) ;
@@ -63,10 +68,8 @@ const STEPS = {
6368 } ;
6469 } ,
6570 loadExtraState : function ( this : StepsBlock , state : StepsExtraState ) : void {
66- if ( state && state . stepNames ) {
67- this . mrcStepNames = state . stepNames ;
68- this . updateShape_ ( ) ;
69- }
71+ this . mrcStepNames = state . stepNames ;
72+ this . updateShape_ ( ) ;
7073 } ,
7174 compose : function ( this : StepsBlock , containerBlock : Blockly . Block ) {
7275 if ( containerBlock . type !== stepContainer . STEP_CONTAINER_BLOCK_NAME ) {
@@ -96,6 +99,21 @@ const STEPS = {
9699 } ) ;
97100
98101 this . updateShape_ ( ) ;
102+
103+ // Add a shadow True block to each empty condition input.
104+ for ( var i = 0 ; i < this . mrcStepNames . length ; i ++ ) {
105+ const conditionInput = this . getInput ( INPUT_CONDITION_PREFIX + i ) ;
106+ if ( conditionInput && ! conditionInput . connection ?. targetConnection ) {
107+ const shadowBlock = this . workspace . newBlock ( 'logic_boolean' ) as Blockly . BlockSvg ;
108+ shadowBlock . setShadow ( true ) ;
109+ shadowBlock . setFieldValue ( 'TRUE' , 'BOOL' ) ;
110+ if ( this . workspace . rendered ) {
111+ shadowBlock . initSvg ( ) ;
112+ shadowBlock . render ( ) ;
113+ }
114+ conditionInput . connection ?. connect ( shadowBlock . outputConnection ! ) ;
115+ }
116+ }
99117 } ,
100118 decompose : function ( this : StepsBlock , workspace : Blockly . Workspace ) {
101119 const stepNames : string [ ] = [ ] ;
@@ -151,8 +169,8 @@ const STEPS = {
151169 // Build a map of step names to their current input indices
152170 const currentStepMap : { [ stepName : string ] : number } = { } ;
153171 let i = 0 ;
154- while ( this . getInput ( 'CONDITION_' + i ) ) {
155- const conditionInput = this . getInput ( 'CONDITION_' + i ) ;
172+ while ( this . getInput ( INPUT_CONDITION_PREFIX + i ) ) {
173+ const conditionInput = this . getInput ( INPUT_CONDITION_PREFIX + i ) ;
156174 const field = conditionInput ?. fieldRow [ 0 ] ;
157175 if ( field ) {
158176 currentStepMap [ field . getValue ( ) ] = i ;
@@ -167,39 +185,43 @@ const STEPS = {
167185
168186 if ( currentIndex !== undefined && currentIndex !== j ) {
169187 // Step exists but is at wrong position - move it
170- const conditionConnection = this . getInput ( 'CONDITION_' + currentIndex ) ?. connection ?. targetConnection ;
171- const stepConnection = this . getInput ( 'STEP_' + currentIndex ) ?. connection ?. targetConnection ;
188+ const conditionConnection = this . getInput ( INPUT_CONDITION_PREFIX + currentIndex ) ?. connection ?. targetConnection ;
189+ const stepConnection = this . getInput ( INPUT_STEP_PREFIX + currentIndex ) ?. connection ?. targetConnection ;
172190
173191 // Temporarily disconnect
174- if ( conditionConnection ) conditionConnection . disconnect ( ) ;
175- if ( stepConnection ) stepConnection . disconnect ( ) ;
192+ if ( conditionConnection ) {
193+ conditionConnection . disconnect ( ) ;
194+ }
195+ if ( stepConnection ) {
196+ stepConnection . disconnect ( ) ;
197+ }
176198
177199 // Remove old inputs
178- this . removeInput ( 'CONDITION_' + currentIndex , false ) ;
179- this . removeInput ( 'STEP_' + currentIndex , false ) ;
200+ this . removeInput ( INPUT_CONDITION_PREFIX + currentIndex , false ) ;
201+ this . removeInput ( INPUT_STEP_PREFIX + currentIndex , false ) ;
180202
181203 // Create new inputs at correct position
182204 const fieldFlydown = createStepFieldFlydown ( stepName , true ) ;
183205 fieldFlydown . setValidator ( this . mrcUpdateStepName . bind ( this , j ) ) ;
184206
185- this . appendValueInput ( 'CONDITION_' + j )
207+ this . appendValueInput ( INPUT_CONDITION_PREFIX + j )
186208 . appendField ( fieldFlydown )
187209 . setCheck ( 'Boolean' )
188210 . appendField ( Blockly . Msg . REPEAT_UNTIL ) ;
189- this . appendStatementInput ( 'STEP_' + j ) ;
211+ this . appendStatementInput ( INPUT_STEP_PREFIX + j ) ;
190212
191213 // Reconnect
192214 if ( conditionConnection ) {
193- this . getInput ( 'CONDITION_' + j ) ?. connection ?. connect ( conditionConnection ) ;
215+ this . getInput ( INPUT_CONDITION_PREFIX + j ) ?. connection ?. connect ( conditionConnection ) ;
194216 }
195217 if ( stepConnection ) {
196- this . getInput ( 'STEP_' + j ) ?. connection ?. connect ( stepConnection ) ;
218+ this . getInput ( INPUT_STEP_PREFIX + j ) ?. connection ?. connect ( stepConnection ) ;
197219 }
198220
199221 delete currentStepMap [ stepName ] ;
200222 } else if ( currentIndex !== undefined ) {
201223 // Step is at correct position - just update the field
202- const conditionInput = this . getInput ( 'CONDITION_' + j ) ;
224+ const conditionInput = this . getInput ( INPUT_CONDITION_PREFIX + j ) ;
203225 const field = conditionInput ?. fieldRow [ 0 ] ;
204226 if ( field && field . getValue ( ) !== stepName ) {
205227 field . setValue ( stepName ) ;
@@ -210,31 +232,19 @@ const STEPS = {
210232 const fieldFlydown = createStepFieldFlydown ( stepName , true ) ;
211233 fieldFlydown . setValidator ( this . mrcUpdateStepName . bind ( this , j ) ) ;
212234
213- const conditionInput = this . appendValueInput ( 'CONDITION_' + j )
235+ this . appendValueInput ( INPUT_CONDITION_PREFIX + j )
214236 . appendField ( fieldFlydown )
215237 . setCheck ( 'Boolean' )
216238 . appendField ( Blockly . Msg . REPEAT_UNTIL ) ;
217- this . appendStatementInput ( 'STEP_' + j ) ;
218-
219- // Add shadow True block to the new condition input
220- if ( this . workspace ) {
221- const shadowBlock = this . workspace . newBlock ( 'logic_boolean' ) as Blockly . BlockSvg ;
222- shadowBlock . setShadow ( true ) ;
223- shadowBlock . setFieldValue ( 'TRUE' , 'BOOL' ) ;
224- if ( this . workspace . rendered ) {
225- shadowBlock . initSvg ( ) ;
226- shadowBlock . render ( ) ;
227- }
228- conditionInput . connection ?. connect ( shadowBlock . outputConnection ! ) ;
229- }
239+ this . appendStatementInput ( INPUT_STEP_PREFIX + j ) ;
230240 }
231241 }
232242
233243 // Remove any leftover inputs (steps that were deleted)
234244 for ( const stepName in currentStepMap ) {
235245 const index = currentStepMap [ stepName ] ;
236- this . removeInput ( 'CONDITION_' + index , false ) ;
237- this . removeInput ( 'STEP_' + index , false ) ;
246+ this . removeInput ( INPUT_CONDITION_PREFIX + index , false ) ;
247+ this . removeInput ( INPUT_STEP_PREFIX + index , false ) ;
238248 }
239249 } ,
240250 mrcGetStepNames : function ( this : StepsBlock ) : string [ ] {
@@ -256,7 +266,7 @@ export const pythonFromBlock = function (
256266 generator : ExtendedPythonGenerator ,
257267) {
258268 let code = 'def steps(self):\n' ;
259- code += generator . INDENT + 'if not self. _initialized_steps:\n' ;
269+ code += generator . INDENT + 'if not hasattr( self, " _initialized_steps") :\n' ;
260270 code += generator . INDENT . repeat ( 2 ) + 'self._current_step = "' + block . mrcStepNames [ 0 ] + '"\n' ;
261271 code += generator . INDENT . repeat ( 2 ) + 'self._initialized_steps = True\n\n' ;
262272 code += generator . INDENT + 'if self._current_step == None:\n' ;
@@ -266,11 +276,11 @@ export const pythonFromBlock = function (
266276 code += generator . INDENT + 'match self._current_step:\n' ;
267277 block . mrcStepNames . forEach ( ( stepName , index ) => {
268278 code += generator . INDENT . repeat ( 2 ) + `case "${ stepName } ":\n` ;
269- let stepCode = generator . statementToCode ( block , 'STEP_' + index ) ;
279+ let stepCode = generator . statementToCode ( block , INPUT_STEP_PREFIX + index ) ;
270280 if ( stepCode !== '' ) {
271281 code += generator . prefixLines ( stepCode , generator . INDENT . repeat ( 2 ) ) ;
272282 }
273- let conditionCode = generator . valueToCode ( block , 'CONDITION_' + index , Order . NONE ) || 'False' ;
283+ let conditionCode = generator . valueToCode ( block , INPUT_CONDITION_PREFIX + index , Order . NONE ) || 'False' ;
274284 code += generator . INDENT . repeat ( 3 ) + 'if ' + conditionCode + ':\n' ;
275285 if ( index === block . mrcStepNames . length - 1 ) {
276286 code += generator . INDENT . repeat ( 4 ) + 'self._current_step = None\n' ;
@@ -282,4 +292,14 @@ export const pythonFromBlock = function (
282292 generator . addClassMethodDefinition ( 'steps' , code ) ;
283293
284294 return ''
285- }
295+ }
296+
297+ export function createStepsBlock ( ) : toolboxItems . Block {
298+ const extraState : StepsExtraState = {
299+ stepNames : [ '0' ] ,
300+ } ;
301+ const fields : { [ key : string ] : any } = { } ;
302+ const inputs : { [ key : string ] : any } = { } ;
303+ inputs [ INPUT_CONDITION_PREFIX + 0 ] = value . createBooleanShadowValue ( true ) ;
304+ return new toolboxItems . Block ( BLOCK_NAME , extraState , fields , inputs ) ;
305+ }
0 commit comments