- 音视频
- 图形学
- 桌面应用
【免费下载链接】t3
TiXL is an open source software to create realtime motion graphics.
HasValueChanged 是 TiXL 运算符库Lib.numbers.float.logic中的一个数值逻辑运算符,用于检测输入数值相对上一次采样是否发生了超过指定阈值的"变化",并以布尔值输出结果,同时附带差值(Delta)信息。在实时动态图形(realtime motion graphics)项目中,它最常见的应用场景是把音频电平、MIDI 控制器、参数旋钮等连续变化的信号转换为干净的事件触发脉冲,从而驱动视觉元素的切换、闪烁或动画。读完本文,你将掌握 HasValueChanged 的 5 个输入参数、3 个输出端子的完整语义,理解其"按阈值比较 + 上升沿触发 + 时间门控"的内部工作原理,并能直接在 TiXL 节点图里搭建出稳定的变化检测与触发链路。
HasValueChanged 在 TiXL 中的作用与定位
HasValueChanged 属于 Lib.numbers.float.logic(浮点数逻辑类)运算符族,与同目录下的 HasValueIncreased、Compare、IsGreater 等配合使用,构成 TiXL 中数值逻辑判断的基础能力。
该运算符的核心职责是:检测输入值(Value)相比上一次评估时的取值是否发生了超出阈值(Threshold)的变化,并把这一判断结果输出为布尔值(HasChanged)。文档中明确指出它 "Similar to HasValueIncreased"(与 HasValueIncreased 类似)——区别在于 HasValueIncreased 只判断"是否增大",而 HasValueChanged 在 Mode 参数的控制下既可以判断"任意方向变化",也可以分别判断"增大"或"减小"。
从仓库使用情况看,HasValueChanged 被广泛应用于各类实时交互场景,例如:
Operators/examples/Symbols/user/pixtur/vj/下多个 VJ(视觉骑师)场景文件,如VJMovieCuts.t3、VJFaceBlobs.t3、VJPhotoDrops.t3;Operators/examples/Symbols/user/fuzzy/midi/LaunchPadXButton.t3(MIDI 打击垫按钮映射);Operators/examples/Symbols/user/still/worksforeverybody/下的参数混合与过场场景;Operators/Skills/Symbols/Math/M04_TriggerAnims/M04a_TriggerBasedAnimation.t3ui(基于触发器的动画教学工程)。
可见它是把外部连续信号"翻译"成离散事件的标准工具。
输入参数详解
HasValueChanged 共有 5 个输入参数,全部支持在 TiXL 中通过连线或参数面板设置,并可在.t3工程文件中持久化默认值。下表整理了每个参数的名称、类型、含义与默认值:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| Value | Single (float) | 待检测的输入数值 | 1.0 |
| Threshold | Single (float) | 变化阈值:输入值相对上次采样变化超过该值,输出布尔才可能为 True | 0.0 |
| Mode | Int32 (枚举) | 定义数值以何种方式被测试,决定布尔输出为 True 的条件 | 0(Changed) |
| MinTimeBetweenHits | Single (float) | 时间阈值:两次有效触发之间的最小时间间隔 | 0.0 |
| PreventContinuedChanges | Boolean | 防止连续变化造成的抖动/不稳定结果 | false |
默认值来自工程文件 HasValueChanged.t3:Mode=0、Threshold=0.0、Value=1.0、PreventContinuedChanges=false、MinTimeBetweenHits=0.0。
Value:被检测的信号源
接入任意产生浮点数的上游运算结果,例如音频电平(AudioAnalysis 输出)、MIDI CC 值、鼠标/键盘映射值、参数动画曲线等。注意它检测的是"变化量",因此输入信号本身保持恒定并不会触发输出。
Threshold:灵敏度阈值
用于过滤噪声与微小抖动。Threshold=0时,任何非零变化都会触发(从实现看,此时判断的是严格大于 0 的变化);Threshold越大,越不敏感,只有大幅变化才能触发。对于音频信号或传感器数据,建议设置一个略高于噪声底的非零阈值。
Mode:判定模式(关键参数)
Mode 是一个映射为枚举的整型输入,在源码 HasValueChanged.cs 中定义为Modes枚举,包含三种模式:
| 枚举值 | 整数映射 | 触发条件(源码实现) |
|---|---|---|
| Changed | 0(默认) | Math.Abs(newValue - _lastValue) > threshold,即变化绝对量超过阈值,无论方向 |
| Increased | 1 | newValue > _lastValue + threshold,即数值增大超过阈值 |
| Decreased | 2 | newValue < _lastValue - threshold,即数值减小超过阈值 |
对应源码片段(HasValueChanged.cs):
switch (Mode.GetEnumValue<Modes>(context)) { case Modes.Changed: var increase = absDelta > threshold; hasChanged = increase; break; case Modes.Increased: hasChanged = newValue > _lastValue + threshold; break; case Modes.Decreased: hasChanged = newValue < _lastValue - threshold; break; default: throw new ArgumentOutOfRangeException(); }选择建议:当只关心"数值上升"(如音频包络峰值、音量旋钮开大)时选Increased;只关心"数值下降"时选Decreased;对方向不敏感(如任意参数被拨动就触发)时选Changed。
MinTimeBetweenHits:触发冷却时间
设定两次有效触发之间的最小时间间隔(单位:秒)。在源码 HasValueChanged.cs 中,每当满足触发条件且通过时间门控检查时,会记录_lastHitTime = context.LocalFxTime,下次触发必须满足timeSinceLastHit >= minTimeBetweenHits才会再次输出 True,否则强制置为 False。典型用途:
- 防止高频信号(如持续的音频节拍)每帧都触发,将事件频率限制到人为设定的节奏(例如 0.1 秒);
- 与
PreventContinuedChanges配合,构建"最小间隔事件节流器"。
PreventContinuedChanges:抖动抑制开关
文档描述其为"可在特定场景下防止不稳定结果"。实现上(HasValueChanged.cs)它启用"上升沿触发"语义:只有当hasChanged由 false 变为 true 的那一刻(即MathUtils.WasTriggered(hasChanged, ref _wasHit)返回 true)才允许记录触发,从而把连续的 True 输出收敛为单次脉冲。这与 TiXL 核心工具类 MathUtils.WasTriggered 的语义一致——"Return true if a boolean changed from false to true"(当布尔值由 false 变为 true 时返回 true)。若关闭该选项,只要变化超过阈值,输出就会持续保持 True,适合需要"电平保持"而不需要脉冲的场景。
输出端子解析
HasValueChanged 提供 3 个输出端子(定义见 HasValueChanged.cs):
| 名称 | 类型 | 含义 |
|---|---|---|
| HasChanged | System.Boolean | 本次评估是否发生了超过阈值的有效变化(经过模式判定、冷却时间、抖动抑制后) |
| Delta | System.Single | 当前值与上一次采样值的差值,newValue - _lastValue(有符号,可正可负) |
| DeltaOnHit | System.Single | 最近一次"命中"(通过所有门控条件成功触发)时记录的变化绝对量 |
三个输出分别对应三种典型取用方式:
- HasChanged→ 作为事件信号直接驱动后续逻辑(如
If分支、动画触发、颜色切换); - Delta→ 反映当前帧的实时变化速率,可用于按变化强度缩放效果;
- DeltaOnHit→ 记录触发那一刻的变化幅度,适合需要"捕获峰值幅度"的下游逻辑(如把一次击打的最大力度保存下来)。
从 HasValueChanged.t3ui 的 UI 布局看,三个输出按纵向排列(Y 坐标 0/100/200),HasChanged与Delta标注为DirtyFlagTrigger.Animated(动画脏标记),表示它们会在每帧动画更新时被重新求值,适合连接实时信号。
内部工作原理:从源码看一次完整评估
结合 HasValueChanged.cs 的Update方法(L23-L81),可以还原运算符每次评估的完整流程:
- 读取输入:获取
Value、Threshold、MinTimeBetweenHits、PreventContinuedChanges(L25-L28); - 帧去重:若当前
context.LocalFxTime与_lastEvalTime之差小于 0.0002 秒,则直接返回(L30-L33),避免同一帧内重复求值; - 计算绝对差值:
absDelta = Math.Abs(newValue - _lastValue)(L37); - 模式判定:依据 Mode 选择 Changed / Increased / Decreased 三种比较逻辑(L39-L57);
- 上升沿检测:
WasTriggered(hasChanged, ref _wasHit)判断状态是否由 false 翻转为 true(L59); - 时间门控:满足触发条件且(
PreventContinuedChanges开启或wasTriggered)时,检查timeSinceLastHit >= minTimeBetweenHits,通过则记录_lastHitTime与_lastHitDelta,否则将hasChanged置为 false(L61-L73); - 写回状态:
HasChanged输出最终布尔值,Delta输出newValue - _lastValue,并更新_lastValue供下一帧比较,DeltaOnHit输出最近一次命中时的_lastHitDelta(L75-L80)。
其中第 5 步依赖的MathUtils.WasTriggered是 TiXL 中广泛复用的边沿检测工具(Core/Utils/MathUtils.cs):
/// <summary> /// Return true if a boolean changed from false to true /// </summary> public static bool WasTriggered(bool newState, ref bool current) { if (newState == current) return false; current = newState; return newState; }理解这 7 个步骤后,就能准确预测任意输入序列下 HasChanged 的输出行为——这是排查触发类节点图问题("为什么没触发""为什么连续触发")的关键。
实战接线方案
场景一:音频电平触发(Changed 模式 + 冷却)
- 将音频分析得到的电平值接入
Value; Threshold设为略高于背景噪声的值(如 0.05~0.15);Mode保持默认Changed;MinTimeBetweenHits设为 0.1~0.5 秒限制触发频率;PreventContinuedChanges设为true获得干净的脉冲输出;- 将
HasChanged接到下游动画/颜色切换的触发输入端,DeltaOnHit接到强度缩放。
场景二:MIDI 旋钮方向感知(Increased / Decreased 模式)
- 旋钮值接入
Value,Threshold=0.01; - 一个实例
Mode=Increased检测正向转动,另一个实例Mode=Decreased检测反向转动; - 分别用
HasChanged驱动"增大"与"减小"两条逻辑分支——这与仓库中 MIDI 映射示例(如Operators/examples/Symbols/user/fuzzy/midi/LaunchPadXButton.t3)的思路一致。
场景三:防抖的交互触发(PreventContinuedChanges 语义)
当输入信号在阈值附近抖动时,Changed模式会在每帧反复输出 True。开启PreventContinuedChanges后输出收敛为单次上升沿脉冲,配合MinTimeBetweenHits可实现完整的"边沿触发 + 冷却"事件流,避免视觉元素在参数抖动下闪烁不停。
与其他逻辑运算符的搭配
- HasValueIncreased:当只需要"单向增大"判断、不需要冷却与脉冲语义时,可直接使用更轻量的 HasValueIncreased(其实现仅保留
v > _lastValue + Threshold的比较与_lastValue更新,逻辑更简单); - Compare / IsGreater:用于静态阈值比较(绝对值判断),与 HasValueChanged 的"差分判断"互补。
工程文件中的配置形态
在 TiXL 中,每个运算符实例的默认参数会序列化到.t3工程文件。HasValueChanged 的默认配置见 HasValueChanged.t3,各输入通过 GUID 绑定:Mode=031ef11b…、Threshold=1e03f11b…、Value=7f5fb125…、PreventContinuedChanges=8ebf4715…、MinTimeBetweenHits=b994249d…。UI 描述与参数分组(Options、Time)见 HasValueChanged.t3ui。当你把 HasValueChanged 拖入自己的工程并调整参数后,TiXL 会在保存时生成同结构的输入节点配置,上述字段可作为理解工程文件的参考。
小结
HasValueChanged 是 TiXL 中把连续数值流转换为离散事件的核心工具:Value提供信号、Threshold过滤噪声、Mode决定比较方向、MinTimeBetweenHits节流触发频率、PreventContinuedChanges抑制抖动;输出端HasChanged提供布尔事件、Delta提供实时差值、DeltaOnHit捕获命中瞬间的变化幅度。通过本文的源码级剖析(实现见 HasValueChanged.cs、边沿检测工具见 MathUtils.cs)与三个实战接线方案,你可以在自己的 TiXL 工程中稳定地构建音频触发、参数方向感知与防抖脉冲等常见交互链路。
- 音视频
- 图形学
- 桌面应用
【免费下载链接】t3
TiXL is an open source software to create realtime motion graphics.
相关推荐
TiXL HasVec2Changed 操作符详解:Vector2 向量变化检测、阈值触发与防抖控制
TiXL HasVec2Changed 操作符详解:Vector2 向量变化检测、阈值触发与防抖控制 HasVec2Changed 是 TiXL 实时动态图形(
音视频图形学桌面应用TiXL [ActivateSnapshot] 运算符实战指南:用索引与触发脉冲程序化激活快照
TiXL ActivateSnapshot 运算符实战指南:用索引与触发脉冲程序化激活快照 TiXL(tooll3)的 ActivateSnapshot 运算符
音视频图形学桌面应用TiXL 数值运算核心:Sub 减法运算符源码解析与实战指南
TiXL 数值运算核心:Sub 减法运算符源码解析与实战指南 导读 Sub(Subtraction)是 TiXL 实时运动图形引擎中 Lib.numbers.f
音视频图形学桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考