Google Blockly Reimplementation with Unity/C#(2)
Contents
- Introduction
- Blockly Model
- Code Generator, Interpreter and Runner
- UGUI Design
For English:
Google Blockly Model
核心Model模块完全参考Google Blockly。正如前文框架图所示,Blockly主要包括模型:Workspace
,Variable
, Block
, Connection
, Input
, Field
。
Workspace相当于一个容器,包含Blocks, Variables。
- 一个Workspace可以存储为一个Xml文件,保留Blocks之间的连接关系,以及属性信息。反过来也可以从一个格式正确的Xml文件重建一个Workspace。
- Code Generator&Interpreter从遍历一个Workspace的顶层Block开始,根据Blocks之间的连接关系依次深度优先向下执行。
- 一个Workspace在UI上显示为可供编辑Block的区域,其中还包含一个Toolbox,提供Block原型的容器。
Variable是作用在一个Workspace中的全局变量。
Block代表一段可执行程序。
- 类比于一个方法,可以有输出(作为另一个Block的输入使用),也可以是没有输出(作为一个命令接在另一个Block下面执行)。
- Blocks之间的关系有两种:输入/输出,前/后。Blocks在一个Workspace中的结构如下:
- Block(Topmost in workspace) - ConnectionOutput - ConnectionPrev - ConnectionNext - Block(Next) - Input - Field - Field ... - ConnectionInput - Block(Input) - Input ... - Block ... - Block ...
Connection是实现Blocks之间的连接的关键,方式如下:
Block.ConnectionOutput <-> Block.Input.ConnectionInput
Block.ConnectionPrev <-> Block.ConnectionNext
Input是Block的基本单元。
一个Input包含若干Field,以及一个Connection用来连接输入Block。
依照json语义,按顺序创建Input。每个input之前的field都包含在该input里,如果剩下的field后没有定义input,则创建一个dummy input来包含剩下的fields。
"message0": "%{BKY_COROUTINE_WAIT_TITLE} %1 %2", "args0": [ { "type": "input_value", "name": "TIME", "check": "Number" }, { "type": "field_dropdown", "name": "UNIT", "options": [ ["%{BKY_TIME_UNIT_MILLISECOND}", "MILLISECOND"], ["%{BKY_TIME_UNIT_SECONDS}", "SECONDS"], ["%{BKY_TIME_UNIT_MINUTES}", "MINUTES"], ["%{BKY_TIME_UNIT_TOO_HIGH}", "TOOHIGH"] ] } ],
Block结果显示为:
message0
定义了block的形态:%{BKY_COROUTINE_WAIT_TITLE}
: 多语言的key%1
: input_value%2
: field_dropdown
该Block有两个Input:
- input_value,Input Connection;
- dummy input。因为field_dropdown后没有input,因此创建一个dummy input来包含该field_dropdown。
Field描述Block的属性、状态,拿上例解释:
field_dropdown
:提供menu选择,不同选项代表了该Block执行不同的功能,比如算术运算的+
,-
,*
,/
。除此之外,还有
field_variable
,field_number
,field_textinput
等,开发者也可自己定义。
Json语义定义
一个Block是由json语义来定义的,主要有如下属性:
- type,用来识别Block的类型标识符;
- Input/Field,如上例,以及对每个field, input属性、输入类型的描述;
- Block Output Connection,或者Previous/Next Connection;
- UI背景色;
- 特殊属性;
开发者可通过自定义Json描述,来定义一个新的Block。
Mutation特性
上文Json定义中提到了特殊属性,其中Mutation就是一个,它提供了动态修改Block结构的功能。
IF/ELSE就是一个典型的需要Mutation的例子:
=>
用户在编辑时,只需要指定else if
的个数,以及是否有else
,Mutation根据这些变量重构Block结构。
函数
Mutation特性给函数Block的实现提供了便利。
下图定义了一个Swap(x, y)的函数,调用结果为将传入的x, y的值互换。
函数Block(Google Blockly称“Procedure”)分为两大类:
- 函数声明Procedure Definition: 利用Mutation功能可以允许用户定义函数名、参数,供所在的Workspace全局调用。见上图右。
- 函数调用Procedure Call: 对应每个声明的函数,都会自动定义一个函数调用Block供用户选择。Block中只包含函数名、参数Input,见上图左;
自定义Mutation
开发者可以定义更多的Mutation,而具体Mutation的功能需自己实现。
以上简单介绍了Blockly的模型结构,下一篇博文会介绍Code Generator, Interpreter 以及 Runner的实现方法。