BlocklyのカスタムブロックをJS-Interpreterで実行できるようにしてみます。
JS-Interpreterに関してはBlocklyでコードを実行してみように記載があります。
最初は

コンソールにhogeの文字列を出力する簡単なブロックを登録してみます。
※関数名もhogeにして話を進めます。
作成中のコードに今回のブロックに関するコードを組み込みます。
~/workspace/blockly/custom.js
に下記のコードを組み込みます。
Blockly.Blocks['hoge'] = {
init: function() {
this.appendDummyInput()
.appendField("hoge");
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(230);
this.setTooltip("");
this.setHelpUrl("");
}
};
javascript.javascriptGenerator.forBlock['hoge'] = function(block, generator) {
var code = 'hoge();\n';
return code;
};
ここでコードの説明用として、hogeブロックにはJavaScriptの組み込み関数にはないhogeという関数を実行することにしています。
JS-Interpreterでhoge関数を実行できるようにします。
Blocklyでコードを実行してみようの記事で作成したコードを下記のように変更します。
~/workspace/blockly/index.html
function initApi(interpreter, globalObject) {
// Add an API function for the alert() block.
var wrapper = function(text) {
return alert(arguments.length ? text : '');
};
interpreter.setProperty(globalObject, 'alert',
interpreter.createNativeFunction(wrapper));
}
※説明用として、initApiに登録している関数はalertのみにしています。
を
function hoge(){
console.log("hoge");
}
function initApi(interpreter, globalObject) {
// Add an API function for the alert() block.
var wrapper = function(text) {
return alert(arguments.length ? text : '');
};
interpreter.setProperty(globalObject, 'alert',
interpreter.createNativeFunction(wrapper));
wrapper = function(){
return hoge();
};
interpreter.setProperty(globalObject, 'hoge',
interpreter.createNativeFunction(wrapper));
}
に変更します。
ここで注意すべき点としまして、hoge関数を作っておき、initApi内で作成したhoge関数を指定していることです。
hoge関数は引数を持たないので、initApiへの登録で引数の指定を気にする必要はありません。
hogeブロックをtoolboxに追加しておきます。
Blocklyでツールボックスのブロックをカテゴリ分けしてみるで作成しましたCustomカテゴリにhogeブロックを追加します。
const toolbox = {
kind: "categoryToolbox",
contents: [
/** 途中省略 **/
{
kind: "category",
name: "Custom",
contents: [
/** 途中省略 **/
{
kind: "block",
type: "forever",
},
{
kind: "block",
type: "hoge",
},
],
},
],
}
続いて、

引数を一つ持つ関数について考えてみます。
~/workspace/blockly/custom.js
から先ほど追加したhoge分を削除して、新たに下記のコードを追加します。
Blockly.Blocks['hoge'] = {
init: function() {
this.appendValueInput("VALUE")
.setCheck("String")
.appendField(new Blockly.FieldLabelSerializable(""), "VALUE");
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(230);
this.setTooltip("");
this.setHelpUrl("");
}
};
javascript.javascriptGenerator.forBlock['hoge'] = function(block, generator) {
var value = generator.valueToCode(block, 'VALUE', javascript.Order.ATOMIC);
var code = 'hoge('+value+');\n';
return code;
};
~/workspace/blockly/index.html
を下記のように変更します。
function hoge(){
console.log("hoge");
}
function initApi(interpreter, globalObject) {
// Add an API function for the alert() block.
var wrapper = function(text) {
return alert(arguments.length ? text : '');
};
interpreter.setProperty(globalObject, 'alert',
interpreter.createNativeFunction(wrapper));
wrapper = function(){
return hoge();
};
interpreter.setProperty(globalObject, 'hoge',
interpreter.createNativeFunction(wrapper));
}
を
function hoge(text){
console.log(text);
}
function initApi(interpreter, globalObject) {
// Add an API function for the alert() block.
var wrapper = function(text) {
return alert(arguments.length ? text : '');
};
interpreter.setProperty(globalObject, 'alert',
interpreter.createNativeFunction(wrapper));
wrapper = function(text){
return hoge(text);
};
interpreter.setProperty(globalObject, 'hoge',
interpreter.createNativeFunction(wrapper));
}
のように修正します。
hoge関数に関する箇所に引数を一つ追加しています。
toolboxに追加する記述は
{
kind: "block",
type: "hoge",
},
から
{
kind: "block",
type: "hoge",
inputs: {
VALUE: {
block: {
type: "text",
fields: {
TEXT: "hoge",
},
},
},
},
},
に変更します。
最後に

引数を二つ持つ関数について考えてみます。
~/workspace/blockly/custom.js
から先ほど追加したhoge分を削除して、新たに下記のコードを追加します。
Blockly.Blocks['hoge'] = {
init: function() {
this.appendValueInput("VALUE")
.setCheck("String")
.appendField(new Blockly.FieldLabelSerializable(""), "VALUE");
this.appendDummyInput();
this.appendValueInput("VALUE2")
.setCheck("String")
.setAlign(Blockly.ALIGN_RIGHT)
.appendField(new Blockly.FieldLabelSerializable(""), "VALUE2");
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(230);
this.setTooltip("");
this.setHelpUrl("");
}
};
javascript.javascriptGenerator.forBlock['hoge'] = function(block, generator) {
var value = generator.valueToCode(block, 'VALUE', javascript.Order.ATOMIC);
var value2 = generator.valueToCode(block, 'VALUE2', javascript.Order.ATOMIC);
var code = 'hoge('+value+','+value2+');\n';
return code;
};
~/workspace/blockly/index.html
を下記のように変更します。
function hoge(text, text2){
console.log(text+text2);
}
function initApi(interpreter, globalObject) {
// Add an API function for the alert() block.
var wrapper = function(text) {
return alert(arguments.length ? text : '');
};
interpreter.setProperty(globalObject, 'alert',
interpreter.createNativeFunction(wrapper));
wrapper = function(text, text2){
return hoge(text, text2);
};
interpreter.setProperty(globalObject, 'hoge',
interpreter.createNativeFunction(wrapper));
}
これで引数が二つの関数もJS-Interpreterで実行できるようになりました。
引数が3個以上でも同様の要領で増やすことで対応できます。
toolboxに追加する記述は
{
kind: "block",
type: "hoge",
inputs: {
VALUE: {
block: {
type: "text",
fields: {
TEXT: "hoge",
},
},
},
},
},
から
{
kind: "block",
type: "hoge",
inputs: {
VALUE: {
block: {
type: "text",
fields: {
TEXT: "hoge",
},
},
},
VALUE2: {
block: {
type: "text",
fields: {
TEXT: "huga",
},
},
},
},
},
に変更します。