BlocklyのカスタムブロックをJS-Interpreterで実行できるようにする

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への登録で引数の指定を気にする必要はありません。




続いて、



引数を一つ持つ関数について考えてみます。


~/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関数に関する箇所に引数を一つ追加しています。




最後に



引数を二つ持つ関数について考えてみます。


~/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.setOutput(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個以上でも同様の要領で増やすことで対応できます。

マインクラフト用ビジュアルエディタを開発しています。
詳しくはinunosinsi/mcws_blockly - githubをご覧ください。