TiXL 上下文变量读取算子 GetVec3Var 完全指南:原理、用法与源码剖析
2026/9/19 23:11:08 网站建设 项目流程
  • 音视频
  • 图形学
  • 桌面应用

【免费下载链接】t3

TiXL is an open source software to create realtime motion graphics.

项目地址:https://gitcode.com/GitHub_Trending/t3/t3
点击查看免费下载

本篇技术指南围绕 TiXL(开源实时动态图形创作软件)算子库Lib.flow.context中的GetVec3Var算子展开,讲解如何在节点图中按名称读取存储在求值上下文中的三维向量变量,并深入剖析其源码实现、下拉选择机制、回退(Fallback)逻辑以及与配套写入算子 SetVec3Var 的协作方式。读完本文,你将掌握上下文变量的完整读写链路,能够用它在 TiXL 中构建跨算子、按需作用域的矢量数据传递方案。

关联文档:.help/docs/operators/lib/flow/context/GetVec3Var.md

一、算子概览:GetVec3Var 在算子库中的定位

GetVec3Var 属于Lib.flow.context(流程控制 / 上下文)算子族,位于运算符库目录Operators/Lib/Symbols/flow/context/下。该算子族的共同特点是围绕**求值上下文(EvaluationContext)**存取各类变量:

  • 读取类:GetBoolVar、GetFloatVar、GetIntVar、GetStringVar、GetMatrixVar、GetVec3Var、GetObjectVar、GetForegroundColor、GetPosition
  • 写入类:SetBoolVar、SetFloatVar、SetIntVar、SetStringVar、SetMatrixVar、SetVec3Var、SetObjectVar、SetRequestedResolutionCmd
  • 执行类:ExecuteRawBufferUpdate

从 上下文算子族 README 可以看到,GetVec3Var 与 GetFloatVar 等读取算子是同一设计模式的类型化变体:写入算子把值存进上下文,读取算子按名字取回。GetVec3Var 专门处理System.Numerics.Vector3类型的三维向量,适合传递位置、方向、缩放、速度等空间数据。

二、接口定义:输入参数与输出

依据官方文档,GetVec3Var 的完整接口如下:

输入参数

名称(相关性 & 类型)说明
VariableName(String)要读取的上下文变量名,与 SetVec3Var 写入时使用的名字一一对应
FallbackDefault(Vector3)当指定变量不存在、尚未被写入或类型不匹配时返回的兜底值

输出

名称类型
ResultSystem.Numerics.Vector3

官方默认值(来自算子定义文件)

在算子定义文件 GetVec3Var.t3 中记录了两个输入的默认值:

{ "Id": "f21de2e1-6af8-4651-90a0-6c662bbb23af", "Inputs": [ { "Id": "5cce784c-020a-4e51-881b-edd48846b0fc", "DefaultValue": { "X": 0.0, "Y": 0.0, "Z": 0.0 } }, { "Id": "d8a9d923-232f-4cd4-9e24-fadbf40fe1d1", "DefaultValue": "pos" } ] }
  • VariableName 默认值为"pos":暗示最常见的用法是读取名为pos(position,位置)的变量。
  • FallbackDefault 默认值为(0, 0, 0):即原点,保证即使变量缺失,输出也是合法的三维向量,不会中断求值。

三、核心工作原理:一次读取的三步判定

GetVec3Var 的实际逻辑非常简单清晰,完整实现位于 GetVec3Var.cs:

private void Update(EvaluationContext context) { if (VariableName.DirtyFlag.IsDirty && !VariableName.HasInputConnections) _contextVariableNames = context.ObjectVariables.Keys.ToList(); var variableName = VariableName.GetValue(context); if (variableName != null && context.ObjectVariables.TryGetValue(variableName, out var value) && value is Vector3 vec3) { Result.Value = vec3; } else { Result.Value = FallbackDefault.GetValue(context); } }

其求值流程可概括为三步判定:

  1. 取变量名:通过VariableName.GetValue(context)获得当前要读取的变量名字符串。
  2. 查字典:在context.ObjectVariables.TryGetValue(variableName, out var value)中查找同名条目。
  3. 类型校验 + 输出:只有当查找成功存储的对象是Vector3类型时,Result才输出该值;否则一律输出FallbackDefault的值。

这段代码揭示了两个关键设计点:

  • 类型安全ObjectVariablesDictionary<string, object>(见下文),存储的是object。GetVec3Var 用value is Vector3 vec3做运行时类型检查,确保同名但不同类型的变量(例如名为pos却存了float)不会被误读,而是安全落入回退分支。
  • 回退而非报错:变量不存在时算子不会报错或输出NaN,而是输出可预测的兜底值,这让它在首帧求值、变量尚未写入时依然行为稳定。

底层存储:EvaluationContext.ObjectVariables

变量真正的存放位置是求值上下文 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(); /// <summary> /// Used to store objects different from float and int /// </summary> public Dictionary<string, object> ObjectVariables { get; } = new(); /// <summary> /// Used to store string vars /// </summary> public Dictionary<string, string> StringVariables { get; } = new(); #endregion

从源码结构可以看出,上下文为不同基础类型准备了独立的字典:BoolVariablesIntVariablesFloatVariablesStringVariables,而ObjectVariables专门用于存放 float、int 之外的对象类型——Vector3正是通过它存取的。GetVec3Var / SetVec3Var 操作的就是这个ObjectVariables字典。

值得注意的是,EvaluationContext.Reset() 会在重置时清空ObjectVariables(以及其余变量字典),说明上下文变量是逐帧求值时的临时数据,生命周期与单次求值/播放状态绑定,而非持久化存储。

四、与 SetVec3Var 配合:写入-读取的完整闭环

要理解 GetVec3Var,必须看它的镜像算子 SetVec3Var,两者通过同一个ObjectVariables字典协作。SetVec3Var 的实现位于 SetVec3Var.cs:

private void Update(EvaluationContext context) { var name = VariableName.GetValue(context); var newValue = Vec3Value.GetValue(context); if (string.IsNullOrEmpty(name)) { Log.Warning($"Can't set variable with invalid name {name}", this); return; } if (SubGraph.HasInputConnections) { var hadPreviousValue = context.ObjectVariables.TryGetValue(name, out var previous); context.ObjectVariables[name] = newValue; SubGraph.GetValue(context); if (hadPreviousValue) { context.ObjectVariables[name] = previous; } } else { context.ObjectVariables[name] = newValue; } }

这里有两种写入模式:

  • 全局写入(无子图连接):直接把Vec3Value写入context.ObjectVariables[name],之后图中任何位置的 GetVec3Var 都能读到。
  • 作用域写入(SubGraph 有连接):先保存旧值,写入新值,求值SubGraph,再恢复旧值。这意味着只有子图内部的算子能读到临时值,子图外的读取不受影响——这是 TiXL 实现“局部变量作用域”的惯用手段。

实战示例:位置变量传递

一个典型用法是:用 SetVec3Var 把某个算子的位置结果写入名为pos的变量,再用 GetVec3Var(保持默认变量名"pos")在图的另一处读取,避免为传递一个向量而拉长长的连线:

  1. 将 SetVec3Var 的VariableName设为posVec3Value连接任意产生Vector3的输出(如 GetPosition 或变换算子的位置输出)。
  2. 在需要该位置的算子前放置 GetVec3Var,VariableName保持默认pos
  3. GetVec3Var 的Result即可作为普通Vector3输入接入下游。
  4. 若想让变量仅在局部生效,可把 SetVec3Var 的SubGraph输入连接到目标算子树,GetVec3Var 放在该子树内部。

当读取到的变量在某一帧尚未写入时,FallbackDefault(默认(0,0,0))会保证输出平滑可用,防止首帧闪烁或空引用。

五、编辑器体验:下拉选择与可视化

自定义下拉框(CustomDropdown)

GetVec3Var 实现了ICustomDropdownHolder接口(GetVec3Var.cs),在编辑器中表现为一个变量名下拉框,可以直接从当前上下文中已有的变量名里点选,而无需手敲字符串:

string ICustomDropdownHolder.GetValueForInput(Guid inputId) { return VariableName.Value; } IEnumerable<string> ICustomDropdownHolder.GetOptionsForInput(Guid inputId) { return _contextVariableNames; } void ICustomDropdownHolder.HandleResultForInput(Guid inputId, string selected, bool isAListItem) { ... // Update the list of available variables when dropdown is shown VariableName.DirtyFlag.Invalidate(); VariableName.SetTypedInputValue(selected); }

在界面定义文件 GetVec3Var.t3ui 中,VariableName输入被标记为"Usage": "CustomDropdown",确认了该输入在编辑器中使用自定义下拉控件渲染。

下拉列表的数据来自缓存字段_contextVariableNames,其刷新逻辑在Update方法开头:

if (VariableName.DirtyFlag.IsDirty && !VariableName.HasInputConnections) _contextVariableNames = context.ObjectVariables.Keys.ToList();

只有当 VariableName 变脏(被改动)且没有被外部连线驱动时,才会重新枚举ObjectVariables的键来刷新候选列表;下拉被打开时通过VariableName.DirtyFlag.Invalidate()主动触发一次刷新。这一设计避免了每帧都枚举字典键的开销,也解释了为何动态新增的变量要等列表刷新后才能在下拉中出现。

自定义节点外观

编辑器 UI 层为 GetVec3Var 提供了专用绘制逻辑 GetVec3VarUi.cs,它:

  • 在节点上直接显示当前变量名和实时的Result值(WidgetElements.DrawSmallValue),方便可视化调试;
  • 鼠标悬停时,绘制连接到同名 Set 算子的参考线(OpUi.DrawVariableReferences),并通过 Guid 精确匹配SetVec3Varfdad077d-e919-4f40-a154-36e86245a585)及其VariableName输入(0edf7837-4555-4e62-902f-930abf72e8b8),让读/写两端在画布上互相可追踪;
  • 返回PreventInputLabels | PreventOpenSubGraph等标志,表示该节点使用自定义渲染而非默认输入标签样式。

六、输出时机:Animated 脏标记

GetVec3Var 的输出槽定义如下(GetVec3Var.cs):

[Output(Guid = "F26C6DFE-AFC5-4824-9580-92FF5CD8F086", DirtyFlagTrigger = DirtyFlagTrigger.Animated)] public readonly Slot<Vector3> Result = new();

DirtyFlagTrigger.Animated表明该输出属于动画驱动型:其求值时机跟随动画/时间刷新节奏,而非仅在输入变化时更新。这与上下文变量可能被逐帧改写的特性匹配——读取端必须紧跟写入端的时间步进,才能拿到最新值。构造器中Result.UpdateAction += Update将上文分析的Update方法注册为输出刷新动作,Update每次被调用时都重新走一遍“查找 → 校验 → 回退”流程。

七、边界情况与注意事项

结合源码可总结出以下使用要点与陷阱:

场景行为
变量存在且为 Vector3输出变量值
变量存在但类型不是 Vector3输出 FallbackDefault(value is Vector3校验失败)
变量不存在 / 尚未写入输出 FallbackDefault,不报错
VariableName 为空字符串查找必然失败,输出 FallbackDefault
SetVec3Var 收到空变量名写入端直接Log.Warning并跳过写入
上下文被 ResetObjectVariables 被清空,GetVec3Var 全部回退到默认值

此外,从 EvaluationContext.Reset() 的实现可以看到ObjectVariables.Clear()被调用,因此不要把上下文变量当作跨播放会话的持久数据;跨帧、跨会话的稳定数据应使用 TiXL 的其他持久化机制。

八、小结

GetVec3Var 是 TiXL 上下文变量体系中面向Vector3的读取算子:它通过EvaluationContext.ObjectVariables字典按名取值,自带类型校验与FallbackDefault回退,与 SetVec3Var 构成读写闭环并支持子图作用域,同时在编辑器中提供下拉选择、实时数值显示与读写两端连线追踪的完整体验。

深入阅读建议:

  • 算子实现:GetVec3Var.cs
  • 配套写入算子:SetVec3Var.cs
  • 上下文与变量字典:EvaluationContext.cs
  • 编辑器界面:GetVec3VarUi.cs
  • 同族算子索引:Lib.flow.context README
  • 官方算子文档:GetVec3Var.md
  • 音视频
  • 图形学
  • 桌面应用

【免费下载链接】t3

TiXL is an open source software to create realtime motion graphics.

项目地址:https://gitcode.com/GitHub_Trending/t3/t3
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询