# dag4blend Composite Editor
## 如何启用
Composite Editor 目前正在开发中,被视为一项实验性功能。因此,默认情况下它是隐藏的。要启用其可见性,您需要在附加组件设置中选中相应的框。
复合编辑器可以在 **Dagor** 选项卡下的 **N-panel**中找到。
面板本身分为三个主要部分:**CMP Import**, **CMP Export**, and **CMP Tools**.
## CMP Import
- **import path**: 这是 `name.composit.blk` 文件的完整路径。
但是,如果选择了正确的项目,您只需指定 `name.composit.blk` 甚至只指定 `name` – 插件将定位并导入它。
- **refresh cache**: 要导入子合成和几何,模块需要知道在哪里可以找到它们。启用此复选框后,导入器将扫描活动项目目录中的所有文件一次,并记录所有内容的位置。然后,在导入过程中使用此列表,与以前的版本相比,这大大加快了作速度,在以前的版本中,可能会在多个嵌套级别中多次搜索目录。如果要从同一项目导入复合,则可以取消选中此框以节省几秒钟的时间,但前提是您确定路径是最新的。为每个项目维护一个单独的缓存。
- **recursive**: 此选项不仅导入指定的合成,还导入其子合成 (节点) 及其子合成。该算法应该是不言自明的。
- **with dags**: 导入所有合成的 `.lod00.dag` rendinsts 和 `.dag` 预制件。如果禁用 **递归** ,则它仅直接在正在导入的合成中导入几何体;否则,它还会导入子合成所需的资产。
- **with lods**: 仅当上一个复选框为 ebabled 时可用。此选项不仅允许您导入 `lod00`,还允许导入所有其他 LOD (细节级别)。请记住,这会显著减慢导入过程并增加场景的复杂性 - 仅当您需要调整小型合成中的网格而不是节点位置时,才有用。例如,如果需要重新定位几个苹果,使它们不会在合成中伸出框外,并且苹果堆是单个网格,则仍需要更新所有 LOD,而不仅仅是第一个 LOD。
如果已存在以复合命名的集合,则在导入过程中将清除该集合,并且导入将在该集合中进行。如果未找到该集合,将创建一个新集合。所有节点都放置在名为 `NODES` 的集合中;同样,如果存在具有此名称的集合,则将使用它。
如果在复合导入之前存在 `.dag`(rendinst 或 prefab)集合,则不会导入该资源。
节点类型及其名称在 **Collection Properties** 中显式设置。
对于 rendinsts,这并不重要,因为名称存储在 `.lods` 中,而不是嵌套的几何集合中。但是,对于预制件,请务必记住 – **Override Name** 将选择被覆盖的集合名称。
```{note}
不要忘记检查日志。
```
### 新的 Blend 文件结构
复合编辑器还为 `.blend` 文件引入了新的文件结构。
新方法建议使用多个场景,每个场景都按内容类型组织,而不是将所有内容都放在单个场景中。
Blender 中的场景可以被认为是 `.blend` 文件中的 `.blend` 文件”。它们彼此独立,这意味着复选框状态、导出路径和其他参数等设置对于每个场景都是唯一的。
- **COMPOSITS**. 此场景是导入所有合成的位置。
- **GAMEOBJ**. 游戏对象的集合在此处创建。这些对象不能自动读取,因此必须手动添加用于预览(以及稍后讨论的一些工具)的占位符。
- **GEOMETRY**. 这是导入所有 `.dag` 文件的位置,包括通过 dag-imports(如果场景存在)导入。
- **Scene**. 存在于新 `.blend` 文件中的默认场景。您创建的任何场景也将出现在此列表中;工具不会删除用户创建的资源。
- **TECH_STUFF**. 理想情况下,您永远不需要使用此场景。它包含随机节点的临时集合,以及将来附加组件内部任务所需的其他资源。
这些场景彼此没有链接。为了在它们之间传输资源,该插件将一个名为 **TRANSFER_COLLECTION** 的集合添加到每个场景中。此集合不是副本,而是所有场景中的同一实体。例如,您可以进入 **GEOMETRY** 场景,从必要的 rendinsts 创建节点,将它们放置在此集合中,然后切换到 **COMPOSITS** 场景以开始使用这些节点组合您的合成。
如果您想在不导入合成的情况下设置此场景结构,或者如果您不小心删除了 **TRANSFER_COLLECTION**,请不要担心。**CMP Tools > Scenes** 部分包括一个用于创建或更新场景结构的按钮,以及一个复制场景切换器。此下拉列表与标准下拉列表的不同之处在于,它可以防止意外删除或复制场景。
### 创建节点
让我们先来探索创建节点的不同方法。有几种方法:
1. **添加空对象**
您可以向场景添加 Empty 对象,在 **Entities** 面板中启用实例化,然后从下拉菜单中选择所需对象的集合。如果实例化被禁用,或者启用了但未指定集合,则节点将导出为空。
2. **拖动集合**
在 **Outliner** 中,您可以将包含所需资源的集合拖动到 3D 视图中。
```{eval-rst}
.. grid:: 1
:class-container: center-grid
.. grid-item::
:class: center-cell
:child-direction: row
:child-align: center
.. image:: _images/dag4blend_comp_ed_07.jpg
:height: 25em
:class: image-gap
.. image:: _images/dag4blend_comp_ed_08.jpg
:height: 25em
```
在这种情况下,无需启用实例化。
3. **通过Object Properties启用实例化**
添加一个 Empty 对象并通过 **Object Properties** 面板(Blender 的原生属性,而不是附加组件的原生属性)启用实例化。
第一种方法实际上是第三种方法的更灵活版本。为什么它更灵活?这将在下面解释。
### 编辑节点
要将标准节点转换为随机节点,只需单击 **Entities** 面板中的 **+** 按钮。
第二个实体最初为空,您可以通过下拉菜单、手动输入集合名称或将其从 **Outliner** 拖动到字段中来为其分配集合。
```{important}
没有防止错误选择项的保护措施,因此所有集合都可供选择。确保所选集合确实是一个节点。
```
要设置不同于默认值`1.0`的权重,请单击 **Init weight** ,然后在新生成的字段中输入所需的值。
默认情况下,所有实体都会立即显示,这可能会妨碍您的工作流程。要隐藏随机节点中的一个或多个实体,请单击其名称旁边的 **Monitor** 图标。
要删除实体,请单击 **Trash** 图标。一旦只剩下一个实体,节点将恢复到非随机状态。
### 设置节点类型和更改显示
在合成中,可以(有时有必要)指定节点类型 – 资源是 rendinst、游戏对象、复合还是预制件。导入器会自动确定类型,但在创建新节点时,您需要手动指定它。
在 Blender 的编辑器中,资源由在 Empty 对象上绘制的集合表示。因此,需要在集合的属性中设置类型。启用复合编辑器后,新面板 **Type** 将添加到 **Collection Properties**。
要指定类型,请单击相应类型旁边的 **圆圈** – 您的选择将突出显示。新创建的集合将显示 **Undefined** 作为活动值,直到设置类型为止。
在导出过程中,将记录集合的名称(不带任何后缀,如`.lodNN`, `.lods`, 或 `.002`)及其类型(如果指定)。具有实例化集合的节点,例如:
- `asset`
- `asset.lods`
- `asset.lod01`
- `asset.001`
被 exporter 等效地处理(假设它们的类型相同)。
“suffix trimming(后缀修剪)”允许您同时切换所有 LOD 的显示(默认情况下),仅切换到基础 LOD 以获得更清晰、更准确的显示,或者专注于有碰撞的 LOD 以检查 *父* 和 *子* 碰撞器之间的交集,以便正确设置破坏。
要在复合预览中隐藏网格,您可以使用监视器图标在视区的源集合中禁用其原始网格,就像在上一节中对实体所做的那样。这对于禁用碰撞网格非常有用,例如,当您想要查看具有碰撞的 LOD 但不查看碰撞体本身时,或者如果 Z 冲突在视觉上分散注意力,则暂时禁用贴花。
可以使用任何集合:
### 组合中的节点层次结构
要在节点之间建立 *parent*-*child* 关系并构建更复杂的层次结构,请使用 Blender 的标准工具。
您可以通过对象的属性为节点设置 *parent*。但是,这将导致矩阵重新计算,从而导致对象在其新的“零”点更改时在视觉上“跳跃”。
要保持节点的视觉位置,请使用 **Set Parent** 命令 – 通过按 `Ctrl`+`P` 或通过 **Object > Parent** 菜单。
要反转此过程并删除父级,同时保留矩阵,请使用 `Alt`+`P` 快捷键或选择相同的 **对象>父项** 菜单中的选项。
### 使用 Blender 的内置功能
要将节点显示为 Empty 对象,复合编辑器使用 Blender 的内置功能: 集合实例化 。因此,使用集合实例化的工具也适用于复合。
#### 快速替换节点内容
如果需要快速将多个节点的内容替换为同一资产:
1. 选择要替换的所有节点。
2. 将所需的集合分配给活动节点(此步骤和第一个步骤的顺序可以交换 - 两者的工作方式相同)。
3. 然后,将同一集合链接到所有选定的 Empty 对象。您可以通过按 `Ctrl`+`L` 并选择 **Link Instance Collection**(默认热键)来执行此作,或者通过 **Object > Link/Transfer Data** 菜单访问相同的选项(如果您的热键已自定义)。
#### Snap to Surface
请记住,对齐在这里也有效。对于将对象放置在不平坦的表面上,您可能会发现 **Project Individual Elements** 激活的 **Face** 对齐模式非常有用。这可确保所有选定节点将其枢轴点捕捉到曲面。(可选)您还可以启用旋转以匹配表面法线。
```{important}
不要将此与导出节点的 `place_type:i` 设置混淆 - 如果需要,需要在 Empty 对象的 **dagObject Properties** 中设置此特定对齐。
```
## CMP Tools
### BBOX to Node
**BBOX to Node** 工具将所有选定对象的边界框转换为选定集合的实例。此工具旨在简化室内墙壁、环境探测器、墙洞等对象的放置。
您需要自己创建必要的集合。
设置集合后,您可以将其隐藏并保持原样 - 只需为未来的游戏对象添加一些网格,并根据需要转换它们,无论是在 Object 还是 *Edit* 模式下。枢轴位置无关紧要;替换将按预期工作。只需确保在转换之前监视边界框(您可以在 **Object Properties** 中启用其显示)。
下面是一个极端的例子(在实践中很少需要这样的旋转):
为清楚起见,建议将带有`gi_black`的 1 米立方体添加到未来游戏对象的集合中。这样可以更轻松地将其临时转换回网格以进行进一步调整。
### To Mesh
**To Mesh** 工具将选定的复合节点(集合实例)转换为实际的几何体。
转换后,几何体可以导出为任何其他格式 - 现在它只是一个网格。例如,您可以通过 Alembic/FBX 将合成传输到 Houdini,其中`.dag`导出已存在,但尚不支持导入。
### Explode
想要直接在原位编辑子复合,例如在表格上移动板或添加另一个板?没关系!**Explode** 工具暂时反汇编选定的复合实例,并将其组件作为原始节点的 *子* 对象放置,该节点现在变为 “空”。然后,您可以进行更改 - 调整变换、添加或删除对象等。
可以通过单击 **Revert** 将更改还原到原始状态,也可以使用 **Rebuild** 应用更改,这将替换原始集合。不要忘记通过导出修改后的子合成来保存这些更改。
但是,重组不是强制性的 – 拆解的组合可以毫无问题地导出为具有多个子节点的空节点。如果需要,您可以使用 **Clear Parent and keep transformation** 将它们分开,并完全删除“空”节点。当您需要将多级随机合成替换为其状态之一时,这非常有用 - 将其拆解(您可以一次拆解多个嵌套级别)并删除不必要的部分。
**Explode** 工具还允许您拆解 rendinst 和 prefabs 以更改其几何图形,这有时非常有用。如果源是包含所有 LOD 的目录,则反汇编的 rendinst 将略有不同:
每个 LOD 都将绑定到其自己的 “空” 节点。
要重新组合它,您需要选择顶级空,而不是带有 LOD 编号的那个。与反汇编的合成不同,反汇编网格将导致导出错误,因此请确保在导出之前将节点恢复到其原始状态或应用更改。
```{important}
一个已知的限制是这种类型的编辑会留下 “垃圾” 索引,因为它是通过创建副本来实现的,并且 Blender 不允许相同类型的两个对象具有相同的名称。此外,**Explode** 目前无法在反汇编的集合中保留 *parent*-*child* 关系,但它确实保留了相对于复合的“零”点的正确坐标。如果层次结构很重要,则需要在使用 **Rebuild** 后手动还原它。
```
## CMP Export
**CMP Export** 部分非常简单:指定应导出复合的目录路径,以及表示要导出的复合的集合。
### 参数
导出参数(如随机偏移)在 Empty 对象的 **Object Properties** 中指定。这些参数不会显示在视区中。在导入过程中,仅应用初始状态(值的第一部分),但不会应用任何随机偏差(逗号后的值)。
如果一个节点至少指定了一个 random field,则不会保存其变换矩阵。如果导入的节点同时具有 matrix 和 random 字段,则将忽略 random 参数,并记录相应的通知。
### 复合编辑器的限制
- **不包括不支持include**
目前,不支持 include。在导入过程中,将忽略带有 `include` 指令的行,这可能会导致一些数据丢失。这将在日志中记录下来。
- **Blender的限制**
Blender 最多支持 7 个嵌套级别。多级合成可能会遇到性能问题,并且可能无法正确显示 – 从第 8 级嵌套开始,将不会渲染内容。但是,仍然可以导入和导出。
例如,node-rendinst 表示一个嵌套级别。具有多个 rendinst 的随机节点表示两个级别。具有这些随机节点的子合成将是三个级别,依此类推。此问题主要在导入具有内部的建筑物时出现,例如在基于 daNetGame 的游戏中,其中`indoor_stuff`包含许多具有随机性的嵌套合成 - 例如随机橱柜,其中对象放置在架子上,每个对象都有随机偏移。
- **轴不匹配**
在 Blender 中,Z 轴向上,而在 Dagor 中,Y 轴向上。虽然矩阵调整是自动处理的,可以防止场景倾斜,但重要的是要记住,`offset_y:p2`指的是上/下移动,尽管名称如此。相同的逻辑也适用于旋转和缩放。
- **随机偏移参数**
目前,随机偏移参数不会自动显示在视区中。在导入过程中,插件会设置初始偏移量,但如果您添加或修改随机参数,则需要手动调整节点的位置。