TiXL 中 Execute 操作符完全指南:命令序列分组执行与图形上下文管理
【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3
Execute 是 TiXL 开源实时动态图形软件中Lib.flow命名空间下的核心流程控制操作符,用于执行一串绘制命令并在完成后恢复图形上下文,实现图形的分组、命名以及子图的激活与停用。本文将以 Execute.md 官方文档 为骨架,结合Execute的底层 C# 实现与Lib.flow家族相关操作符,完整讲解其参数、输出、执行原理、与 Group 的取舍及实际应用场景,帮助你掌握 TiXL 图编排中的命令执行机制。
Execute 是什么
在 TiXL 中,图形渲染本质上是无数个"命令"(Command)在图网络中按连接关系依次求值的过程。Execute的作用非常朴素但极其常用:
执行一系列绘制操作,然后在结束后恢复图形上下文(graphics context)。你可以用它来分组,或者激活/停用图形中的部分内容。
它的核心价值在于两点:
- 上下文隔离:进入
Execute时可以先执行准备动作(PrepareAction),执行完所有子命令后再执行恢复动作(RestoreAction),从而保证子图对全局状态(如颜色、变换矩阵等)的修改不会泄漏到图形网络的其它部分。 - 图结构组织:由于
Execute本身不产生任何绘制效果,它天然适合作为"容器"节点,把一段有逻辑关联的子图收纳在一起,配合实例命名形成清晰的图结构。
在 Lib.flow 命名空间文档 中,Execute 被列为流程控制类操作符的一员,与ExecRepeatedly、ExecuteOnce、Loop、Switch、TimeClip等共同构成 TiXL 的图执行控制体系。
输入参数
Execute的输入参数由官方文档定义为两张表,这里结合源码逐一展开说明。
| 名称(相关性 & 类型) | 说明 |
|---|---|
| Command(Command Required) | 要执行的绘制命令序列,这是一个多输入插槽(MultiInputSlot),可以同时连接多条命令分支 |
| IsEnabled(Boolean) | 是否启用该 Execute 的执行;为false时整段子图被跳过,可用于激活/停用部分图形 |
Command:多输入的命令收集机制
从源码 Operators/Lib/Symbols/flow/Execute.cs 可以看到,Command被声明为MultiInputSlot<Command>,这意味着它支持同时接入多条命令分支,TiXL 会在求值前将各分支收集为命令列表:
[Input(Guid = "5D73EBE6-9AA0-471A-AE6B-3F5BFD5A0F9C")] public readonly MultiInputSlot<Command> Command = new();多输入插槽的收集逻辑定义在 Core/Operator/Slots/MultiInputSlot.cs:它会遍历所有输入连接,并把嵌套的多输入递归展开后合入CollectedInputs列表。因此你可以把任意数量的子绘制分支接入同一个Execute,它们会按照连接顺序被依次执行。
IsEnabled:整段子图的开关
IsEnabled是布尔型输入(Execute.cs)。当它为false时,Execute会跳过整段命令的执行,相当于"停用"了该分组的所有子图;当它为true时正常执行。这为动态开关某段视觉效果提供了最直接的挂载点——你可以把它接到任何布尔表达式、Midi 输入、键盘事件或Once的触发信号上。
输出
| 名称 | 类型 |
|---|---|
| Output | T3.Core.DataTypes.Command |
Execute的输出是Slot<Command>,即它自身也表现为一个命令节点(Execute.cs),可以继续向下游的其它命令类操作符传递,从而形成命令流的链式结构。其完整类型为T3.Core.DataTypes.Command。
源码级原理:Prepare → Execute → Restore 三阶段
虽然官方文档对Execute的功能描述只有一句话,但其底层实现非常清晰,位于 Operators/Lib/Symbols/flow/Execute.cs。每次求值(Update)时会执行如下流程:
private void Update(EvaluationContext context) { var commands = Command.CollectedInputs; if (IsEnabled.GetValue(context)) { // 阶段一:准备工作(如有需要) for (int i = 0; i < commands.Count; i++) { commands[i].Value?.PrepareAction?.Invoke(context); } // 阶段二:依次执行各命令 for (int i = 0; i < commands.Count; i++) { commands[i].GetValue(context); } // 阶段三:执行完毕后的清理/恢复 for (int i = 0; i < commands.Count; i++) { commands[i].Value?.RestoreAction?.Invoke(context); } } Command.DirtyFlag.Clear(); }三个阶段分别承担不同职责:
- Prepare(准备):遍历所有已收集的命令,调用各自的
PrepareAction,通常用于在绘制前压栈保存当前图形上下文(如颜色、变换)。 - Execute(执行):逐一调用
GetValue(context)真正触发子图求值,产生实际绘制。 - Restore(恢复):调用
RestoreAction,将图形上下文弹栈还原到进入Execute之前的状态,保证状态不泄漏。
最后一个Command.DirtyFlag.Clear()用于清除脏标记,避免下一帧重复求值,这是 TiXL 增量求值机制的关键一环。
Command 数据类型的构成
Execute输入输出所使用的Command类型定义于 Core/DataTypes/Command.cs,它本身只是一个携带两个回调的轻量容器:
public class Command { public Action<EvaluationContext> PrepareAction { get; init; } public Action<EvaluationContext> RestoreAction { get; set; } }也就是说,任何需要被Execute调度的子图,本质上都注册了进入时的准备回调与退出时的恢复回调。理解这一点,就理解了"执行命令序列并恢复图形上下文"这一文档描述的底层含义。
与 Group 的对比:何时用 Execute,何时用 Group
官方文档明确指出:Execute的替代方案是Group,而Group额外拥有平移(translation)和多个输入连接能力。
从源码 Operators/Lib/Symbols/render/transform/Group.cs 可以看出,Group在内部执行了与Execute几乎相同的命令调度循环(Prepare → GetValue → Restore),但在此基础上还做了大量额外工作:
- 实现了
ITransformable接口,提供Translation / Rotation / Scale / UniformScale四个变换输入,会构建变换矩阵并乘入context.ObjectToWorld; - 提供Color输入(与
ForegroundColor相乘)与ForceColorUpdate强制颜色刷新; - 提供EnableProfiling输入,可配合
DebugDataRecording对子图更新耗时进行性能剖析。
因此使用建议非常明确:
| 需求 | 推荐节点 |
|---|---|
| 仅需要命令序列分组、命名、开/关控制 | Execute(更轻量) |
| 需要位移、旋转、缩放或颜色叠加 | Group |
| 需要多路输入连接做进一步组织 | Group或直接接多输入到 Execute 的 Command |
在 Lib.flow 家族中的定位
Execute是流程控制的基础原子操作符,其它 flow 操作符往往在它之上叠加了"执行时机/次数"的控制语义,可视为同源变体,便于举一反三:
- ExecuteOnce(Operators/Lib/Symbols/flow/ExecuteOnce.cs):仅当
Trigger输入为脏时才执行一次子图,适用于初始化缓冲区或重置状态;执行逻辑与 Execute 完全同构(同样是 Prepare → GetValue → Restore 三段循环),只是外层多了一层Trigger.DirtyFlag.IsDirty判断。 - Loop(Operators/Lib/Symbols/flow/Loop.cs):按
Count重复执行子图,并在context.FloatVariables/IntVariables中写入索引与进度变量,用于迭代式绘制。 - ExecRepeatedly:控制子图的执行频率;Switch:在多个已连接子图间切换("剪切"场景);BlendScenes:用浮点索引在绘制场景间做 Alpha 混合;TimeClip:在时间轴 DopeView 中创建时间片段条。
从 Lib.flow 命名空间文档 可以看到完整的操作符清单及一句话功能说明,可作为选择流程控制节点时的速查表。
实战建议
结合文档描述与源码实现,以下是Execute的典型用法与注意事项:
- 命名分组:因为
Execute本身不产生绘制,官方文档建议"把它插入图网络并按下 Enter 设置实例名称",用命名来表达子图语义。这相当于在图中建立可读的"代码注释块"。 - 激活/停用局部图形:将
IsEnabled接到布尔信号源(键盘、Midi、UI 开关或逻辑运算结果),即可在不拆线的情况下快速启用或禁用一段效果。 - 上下文安全:得益于 Prepare/Restore 机制,被
Execute包裹的子图对内修改的状态会在退出时还原,避免污染后续绘制——这是它与直接连线最大的行为差异。 - 需要变换时换用 Group:一旦子图需要位移/旋转/缩放/统一颜色,应改用 Group,其参数与行为差异参见上文对比表。
总结
Execute是 TiXL 图编排中最基础也最常用的流程控制操作符:它通过"准备—执行—恢复"三阶段循环(源码见 Operators/Lib/Symbols/flow/Execute.cs)调度一串Command(Core/DataTypes/Command.cs)并在结束后还原图形上下文。它既可以作为语义化的命名容器整理图结构,也可以通过IsEnabled实现子图动态开关;当需要变换能力时,则应选择功能更丰富的Group。理解Execute的执行模型,也就掌握了ExecuteOnce、Loop、Switch等整个Lib.flow命令调度家族的共同底层逻辑。
【免费下载链接】t3TiXL is an open source software to create realtime motion graphics.项目地址: https://gitcode.com/GitHub_Trending/t3/t3
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考