Blockly 11.1
Goals:
Create a basic single-input block that's auto connected to a shadow
block that can take any type of input including a default blockly variable
Using the built-in variables category
<category name="Variables" colour="#a55b80"
css-icon="customIcon_cat_variables" css-row="cat_row"
css-label="cat_label" expanded="false" custom="VARIABLE">
</category>
And using my handy-dandy helper
Blockly.Custom.appendShadowBlock = function(block_svg, input_name,
block_name, defaultValue) {
let shadowBlock = block_svg.workspace.newBlock(block_name);
shadowBlock.setShadow(true);
shadowBlock.initSvg();
shadowBlock.render();
// Note: If we support other types of shadow blocks in the future,
we'll need to monkey this up to support defaults
shadowBlock.getField("NUM")?.setValue(defaultValue); // A shadow
block is typically either
shadowBlock.getField("TEXT")?.setValue(defaultValue); // a number
input or a text input
var input = block_svg.getInput(input_name);
if (!input) {
alert('Blockly.Custom.appendShadowBlock: Input not found: ' +
input_name + ', In block:' + block_name);
return;
}
let cc = input.connection;
cc.connect(shadowBlock.outputConnection);
};
And my handy-dandy shadow-block builder-helper (I'm really surprised
something like this doesn't already exist in the API... seems like
everyone asks for it according to google)
Blockly.Custom.DefineBlock = function ( opts ) {
Blockly.Blocks[opts.type] = {
init: function() {
this.jsonInit(opts);
var self = this; // The block we just defined
if (opts.args0) {
opts.args0.forEach((arg) => {
if (arg.shadow) {
// (block, block_name, shadowblock_type,
shadowblock_default_value
Blockly.Custom.appendShadowBlock(self,
arg.name,
arg.shadow, arg.value);
}
});
}
}
};
};
Blockly.Custom.DefineBlock({
"type" : "function_convert_to_number",
"message0" : "Convert %1 to Number",
"colour" : 330,
"tooltip" : "",
"helpUrl" : "",
"args0" : [{
"type" : "input_value",
"name" : "VALUE",
"text" : "",
"shadow" : "text",
"check" : "String"
}],
output : "Number"
});
The above works perfectly fine for connecting a "String" type. But I'm
unable to connect a blockly default variable created in 'Variables',
because from what I can tell the output type is null, which doesn't
match up with "String".
So... if I change check: to null... or get rid of check: alltogether,
then I get this:
blockly_compressed.js:971 Uncaught Error: Could not connect shadow block
to connection
at
RenderedConnection$$module$build$src$core$rendered_connection.createShadowBlock
(blockly_compressed.js:971:227)
at
RenderedConnection$$module$build$src$core$rendered_connection.respawnShadow_
(blockly_compressed.js:965:297)
at
RenderedConnection$$module$build$src$core$rendered_connection.respawnShadow_
(blockly_compressed.js:1209:147)
at
RenderedConnection$$module$build$src$core$rendered_connection.setShadowStateInternal
(blockly_compressed.js:970:79)
at
RenderedConnection$$module$build$src$core$rendered_connection.setShadowDom
(blockly_compressed.js:966:551)
at applyInputTagNodes$$module$build$src$core$xml
(blockly_compressed.js:306:3)
at domToBlockHeadless$$module$build$src$core$xml
(blockly_compressed.js:308:325)
at applyInputTagNodes$$module$build$src$core$xml
(blockly_compressed.js:305:374)
at domToBlockHeadless$$module$build$src$core$xml
(blockly_compressed.js:308:325)
at applyInputTagNodes$$module$build$src$core$xml
(blockly_compressed.js:305:374)
And then you wind up with a 'stuck' block in the canvas, that when you
click on it does this:
blockly_compressed.js:737 Uncaught TypeError: Cannot read properties of
null (reading 'isShadow')
at Gesture$$module$build$src$core$gesture.setTargetBlock
(blockly_compressed.js:737:402)
at Gesture$$module$build$src$core$gesture.setTargetBlock
(blockly_compressed.js:737:418)
at Gesture$$module$build$src$core$gesture.setStartBlock
(blockly_compressed.js:737:363)
at Gesture$$module$build$src$core$gesture.handleBlockStart
(blockly_compressed.js:733:132)
at BlockSvg$$module$build$src$core$block_svg.onMouseDown_
(blockly_compressed.js:1236:466)
at SVGGElement.f (blockly_compressed.js:87:149)
Which looks like it's this bug:
https://github.com/google/blockly/issues/4847
Also...
If I set 'check' to null, why should I get a connection error? One
would think that if you're allowing any kind of input, you can connect a
generic shadow block that didn't define any.
And, as mentioned... a default/standard variable doesn't have an output
type, so in theory it should be able to connect?