如何在 Nuke 中的 Ops 之间交换自定义数据?
How to exchange custom data between Ops in Nuke?
此问题是针对使用 C++ 和 NDK of Nuke 的开发人员提出的。
Context: 假设一个自定义 Op 实现了 DD::Image::NoIop
和
DD::Image::Executable
。节点迭代一系列帧以提取信息
每个帧,存储在自定义数据结构中。一个自定义旋钮,它是一个成员
上述 Op 的变量(但在 UI 中不可见),处理加载和保存
数据结构的(序列化)。
现在我想在 Ops 之间交换那个数据结构。
到目前为止,我有以下想法:
表达式链接
旋钮可以使用表达式链接共享信息(矩阵等)。
此功能也可以用于自定义数据吗?
图像数据的序列化
自定义数据将被序列化并写入(新)通道。一个
处理树下方的节点可以抓住它并反序列化
再次。当然,通道不能在序列化之间改变
和反序列化或者其他......我知道这是一个黑客,但是,嘿,任何端口
在暴风雨中!
GeoOp + 渲染器
在自定义数据完全基于点的情况下(不幸的是,
它不是在我的情况下),我可以把上面的节点变成一个 3D 节点并通过
将数据指向其他 3D 节点。在某些时候需要渲染节点
回到二维。
我正朝着正确的方向前进?如果不是,什么是明智的
使该数据结构可用于其他节点的方法,这些节点依赖于
里面包含的信息?
此问题已在 Nuke-dev mailing list 上得到回答:
如果您知道您的 Op 输入的实际 class,则可以将
输入 class 类型并直接访问它。一个简单的例子可以是
下面这个片段:
//! @file DownstreamOp.cpp
#include "UpstreamOp.h" // The Op that contains your custom data.
// ...
UpstreamOp * upstreamOp = dynamic_cast< UpstreamOp * >( input( 0 ) );
if ( upstreamOp )
{
YourCustomData * data = yourOp->getData();
// ...
}
// ...
更新
参考我通过电子邮件收到的问题进行更新:
I am trying to do this exact same thing, pass custom data from one Iop
plugin to another.
But these two plugins are defined in different dso/dll files.
How did you get this to work ?
简答:
将您的 Ops 编译成一个共享对象。
长答案:
说
- UpstreamOp.cpp
- DownstreamOp.cpp
定义依赖操作。
在第一次尝试中,我仅使用 UpstreamOp.cpp
编译了第一个插件,
照常。对于第二个插件,我编译了 DownstreamOp.cpp
和
UpstreamOp.cpp
进入该插件。
奇怪的是它起作用了(在 Linux 上;没有测试 Windows)。
但是,通过覆盖
bool Op::test_input( int input, Op * op ) const;
东西会坏的。仍然使用上述插件创建和保存一个 Comp
作品。但是再次加载相同的 Comp 会破坏节点图中的连接
在 UpstreamOp
和 DownstreamOp
之间并且无法再连接
他们又来了。
我的假设是:因为两个插件都包含 UpstreamOp
它的符号
如果节点使用 UpstreamOp
的实例,则取决于插件的加载顺序
来自第一个或第二个插件。所以,如果 UpstreamOp
来自第一个插件
使用则 Op::test_input()
中的任何 dynamic_cast
都会失败,并且两个 Op 不能
被连接了。
令人惊讶的是,Nuke 甚至不厌其烦地从上面开始
配置,因为它可能对来自插件的符号相当挑剔,例如,如果它们
缺失。
无论如何,为了解决这个问题,我做了以下事情:
- 将两个 Ops 编译成一个共享对象,例如myplugins.so,以及
- 添加TCL脚本或Python脚本(init.py/menu.py)指示Nuke如何加载
Ops 正确。
可以在 dev guide 和说明中找到 TCL 脚本的示例
因为你的 menu.py 可能是这样的
menu = nuke.menu( 'Nodes' ).addMenu( 'my-plugins' )
menu.addCommand('UpstreamOp', lambda: nuke.createNode('UpstreamOp'))
menu.addCommand('DownstreamOp', lambda: nuke.createNode('DownstreamOp'))
nuke.load('myplugins')
到目前为止,这对我们来说是可靠的(在 Linux 和 Windows 上,还没有测试 Mac)。
此问题是针对使用 C++ 和 NDK of Nuke 的开发人员提出的。
Context: 假设一个自定义 Op 实现了 DD::Image::NoIop
和
DD::Image::Executable
。节点迭代一系列帧以提取信息
每个帧,存储在自定义数据结构中。一个自定义旋钮,它是一个成员
上述 Op 的变量(但在 UI 中不可见),处理加载和保存
数据结构的(序列化)。
现在我想在 Ops 之间交换那个数据结构。
到目前为止,我有以下想法:
表达式链接
旋钮可以使用表达式链接共享信息(矩阵等)。 此功能也可以用于自定义数据吗?
图像数据的序列化
自定义数据将被序列化并写入(新)通道。一个 处理树下方的节点可以抓住它并反序列化 再次。当然,通道不能在序列化之间改变 和反序列化或者其他......我知道这是一个黑客,但是,嘿,任何端口 在暴风雨中!
GeoOp + 渲染器
在自定义数据完全基于点的情况下(不幸的是, 它不是在我的情况下),我可以把上面的节点变成一个 3D 节点并通过 将数据指向其他 3D 节点。在某些时候需要渲染节点 回到二维。
我正朝着正确的方向前进?如果不是,什么是明智的 使该数据结构可用于其他节点的方法,这些节点依赖于 里面包含的信息?
此问题已在 Nuke-dev mailing list 上得到回答:
如果您知道您的 Op 输入的实际 class,则可以将 输入 class 类型并直接访问它。一个简单的例子可以是 下面这个片段:
//! @file DownstreamOp.cpp
#include "UpstreamOp.h" // The Op that contains your custom data.
// ...
UpstreamOp * upstreamOp = dynamic_cast< UpstreamOp * >( input( 0 ) );
if ( upstreamOp )
{
YourCustomData * data = yourOp->getData();
// ...
}
// ...
更新
参考我通过电子邮件收到的问题进行更新:
I am trying to do this exact same thing, pass custom data from one Iop plugin to another. But these two plugins are defined in different dso/dll files. How did you get this to work ?
简答:
将您的 Ops 编译成一个共享对象。
长答案:
说
- UpstreamOp.cpp
- DownstreamOp.cpp
定义依赖操作。
在第一次尝试中,我仅使用 UpstreamOp.cpp
编译了第一个插件,
照常。对于第二个插件,我编译了 DownstreamOp.cpp
和
UpstreamOp.cpp
进入该插件。
奇怪的是它起作用了(在 Linux 上;没有测试 Windows)。
但是,通过覆盖
bool Op::test_input( int input, Op * op ) const;
东西会坏的。仍然使用上述插件创建和保存一个 Comp
作品。但是再次加载相同的 Comp 会破坏节点图中的连接
在 UpstreamOp
和 DownstreamOp
之间并且无法再连接
他们又来了。
我的假设是:因为两个插件都包含 UpstreamOp
它的符号
如果节点使用 UpstreamOp
的实例,则取决于插件的加载顺序
来自第一个或第二个插件。所以,如果 UpstreamOp
来自第一个插件
使用则 Op::test_input()
中的任何 dynamic_cast
都会失败,并且两个 Op 不能
被连接了。
令人惊讶的是,Nuke 甚至不厌其烦地从上面开始 配置,因为它可能对来自插件的符号相当挑剔,例如,如果它们 缺失。
无论如何,为了解决这个问题,我做了以下事情:
- 将两个 Ops 编译成一个共享对象,例如myplugins.so,以及
- 添加TCL脚本或Python脚本(init.py/menu.py)指示Nuke如何加载 Ops 正确。
可以在 dev guide 和说明中找到 TCL 脚本的示例 因为你的 menu.py 可能是这样的
menu = nuke.menu( 'Nodes' ).addMenu( 'my-plugins' )
menu.addCommand('UpstreamOp', lambda: nuke.createNode('UpstreamOp'))
menu.addCommand('DownstreamOp', lambda: nuke.createNode('DownstreamOp'))
nuke.load('myplugins')
到目前为止,这对我们来说是可靠的(在 Linux 和 Windows 上,还没有测试 Mac)。