Plug-in-Feld zu Block Factory hinzufügen

Mit den Blockly-Entwicklertools können Sie benutzerdefinierte Blöcke erstellen. Es unterstützt Felder, die als Plug-ins veröffentlicht werden, zusätzlich zu den Feldern, die mit dem Blockly-Kern geliefert werden. Wenn Sie ein benutzerdefiniertes Feld erstellt haben, können Sie die Unterstützung dafür in der Block Factory hinzufügen. Folgen Sie dazu dieser Anleitung. Das benutzerdefinierte Feld muss auf npm veröffentlicht werden, bevor Sie Unterstützung dafür hinzufügen können. Außerdem müssen Sie sich verpflichten, das Feld zu aktualisieren, um mit Änderungen in Blockly Schritt zu halten. Andernfalls müssen wir es möglicherweise in Zukunft aus Block Factory entfernen.

Entwicklung in der Block Factory

Der Quellcode für die Block Factory befindet sich im Repository „blockly-samples“ im Verzeichnis examples/developer-tools.

Wenn Sie eine Änderung an den Entwicklertools in blockly-samples einreichen möchten, müssen Sie die üblichen Schritte für die Entwicklung in blockly-samples ausführen. Anders als bei der Arbeit mit Plug-ins müssen Sie npm install jedoch direkt aus dem Verzeichnis examples/developer-tools und nicht auf der Stammebene von „blockly-samples“ ausführen.

Plug-in installieren

Damit das benutzerdefinierte Feld in der Block Factory in der Vorschau angezeigt wird, muss es installiert werden. Fügen Sie Ihr Feld als NPM-Abhängigkeit von „developer-tools“ hinzu. Registrieren Sie es dann oder führen Sie andere erforderliche Einrichtungsschritte in developer-tools/src/blocks/index.ts aus.

Block für das Feld erstellen

Da in der Block Factory Blöcke zum Erstellen benutzerdefinierter Blöcke verwendet werden, benötigen Sie einen Block, der Ihr benutzerdefiniertes Feld darstellt.

Blockdefinition erstellen

Sie müssen den Block für Ihr Feld entwerfen. Wenn Sie möchten, können Sie ihn sogar mit Block Factory entwerfen. Der Block sollte es dem Nutzer ermöglichen, die für das Feld erforderliche Einrichtung zu konfigurieren, z. B. Standardwerte und einen Namen. Fügen Sie diese Blockdefinition in developer-tools/src/blocks/fields.ts ein und importieren Sie sie in developer-tools/src/blocks/index.ts.

Block zur Toolbox hinzufügen

Als Nächstes müssen Sie diesen Block der Toolbox-Definition hinzufügen, damit er für Nutzer zugänglich ist. Die Toolbox-Definition befindet sich in developer-tools/src/toolbox.ts. Der Block sollte der Kategorie „Felder“ hinzugefügt werden.

Code-Generatoren

Die Block Factory verwendet das Code Generator-System, das Sie bereits aus Blockly kennen. Jeder Block hat einen Blockcodegenerator für jede Art von Ausgabe, die von der Block Factory generiert wird. Die übergeordneten Blöcke fügen den Code für die untergeordneten Blöcke in die richtige Ausgabe ein. Wenn Sie Unterstützung für ein benutzerdefiniertes Feld hinzufügen möchten, müssen Sie für jede der Code Generator-Klassen Blockcode-Generatorfunktionen hinzufügen.

Erstellen Sie eine Datei für Ihren Feldblock im Verzeichnis output-generators/fields. Sie fügen dieser Datei die Blockcodegeneratoren für die folgenden Generatoren hinzu. Importieren Sie diese Datei in die Datei blocks/index.ts, damit die Blockcodegeneratorfunktionen in die Anwendung geladen werden.

JavaScript-Definition

Mit javascriptDefinitionGenerator wird der Code erstellt, der in die JavaScript-Definition für einen Block mit Ihrem benutzerdefinierten Feld aufgenommen wird. Normalerweise bedeutet das, dass der Blockcodegenerator eine Codezeile zurückgeben sollte, die so aussieht: .appendField(new YourFieldConstructor(arg1, arg2), 'userSpecifiedName'). Diese Zeile enthält kein Semikolon, da bei einer Eingabe mit mehreren Feldern mehrere Aufrufe von appendField verkettet werden. Die Argumente im Konstruktor werden aus den Werten abgerufen, die der Nutzer im Feldblock festgelegt hat. Hier sehen Sie ein Beispiel für diesen Blockcodegenerator für 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})`;
};

Der Winkelblock, den der Nutzer aus der Kategorie „Felder“ der Block Factory-Toolbox gezogen hat, enthält zwei Felder:

  • FIELDNAME: Der Nutzer kann den Namen des Felds in seinem benutzerdefinierten Block festlegen.
  • ANGLE: Der Nutzer kann den Standardwinkelwert festlegen.

In diesem Blockcode-Generator rufen wir den Standardwinkelwert ab und übergeben ihn als einziges Argument an den FieldAngle-Konstruktor. Der Feldname wird immer als zweites Argument an appendField übergeben.

JSON-Definition

jsonDefinitionGenerator ist ähnlich, gibt aber den Teil der JSON-Blockdefinition aus, der Ihrem Feld entspricht. Normalerweise ist dieser Code ein JSON-Objekt, das Folgendes enthält:

  • type: entspricht dem Namen Ihres Felds in der Blockly-Feldregistrierung.
  • name: Der Nutzer kann den Namen des Felds in seinem benutzerdefinierten Block festlegen.
  • Alle anderen benutzerdefinierten Eigenschaften, die für die JSON-Initialisierungsmethode des Felds erforderlich sind.

Hier ein weiteres Beispiel aus 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);
};

Code-Header

Der Code Header Generator erstellt die Code-Header-Ausgabe, die in der Block Factory angezeigt wird. Die Ausgabe kann zwischen esmodule-Importen und Script-Tags umgeschaltet werden, je nachdem, wie der Nutzer den Code laden möchte. Es gibt also zwei verschiedene Generatorinstanzen: eine für jeden Fall. Sie müssen für jede einen Blockcode-Generator hinzufügen. Hier ein Beispiel für 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 '';
};

Diese Generatoren haben eine Methode namens addHeaderLine, mit der Sie eine Codezeile angeben können, die aufgerufen werden soll, bevor Ihr Feld im Code verwendet wird. Dazu gehört in der Regel, das Feld zu importieren oder über ein Script-Tag zu laden und möglicherweise eine Funktion aufzurufen, die das Feld in der Feldregistrierung von Blockly registriert.

Bei diesen beiden Blockcodegeneratoren sollte der gesamte Code über Aufrufe von addHeaderLine hinzugefügt werden. Mit dieser Funktion wird dafür gesorgt, dass jede Kopfzeile nur einmal angezeigt wird, auch wenn Ihr benutzerdefinierter Feldblock mehrmals in einem benutzerdefinierten Block verwendet wird. Der Blockcodegenerator sollte den leeren String zurückgeben.

Generator-Stub

Schließlich haben wir den Generator, der den Generator-Stub für das Feld erstellt. In diesem Blockcodegenerator schreiben Sie Code, der Code generiert, der dem Nutzer hilft, Code zu schreiben, der Code generiert. Verwirrt? Das ist einfacher, als es klingt.

Der Generator-Stub für einen benutzerdefinierten Block enthält eine vorgefertigte Variable, die jedes Feld im Block darstellt. Dann gibt es ein TODO, das der Nutzer ausfüllen muss, um alle diese Variablen in den endgültigen Codestring einzufügen, den sein benutzerdefinierter Block zurückgibt. Das bedeutet, dass Ihr Blockcode-Generator in der Regel nur die Zeile zurückgeben muss, mit der diese benutzerdefinierte Variable erstellt wird. Angenommen, der Nutzer erstellt einen benutzerdefinierten Block, mit dem Sonnenstrahlen auf die Arbeitsfläche eingefügt werden. Sie fügen dem Block ein Winkelfeld hinzu und nennen es "SUN_DIRECTION". Der Generator-Stub für diesen Block würde die Zeile const angle_sun_direction = block.getFieldValue("SUN_DIRECTION"); enthalten. Das ist die Codezeile, die unser Blockcodegenerator für das Winkelfeld zurückgeben muss:

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`;
};

Um einen standardisierten Namen für die Variable zu erhalten, können Sie generator.createVariableName aufrufen und den Typ des Felds (z. B. angle, number usw.) zusammen mit dem Namen übergeben, den der Nutzer für das Feld angegeben hat.

Testen

Nachdem Sie alle diese Teile geschrieben haben, können Sie die Block Factory starten, indem Sie npm start im Verzeichnis blockly-samples/examples/developer-tools ausführen. Sie sollten den Block aus der Feldkategorie ziehen, ihn einer Eingabe eines Blocks hinzufügen und beobachten können, wie sich die Ausgabe ändert. Prüfen Sie, ob die Vorschau des Blocks richtig aussieht und der Code für die einzelnen Ausgabebereiche korrekt ist.