进阶积木 API 用法
一次性添加/删除积木
ClipCC 提供一次性添加/删除积木的支持。 你可以使用 api.addBlocks(blocks: BlockPrototype[]) 和 api.removeBlocks(blocksOpcode: string[]) 来实现它们。
显示条件
ClipCC 从 3.1.4 开始提供对积木显示条件的支持。 以下是一个示例:
api.addBlock({
    opcode: 'example.block',
    type: type.BlockType.COMMAND,
    messageId: 'example.block',
    categoryId: 'example.category',
    function: () => {...},
    option: {
        // 仅在舞台中显示
        filter: type.FilterType.STAGE
    }
});
对于更多积木选项, 请查看 BlockPrototype - BlockOption
菜单
ClipCC 从 3.1.2 开始提供对菜单输入的支持。正确定义菜单的方式是在 parameter 属性内定义包含菜单项的menu属性。
菜单
param: {
    PARAMETER: {
        type: type.ParameterType.STRING,
       menu: [{
           messageId: 'example.extension.menu.type',
           value: 'type'
            }, {
                   messageId: 'example.extension.menu.rainbow',
                   value: 'rainbow'
            }, {
                  messageId: 'example.extension.menu.zoom',
                  value: 'zoom'
            }],
           default: 'rainbow'
      }
}
动态菜单
caution
以下所涉及的扩展API能处于草案阶段,所涉及的内容可能在未来被修改。
param: {
    PARAMETER: {
        type: type.ParameterType.STRING,
        menu: () => {
            // 返回当前所有角色
            const vm = api.getVmInstance();
            const sprites = [];
            for (const targetId in vm.runtime.targets) {
                if (!vm.runtime.targets.hasOwnProperty(targetId)) continue;
                const name = vm.runtime.targets[targetId].sprite.name;
                sprites.push([name, name]);
            }
            return sprites;
        },
        default: 'rainbow'
      }
}
如果你想定义一个不可动态输入的菜单, 那么你可以将field 属性设置为 true.
param: {
    PARAMETER: {
        type: type.ParameterType.STRING,
        default: 'something',
        field: true,
        menu: [...]
      }
},
帽状积木
这个简单的实例阐述了如何定义一个 HAT 类型的积木:
api.addBlock({
        opcode: 'example.hat',
        type: type.BlockType.HAT,
        messageId: 'example.hat',
        categoryId: 'example.category',
        param: {
            CONDITION: {
                type: type.ParameterType.BOOLEAN
            }
        },
        function: (args) => {
            if (!!hasReported) {
                window.hasReported = false;
                return false;
            }
            const result = !!args.CONDITION;
            if (result) {
                hasReported = true;
                return true;
            }
            return false;
        }
});
当积木被拖拽至工作区后,项目会进入“假”运行状态(绿旗高亮,但没有脚本被触发)。编辑器每帧都会检查该 HAT 是否被触发。只有当上一帧返回false且当前帧返回true时积木才会正常被调用。
树状积木
ClipCC 从 3.1.4 开始提供对树状积木的支持。以下是一个定义树状积木的定义:
api.addBlock({
    opcode: 'example.if',
    type: type.BlockType.COMMAND,
    messageId: 'example.if',
    categoryId: 'example.category',
    branchCount: 1,
    param: {
        COND: {
            type: type.ParameterType.BOOLEAN
        }
    },
    function: (args, util) => {
        // If the condition is true, start the branch.
        if (!!args.COND) util.startBranch(1, false);
    }
});
{
    "example.if": "if [COND] [SUBSTACK]"
}
你需要在 BlockPrototype 中指定 "branchCount", 它意味着树状积木的分支数量。 你还需要在语言文件中以 [SUBSTACKX] 的命名方式定义分支参数。 对于一个树状积木, 你可以通过 util 对象中的 startBranch 方法来进行流程控制。
/**
* 在当前积木下触发某个分支
* @param {number} branchNum 触发分支的编号 (i.e., 1, 2).
* @param {boolean} isLoop 这个分支是否是一个循环
*/
startBranch (branchNum, isLoop) {...}
当 isLoop 参数被设为 true 时, 积木将被重复调用,直到startBranch 不再被触发。当被设为 false 时, 当前积木将被立刻跳出。 当branchNum参数未被指定时, 默认为1。这里有一个关于流程控制的 更为详细的范例.
编写这类积木通常需要对线程和调度器进行修改, 所以你需要对 Scratch/ClipCC 的代码具有一定程度上的理解。通常情况下,我们不推荐你定义这类积木。