Block Factory에 플러그인 필드 추가

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

블록 팩토리에서의 개발

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

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

플러그인 설치

블록 팩토리가 미리보기에 맞춤 필드를 표시하려면 맞춤 필드를 설치해야 합니다. 필드를 개발자 도구의 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에 있습니다. 해당 블록을 '필드' 카테고리에 추가해야 합니다.

코드 생성기

Block Factory는 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를 완료해야 합니다. 즉, 일반적으로 블록 코드 생성기는 이 맞춤 변수를 만드는 줄을 반환하기만 하면 됩니다. 사용자가 캔버스에 햇빛을 추가하는 맞춤 블록을 만든다고 가정해 보겠습니다. 블록에 angle 필드를 추가하고 이름을 "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를 실행하여 블록 팩토리를 시작할 수 있습니다. 필드 카테고리에서 블록을 드래그하여 블록의 입력에 추가하고 출력이 변경되는 것을 확인할 수 있어야 합니다. 블록의 미리보기가 제대로 표시되는지, 각 출력 섹션의 코드가 올바른지 확인하세요.