Добавьте поле плагина в Block Factory

Инструменты разработчика Blockly позволяют создавать собственные блоки с помощью блоков! Он поддерживает поля, которые публикуются как плагины, в дополнение к полям, которые входят в состав ядра Blockly. Если вы создали настраиваемое поле, вы можете добавить его поддержку в Фабрику блоков, следуя этому руководству. Настраиваемое поле должно быть опубликовано в npm, прежде чем вы сможете добавить его поддержку. Вам также необходимо обновить свое поле, чтобы идти в ногу с изменениями в Blockly, в противном случае нам может потребоваться удалить его из Block Factory в будущем.

Разработка на заводе блоков

Исходный код Block Factory находится в репозитории blockly-samples в каталоге examples/developer-tools .

Чтобы внести изменения в инструменты разработчика в блочных образцах, вам необходимо выполнить типичные шаги для разработки в блочных образцах. Однако, в отличие от работы с плагинами, вам нужно будет запустить npm install напрямую из каталога examples/developer-tools , а не на корневом уровне блочных образцов.

Установите плагин

Чтобы Фабрика блоков отображала ваше настраиваемое поле в предварительном просмотре, необходимо установить настраиваемое поле. Добавьте свое поле в качестве зависимости npm от инструментов разработчика. Затем зарегистрируйте его или выполните любую другую необходимую работу по настройке в developer-tools/src/blocks/index.ts .

Создайте блок для поля

Поскольку Фабрика блоков использует блоки для создания пользовательских блоков, вам понадобится блок, представляющий ваше настраиваемое поле.

Создайте определение блока

Вам необходимо спроектировать блок для вашего поля; если вы хотите получить мета, вы даже можете создать его с помощью Block Factory! Блок должен позволять пользователю настраивать параметры, необходимые для вашего поля, например значения по умолчанию и имя. Добавьте это определение блока в developer-tools/src/blocks/fields.ts и импортируйте его в developer-tools/src/blocks/index.ts .

Добавить блок в панель инструментов

Далее вам необходимо добавить этот блок в определение панели инструментов, чтобы сделать его доступным для пользователей. Определение набора инструментов находится в developer-tools/src/toolbox.ts . Ваш блок должен быть добавлен в категорию «Поля».

Генераторы кода

Фабрика блоков работает с использованием системы генератора кода, с которой вы уже знакомы по Blockly. Каждый блок имеет генератор блочного кода для каждого типа вывода, генерируемого фабрикой блоков, а родительские блоки собирают код для дочерних блоков в правильный вывод. Чтобы добавить поддержку настраиваемого поля, вам необходимо добавить функции генератора блочного кода для каждого из классов генератора кода.

Создайте файл для вашего блока полей в каталоге output-generators/fields . Вы добавите в этот файл генераторы блочного кода для каждого из следующих генераторов. Импортируйте этот файл в файл 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})`;
};

Угловой блок, который пользователь перетащил из категории «Поля» панели инструментов «Фабрика блоков», содержит два поля:

  • FIELDNAME : пользователь может установить имя поля в своем пользовательском блоке.
  • ANGLE : пользователь может установить значение угла по умолчанию.

В этом генераторе блочного кода мы получаем значение угла по умолчанию и передаем его в качестве единственного аргумента конструктору FieldAngle . Имя поля всегда передается в качестве второго аргумента методу appendField .

Определение 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);
};

Заголовки кода

Генератор заголовков кода создает выходные данные заголовков кода, показанные в фабрике блоков. Этот вывод можно переключать между импортом esmodule и тегами скрипта, в зависимости от того, как пользователь желает загрузить код, поэтому на самом деле существует два разных экземпляра генератора: по одному для каждого случая. Вам необходимо добавить генератор блочного кода для каждого из них. Вот пример 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.

Для этих двух генераторов блочного кода весь код должен быть добавлен посредством вызовов addHeaderLine . Эта функция гарантирует, что каждая строка заголовка отображается только один раз, даже если ваш блок настраиваемых полей используется несколько раз в одном настраиваемом блоке. Генератор блочного кода должен вернуть пустую строку.

Заглушка генератора

Наконец, у нас есть генератор, который создает заглушку генератора для поля. В этом генераторе блочного кода вы будете писать код, генерирующий код, помогающий пользователю писать код, генерирующий код. Еще не запутались? Это проще, чем кажется!

Заглушка генератора пользовательского блока включает в себя заранее созданную переменную, представляющую каждое поле блока. Затем есть 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 и т. д.) вместе с тем, как пользователь назвал свое поле.

Проверьте это

После того, как вы написали все эти части, вы сможете запустить Block Factory, запустив npm start в каталоге blockly-samples/examples/developer-tools . У вас должна быть возможность перетащить свой блок из категории полей, добавить его к входным данным блока и наблюдать за изменением выходных данных. Убедитесь, что предварительный просмотр блока выглядит правильно и что код для каждого из выходных разделов верен.