- 音视频
- 图形学
- 桌面应用
【免费下载链接】t3
TiXL is an open source software to create realtime motion graphics.
本篇技术指南围绕 TiXL(实时动态图形创作软件)中Lib.flow.context库的SetIntVar操作符展开,讲解如何将整数变量写入求值上下文(EvaluationContext),并由下游(图左侧)的 GetIntVar 读取复用,实现跨算子传递状态、VJ 触发信号分发等实战场景。阅读本文后,你将掌握 SetIntVar 的全部输入参数、底层字典机制、SubGraph 作用域与值恢复语义,并能结合源码写出可复用、可调试的上下文变量方案。
一、SetIntVar 是什么
SetIntVar 是 TiXL 操作符库 Lib.flow.context 中的一员,其官方描述为:
Sets or overwrites an int variable that can be retrieved by [GetIntVar] further down (left in) the graph.
即:设置或覆盖一个整数变量,该变量可以被图中更靠后(左侧)的 GetIntVar 读取。同一分类下还有SetFloatVar、SetBoolVar、SetStringVar、SetObjectVar、SetVec3Var、SetMatrixVar等兄弟算子,构成了 TiXL 的“上下文变量”家族——它们共享同一个EvaluationContext上按类型划分的字典存储。
核心定位:SetIntVar 是一种作用域受限的状态传递机制,它不像全局变量那样跨项目任意可见,而是以当前求值上下文(一次图求值的运行环境)为生命周期,天然适合在子图内传递参数、在中途改写数值后再恢复。
二、输入参数与输出
2.1 输入参数总览
| 名称(类型) | 说明 |
|---|---|
| SubGraph(Command) | 可选子图;接入后 SetIntVar 会先写入变量、执行子图、再按规则恢复/清理变量 |
| VariableName(String) | 变量名(键),空字符串会被拒绝并触发警告 |
| Value(Int32) | 要写入的整数 |
| LogLevel(Int32) | 日志级别,映射到内部枚举,控制写入/变更时是否输出日志 |
| ClearAfterExecution(Boolean) | 仅当子图执行后变量原本不存在时有效:为 true 则执行后移除该变量,为 false 则保留 |
各输入在符号定义文件 SetIntVar.t3 中的默认值如下:
| 输入 | 默认值 |
|---|---|
| VariableName | "i" |
| Value | 0 |
| LogLevel | 0(即 None) |
| ClearAfterExecution | false |
| SubGraph | null(未连接) |
2.2 输出
| 名称 | 类型 |
|---|---|
| Output | T3.Core.DataTypes.Command |
Output 类型是Command,意味着 SetIntVar 本身是一个命令型算子,可以串联到渲染/执行链中,其副作用(写变量)发生在求值过程中。
三、底层存储:EvaluationContext.IntVariables
SetIntVar 写入的并非全局静态变量,而是求值上下文中的字典。在 EvaluationContext.cs 中可以看到上下文变量区域:
#region context variables public Dictionary<string, bool> BoolVariables { get; } = new(); public Dictionary<string, int> IntVariables { get; } = new(); public Dictionary<string, float> FloatVariables { get; } = new(); public Dictionary<string, object> ObjectVariables { get; } = new(); public Dictionary<string, string> StringVariables { get; } = new(); #endregion关键语义:
- 整型变量存放在
Dictionary<string, int> IntVariables中,键为变量名字符串,值为 32 位整数; - 该字典是只读属性、可变内容,Set 类算子通过索引器
context.IntVariables[name] = newValue写入; - 上下文在每次求值前会执行
Reset(),其中包含IntVariables.Clear()(见 EvaluationContext.cs),因此变量不会跨帧/跨求值会话残留——每帧重新构建,这正是它适合做“瞬时触发信号”而非“持久配置”的原因。
四、执行逻辑逐行拆解
SetIntVar 的核心实现位于 SetIntVar.cs,其Update方法完整逻辑如下:
private void Update(EvaluationContext context) { var name = VariableName.GetValue(context); var newValue = Value.GetValue(context); var clearAfterExecution = ClearAfterExecution.GetValue(context); var logLevel = LogLevel.GetEnumValue<LogLevels>(context); if (string.IsNullOrEmpty(name)) { if((int)logLevel >= (int)LogLevels.Warnings) Log.Warning($"Can't set variable with invalid name {name}", this); return; } if (SubGraph.HasInputConnections) { var hadPreviousValue = context.IntVariables.TryGetValue(name, out var previous); context.IntVariables[name] = newValue; SubGraph.GetValue(context); if (hadPreviousValue) { if ((int)logLevel >= (int)LogLevels.Changes) Log.Debug($"Changing {name} from {previous} -> {newValue}", this); context.IntVariables[name] = previous; } else { if ((int)logLevel >= (int)LogLevels.AllUpdates) Log.Debug($"Setting {name} to {newValue}", this); if(!clearAfterExecution) context.IntVariables.Remove(name); } } else { context.IntVariables[name] = newValue; } }可以将其拆分为三个分支场景:
4.1 空变量名:拒绝写入
当VariableName为空字符串或 null 时,直接返回,不做任何写入;若LogLevel不低于Warnings,则输出Log.Warning("Can't set variable with invalid name ...")。这是对键缺失的保护,避免在字典中产生空键污染。
4.2 未连接 SubGraph:直接持久写入
未连接 SubGraph 时,行为最简单:
context.IntVariables[name] = newValue;变量被设置,并一直保留到上下文被Reset()清除(即当前求值会话结束)。
4.3 连接 SubGraph:临时覆盖 + 自动恢复
连接 SubGraph 后,SetIntVar 变成“局部作用域写入器”:
- 先通过
TryGetValue记录该变量是否已存在及旧值; - 写入新值;
- 执行
SubGraph.GetValue(context),此时子图内的下游算子(包括 GetIntVar)读到的是新值; - 子图执行完毕后:
- 若变量原本就存在(
hadPreviousValue == true):恢复为旧值,并在 LogLevel ≥ Changes 时输出Log.Debug($"Changing {name} from {previous} -> {newValue}"); - 若变量原本不存在:当
ClearAfterExecution == false时移除该变量(恢复“不存在”状态);当ClearAfterExecution == true时保留新值;LogLevel ≥ AllUpdates 时输出Log.Debug($"Setting {name} to {newValue}")。
- 若变量原本就存在(
从源码可见,ClearAfterExecution的名字与实际行为存在微妙关系:它实际控制的是“原本不存在的变量,在子图执行后是移除还是保留”,而“原本存在的变量”无论如何都会被恢复为旧值。理解这一点是正确使用该参数的关键。
五、LogLevel 日志级别
LogLevel 输入是InputSlot<int>,通过MappedType = typeof(LogLevels)映射为枚举,编辑器会将其显示为下拉选项。枚举定义在 SetIntVar.cs:
private enum LogLevels { None, // 0:不输出任何日志 Warnings, // 1:仅输出警告(如空变量名) Changes, // 2:额外输出变量值变更日志(原值 -> 新值) AllUpdates, // 3:输出所有写入/设置日志 }日志通过 TiXL 的Log.Debug/Log.Warning输出到统一日志系统(见 Logging 相关实现),可用于调试“变量是否被正确写入、何时被覆盖”。
六、与 GetIntVar 的配套使用
6.1 读取端行为
GetIntVar.cs 是 SetIntVar 的标准配套读取算子:
- 输入
VariableName、FallbackValue(变量不存在时返回的兜底值)、LogUpdates; - 输出
Result(Int32),带DirtyFlagTrigger.Animated标记; - 当字典中不存在该变量时,输出
FallbackValue,并在 LogUpdates ≥ Warnings 时输出Log.Warning($"Can't read undefined int {variableName}.")(每个算子实例只告警一次,由_complainedOnce控制,避免刷屏)。
6.2 变量名下拉提示
GetIntVar 实现了ICustomDropdownHolder接口(GetIntVar.cs):在编辑器中打开 VariableName 输入的下拉时,会调用GetOptionsForInput刷新context.IntVariables.Keys列表,直接列出当前上下文中所有已写入的整型变量名,方便可视化选择,避免手拼字符串出错。这一点与 SetIntVar 的写入端形成闭环:写端定义键,读端自动发现键。
6.3 编辑器可视化
SetIntVar 还带有自定义节点 UI,实现在 SetIntVarUi.cs:
- 节点标题优先使用符号实例名,否则显示为
Set int: <变量名>; - 节点主体显示当前 Value 的整数值;
- 鼠标悬停时通过
OpUi.DrawVariableReferences绘制变量引用连线,把 SetIntVar 与其对应的 GetIntVar 实例(按 GUID470db771-...定位 GetIntVar、d7662b65-...定位其 VariableName 输入)在画布上视觉关联起来,帮助用户一眼看清“谁写、谁读”。
七、实战示例:VJ 触发信号分发
仓库自带的 VJ 示例 SetVJVariables.t3 展示了 SetIntVar 的真实用法。该符号内使用了多个SetIntVar实例,例如:
{ "Id": "ac317f6d-2666-4b58-8ee2-28b48a21cea7"/*SetIntVar*/, "SymbolId": "7953f704-ebee-498b-8bdd-a2c201dfe278", "InputValues": [ { "Id": "bfd87742-aaf5-4fa8-b714-fd275de1c60d"/*VariableName*/, "Type": "System.String", "Value": "__TriggerBass" } ], "Outputs": [] }在这个场景中,MIDI 输入 / AudioReaction 检测等信号源经过 BoolToInt、FloatToInt、Sum、Add 等算子转换为整数后,通过 SetIntVar 写入__Trigger、__TriggerBass等以下划线开头的“瞬时触发”变量;下游的视觉算子再用 GetIntVar 读取这些变量驱动动画切换。由于上下文每帧重置,这类触发变量天然是“当帧有效”,不会跨帧粘连,非常适合做节拍触发、场景切换等 VJ 场景。同理,SetSpeedFactorA/B这类“持续状态”变量则使用 SetFloatVar 写入,配合 SetTime 等算子保持跨帧效果。
八、使用注意事项与最佳实践
- 生命周期是“一帧”:
IntVariables在每次上下文Reset()时被清空(EvaluationContext.cs)。若需要跨帧保持状态,应使用 TiXL 的算子实例字段或时间相关机制,而非依赖上下文变量。 - 变量名唯一且非空:同名的后续写入会覆盖前值;空名会被直接拒绝并产生警告。
- SubGraph 连接即“作用域化”:需要临时覆盖某变量、执行一段逻辑后再还原时,把逻辑放进 SubGraph 即可,无需手动保存/恢复——SetIntVar 帮你做了。注意区分“原本存在”(总会恢复旧值)与“原本不存在”(由 ClearAfterExecution 决定保留或移除)两种恢复语义。
- 善用 FallbackValue 与 LogUpdates:在 GetIntVar 端设置合理的兜底值,避免变量未写入时读到脏数据;调试期把 LogUpdates / LogLevel 调到
AllUpdates,可在日志中看到完整的写入与读取轨迹。 - 编辑器悬停连线:在画布上将鼠标悬停在 SetIntVar 上,可查看它关联的读取者,便于排查“写了不少、读不到”的拼写问题。
九、相关资源
- 操作符文档入口:Lib.flow.context 索引
- 读取端文档:GetIntVar
- 实现源码:SetIntVar.cs、GetIntVar.cs
- 符号定义与默认值:SetIntVar.t3
- 上下文存储载体:EvaluationContext.cs
- 编辑器自定义 UI:SetIntVarUi.cs
- 实战示例:SetVJVariables.t3
通过将 SetIntVar(写入端)、GetIntVar(读取端)与 EvaluationContext 的按类型字典结合使用,你可以在 TiXL 的算子图内以声明式、可调试、作用域可控的方式传递整数状态,为复杂实时动态图形系统搭建清晰的数据流骨架。
- 音视频
- 图形学
- 桌面应用
【免费下载链接】t3
TiXL is an open source software to create realtime motion graphics.
相关推荐
TiXL 图计算核心:深入理解 EvaluationContext(求值上下文)与每帧数据流
TiXL 图计算核心:深入理解 EvaluationContext(求值上下文)与每帧数据流 TiXL 是用于实时动态图形(realtime motion gr
音视频图形学桌面应用t3(TiXL)GetFloatVar 操作符详解:在节点图中读取评估上下文的浮点变量
t3(TiXL)GetFloatVar 操作符详解:在节点图中读取评估上下文的浮点变量 本文以 t3(TiXL 实时动态图形)操作符库 Lib.flow.con
音视频图形学桌面应用TiXL (t3) 节点图中的 GetIntVar 算子:从 EvaluationContext 读取 Int 变量并配合 SetIntVar 完成跨节点状态传递
TiXL t3 节点图中的 GetIntVar 算子:从 EvaluationContext 读取 Int 变量并配合 SetIntVar 完成跨节点状态传递
音视频图形学桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考