Blockly Developer Tools を使用すると、ブロックを使用してカスタム ブロックを作成できます。コア Blockly に付属のフィールドに加えて、プラグインとして公開されたフィールドもサポートしています。カスタム フィールドを作成した場合は、このガイドに沿って Block Factory にサポートを追加できます。カスタム フィールドのサポートを追加するには、事前に npm で公開する必要があります。また、Blockly の変更に対応するためにフィールドを更新することもコミットする必要があります。そうしないと、将来的に Block Factory から削除される可能性があります。
ブロック ファクトリーでの開発
ブロック ファクトリのソースコードは、blockly-samples リポジトリの examples/developer-tools
ディレクトリにあります。
blockly-samples のデベロッパー ツールに変更を送信するには、blockly-samples での開発の一般的な手順に沿って操作する必要があります。ただし、プラグインを操作する場合とは異なり、blockly-samples のルートレベルではなく、examples/developer-tools
ディレクトリから npm
install
を直接実行する必要があります。
プラグインをインストールする
ブロック ファクトリでカスタム フィールドをプレビューに表示するには、カスタム フィールドをインストールする必要があります。フィールドを developer-tools の npm 依存関係として追加します。次に、developer-tools/src/blocks/index.ts
で登録などの必要な設定を行います。
フィールドのブロックを作成する
Block Factory はブロックを使用してカスタムブロックを作成するため、カスタム フィールドを表すブロックが必要です。
ブロック定義を作成する
フィールドのブロックを設計する必要があります。メタデータを取得する場合は、Block Factory を使用して設計することもできます。ブロックでは、デフォルト値や名前など、フィールドに必要な設定をユーザーが構成できるようにする必要があります。このブロック定義を developer-tools/src/blocks/fields.ts
に追加し、developer-tools/src/blocks/index.ts
でインポートします。
ツールボックスにブロックを追加
次に、このブロックをツールボックス定義に追加して、ユーザーがアクセスできるようにする必要があります。ツールボックスの定義は developer-tools/src/toolbox.ts
にあります。ブロックは [フィールド] カテゴリに追加されます。
コード生成ツール
ブロック ファクトリは、Blockly でおなじみのコード生成システムを使用して動作します。各ブロックには、ブロック ファクトリで生成される出力のタイプごとにブロックコード ジェネレータがあり、親ブロックは子ブロックのコードを正しい出力に組み立てます。カスタム フィールドのサポートを追加するには、各 Code Generator クラスにブロックコード ジェネレータ関数を追加する必要があります。
output-generators/fields
ディレクトリにフィールド ブロックのファイルを作成します。このファイルに、次の各 Generator のブロックコード ジェネレータを追加します。blocks/index.ts
ファイルでこのファイルをインポートして、ブロックコード ジェネレータ関数がアプリケーションに読み込まれるようにします。
JavaScript の定義
javascriptDefinitionGenerator
は、カスタム フィールドを含むブロックの JavaScript 定義に含まれるコードを作成します。通常、これはブロックコード ジェネレータが .appendField(new YourFieldConstructor(arg1, arg2), 'userSpecifiedName')
のようなコード行を返す必要があることを意味します。複数のフィールドを含む入力には appendField
の呼び出しが複数連結されるため、このコード行にはセミコロンは含まれていません。コンストラクタの引数は、ユーザーがフィールド ブロックで設定した値から取得されます。FieldAngle
のブロックコード生成ツールの例を次に示します。
javascriptDefinitionGenerator.forBlock['field_angle'] = function (
block: Blockly.Block,
generator: JavascriptDefinitionGenerator,
): string {
const name = generator.quote_(block.getFieldValue('FIELDNAME'));
const angle = block.getFieldValue('ANGLE');
return `.appendField(new FieldAngle(${angle}), ${name})`;
};
ユーザーが Block Factory ツールボックスの [フィールド] カテゴリからドラッグした角度ブロックには、2 つのフィールドがあります。
FIELDNAME
: ユーザーはカスタムブロックのフィールドの名前を設定できますANGLE
: ユーザーはデフォルトの角度値を設定できます
このブロックコード ジェネレータでは、デフォルトの角度値を取得し、FieldAngle
コンストラクタに唯一の引数として渡します。フィールド名は常に appendField
の 2 番目の引数として渡されます。
JSON の定義
jsonDefinitionGenerator
も同様ですが、こちらはフィールドに対応する JSON ブロック定義の一部を出力します。通常、このコードは次のものを含む JSON オブジェクトです。
type
: Blockly フィールド レジストリのフィールド名に対応します。name
: ユーザーはカスタムブロックのフィールドの名前を設定できます- フィールドの JSON 初期化メソッドに必要なその他のカスタム プロパティ。
FieldAngle
の例をもう一度示します。
jsonDefinitionGenerator.forBlock['field_angle'] = function (
block: Blockly.Block,
generator: JsonDefinitionGenerator,
): string {
const code = {
type: 'field_angle',
name: block.getFieldValue('FIELDNAME'),
angle: block.getFieldValue('ANGLE'),
};
return JSON.stringify(code);
};
コード ヘッダー
コード ヘッダー ジェネレータは、Block Factory に表示されるコード ヘッダー出力を作成します。この出力は、ユーザーがコードを読み込む方法に応じて、esmodule インポートとスクリプトタグの間で切り替えることができます。そのため、実際には 2 つの異なるジェネレータ インスタンス(各ケースに 1 つずつ)があります。それぞれにブロックコード ジェネレータを追加する必要があります。FieldAngle
の例を次に示します。
importHeaderGenerator.forBlock['field_angle'] = function (
block: Blockly.Block,
generator: CodeHeaderGenerator,
): string {
generator.addHeaderLine(
`import {registerFieldAngle, FieldAngle} from '@blockly/field-angle';`,
);
generator.addHeaderLine(`registerFieldAngle();`);
return '';
};
scriptHeaderGenerator.forBlock['field_angle'] = function (
block: Blockly.Block,
generator: CodeHeaderGenerator,
): string {
generator.addHeaderLine(
`<script src="https://unpkg.com/@blockly/field-angle"></script>`,
);
generator.addHeaderLine(`registerFieldAngle();`);
return '';
};
これらのジェネレータには、コードでフィールドが使用される前に呼び出すコード行を指定できる addHeaderLine
というメソッドがあります。通常、これにはフィールドのインポートやスクリプトタグによる読み込み、Blockly のフィールド登録にフィールドを登録する関数の呼び出しなどの作業が含まれます。
これら 2 つのブロックコード ジェネレータでは、すべてのコードを addHeaderLine
の呼び出しを通じて追加する必要があります。この関数を使用すると、カスタム フィールド ブロックが 1 つのカスタム ブロックで複数回使用されている場合でも、各ヘッダー行が 1 回のみ表示されます。ブロックコード ジェネレータは空の文字列を返します。
ジェネレータ スタブ
最後に、フィールドの生成ツール スタブを作成する生成ツールがあります。このブロックコード ジェネレータでは、ユーザーがコードを生成するコードを記述するのに役立つコードを生成するコードを記述します。混乱しましたか?思ったより簡単です。
カスタムブロックのジェネレータ スタブには、ブロックのすべてのフィールドを表す既製の変数が含まれています。次に、ユーザーがこれらの変数をすべて組み立てて、カスタム ブロックが返す最終的なコード文字列にするために完了する必要がある TODO
があります。つまり、通常、ブロックコード ジェネレータは、このカスタム変数を作成する行を返すだけで済みます。ユーザーがキャンバスに太陽光線を追加するカスタム ブロックを作成しているとします。ブロックに角度フィールドを追加して、"SUN_DIRECTION"
という名前を付けます。このブロックのジェネレータ スタブには、const angle_sun_direction =
block.getFieldValue("SUN_DIRECTION");
という行が含まれます。これは、角度フィールドのブロックコード ジェネレータが返す必要があるコード行です。
generatorStubGenerator.forBlock['field_angle'] = function (
block: Blockly.Block,
generator: GeneratorStubGenerator,
): string {
const name = block.getFieldValue('FIELDNAME');
const fieldVar = generator.createVariableName('angle', name);
return `const ${fieldVar} = block.getFieldValue(${generator.quote_(
name,
)});\n`;
};
変数の標準化された名前を取得するには、generator.createVariableName
を呼び出し、フィールドの型(angle
、number
など)とユーザーがフィールドに付けた名前を渡します。
テスト
これらの部分をすべて記述したら、blockly-samples/examples/developer-tools
ディレクトリで npm start
を実行して、ブロック ファクトリを開始できます。フィールド カテゴリからブロックをドラッグして、ブロックの入力に追加し、出力の変化を確認できます。ブロックのプレビューが正しく表示され、各出力セクションのコードが正しいことを確認します。