子图
子图节点表示当前图内部的另一个图。
子图节点的端口由内部图的暴露变量生成。

当用户需要进入子图时,使用 GraphEditorView。双击动作由子图节点元素处理,并请求最近的 GraphEditorView 将内部图作为新的面包屑层级打开。

在子图内部,不直接编辑子图节点上的端口。应该在 Blackboard 中定义变量,然后在 Inspector 中设置它们的 flow direction:
Input会在面向父图的子图节点上创建输入端口。Output会在面向父图的子图节点上创建输出端口。Input + Output会创建两个方向的端口。
准确的方向映射见 Variables and Blackboard。
本地子图
本地子图以内联方式存储在父图中。
SubgraphNodeModel.Kind.LOCAL 通过 UID 指向父模型 localSubGraphs 列表中的某个图。
当内部图只属于该父图时,使用本地子图。
外部子图
外部子图指向一个 IResourcePath。
SubgraphNodeModel.Kind.EXTERNAL 通过 GraphModel.getReferenceResolver() 解析。
在编辑器上下文之外,resolver 可能为 null。这种情况下,子图节点会复用缓存的端口形状,让已有连线能保留下来。
从资源导入外部子图
对于基于资源的图资产,可以从 editor resource panel 把图资源拖到图画布上。
编辑器流程是:
GraphResourceProviderContainer 会保留被拖拽资源的路径,因此放下后的节点会存储稳定的外部引用,而不是复制图 NBT。
以下情况会拒绝 drop:
- 图不允许创建子图,
- 资源被拖放到图内容区域之外,
- 资源路径与当前打开的根图相同,
- 资源属于另一个图类型,并且宿主图没有通过
acceptsSubgraphGraph(...)接受它。
导入后,该节点和其他子图节点一样使用。双击它可以编辑被引用的图。通过 dive-in view 编辑外部子图时,GraphEditorView 会通过 reference resolver 保存该层级,SubgraphRegistry 会刷新其他引用同一资源的已打开图。
变量端口
子图节点端口由内部图的变量生成:
| 内部变量 | 外部子图节点 |
|---|---|
VariableKind.INPUT | 输入端口。 |
VariableKind.OUTPUT | 输出端口。 |
READ_WRITE 变量会用带后缀的端口 id 创建两个方向。
使用这个 graph hook 限制可暴露的变量方向:
@Override
public Set<VariableKind> getSupportedSubgraphVariableKinds() {
return Set.of(VariableKind.INPUT, VariableKind.OUTPUT);
}返回空集合可以禁用基于变量的子图端口。
跨类型子图
默认允许同类型本地子图。
跨类型子图需要宿主图显式允许:
@Override
public boolean acceptsSubgraphGraph(Graph other) {
return other instanceof MaterialGraph;
}这同时适用于导入的外部引用和外来本地子图。
外部保存广播
当外部图资源被保存时,SubgraphRegistry 会广播事件。
订阅者包括:
- 需要重新定义子图节点端口的根
GraphModel实例, - 可能需要重新加载或刷新已打开图 view 的编辑器监听器。
GraphEditorView 会在图加载时注册,在清理时注销。