Block Factory에 플러그인 필드 추가

Blockly 개발자 도구를 사용하면 블록을 사용하여 맞춤 블록을 만들 수 있습니다. 핵심 Blockly와 함께 제공되는 필드 외에도 플러그인으로 게시되는 필드를 지원합니다. 맞춤 입력란을 만든 경우 이 가이드에 따라 블록 팩토리에 지원을 추가할 수 있습니다. 커스텀 필드를 지원하려면 먼저 npm에 게시해야 합니다. 또한 Blockly의 변경사항을 따라 필드를 업데이트해야 합니다. 그렇지 않으면 향후 블록 팩토리에서 필드를 삭제해야 할 수 있습니다.

블록 팩토리에서 개발

블록 팩토리의 소스 코드는 examples/developer-tools 디렉터리의 blockly-samples 저장소에 있습니다.

blockly-samples의 개발자 도구에 변경사항을 제출하려면 blockly-samples에서 개발하는 일반적인 단계를 따라야 합니다. 플러그인 작업과 달리 blockly-samples의 루트 수준이 아닌 examples/developer-tools 디렉터리에서 직접 npm install를 실행해야 합니다.

플러그인 설치

블록 팩토리에서 미리보기에 맞춤 필드를 표시하려면 맞춤 필드를 설치해야 합니다. 필드를 developer-tools의 npm 종속 항목으로 추가합니다. 그런 다음 developer-tools/src/blocks/index.ts에서 등록하거나 필요한 다른 설정 작업을 실행합니다.

필드의 블록 만들기

블록 팩토리에서는 블록을 사용하여 맞춤 블록을 만들기 때문에 맞춤 필드를 나타내는 블록이 필요합니다.

블록 정의 만들기

필드의 블록을 설계해야 합니다. 메타를 가져오려면 블록 팩토리를 사용하여 설계할 수도 있습니다. 이 블록을 통해 사용자는 기본값, 이름 등 필드에 필요한 설정을 구성할 수 있어야 합니다. 이 블록 정의를 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 등)과 사용자가 필드에 지정한 이름을 전달하면 됩니다.

테스트

이러한 부분을 모두 작성한 후 blockly-samples/examples/developer-tools 디렉터리에서 npm start를 실행하여 블록 팩토리를 시작할 수 있습니다. 필드 카테고리에서 블록을 드래그하여 블록의 입력에 추가하고 출력이 변경되는 것을 확인할 수 있습니다. 블록의 미리보기가 올바르게 표시되고 각 출력 섹션의 코드가 올바른지 확인합니다.