AEJoy —— AE 插件开发中的 交互的回调函数 交互的

交互的回调函数

PF_InData 中提供了非宏的(un-macro’d)函数指针,使用提供的宏来访问它们。

交互回调函数

PF_ADD_PARAM

PF_Cmd_PARAM_SETUP 期间,将插件的参数枚举到 After Effects,多次调用此函数, 。

注意: 不能完全清除 PF_ADD_PARAM() 之前的 PF_ParamDef 的话,会导致很多问题。在添加参数之前总是使用 AEFX_CLR_STRUCT

1
2
3
4
cpp复制代码PF_Err PF_ADD_PARAM (
PF_InData *in_data,
PF_ParamIndex index,
PF_ParamDefPtr def);

我们在 Utils/ Param_Utils.h 中为特定的参数类型提供了方便的宏:

  • PF_ADD_COLOR,
  • PF_ADD_ARBITRARY,
  • PF_ADD_SLIDER,
  • PF_ADD_FIXED,
  • PF_ADD_FLOAT_SLIDERX,
  • PF_ADD_CHECKBOXX,
  • PF_ADD_BUTTON,
  • PF_ADD_ANGLE,
  • PF_ADD_NULL,
  • PF_ADD_LAYER,
  • PF_ADD_255_SLIDER,
  • PF_ADD_PERCENT,
  • PF_ADD_POINT,
  • PF_ADD_POINT_3D,
  • PF_ADD_TOPICX,
  • PF_END_TOPIC,
  • PF_ADD_POPUPX,
  • PF_ADD_FLOAT_SLIDERX_DISABLED

PF_ABORT

如果用户已取消,返回非零;将该值返回给 After Effects 。将渲染程序包装在一个“当没有要求中止” 的 while 循环中。

1
cpp复制代码PF_Err PF_ABORT (PF_InData *in_data);

PF_PROGRESS

在处理过程中显示进度条; currenttotal 描述完成的百分比。如果您应该暂停或中止当前处理,则返回非零; 将该值返回给 After Effects 。每扫描线调用一次,除非您的效果非常慢。

如果 total 为 0 ,则使用 PF_ABORT(为用户提供不同的选择)。

1
2
3
4
cpp复制代码PF_Err PF_PROGRESS (
PF_InData *in_data,
A_long current,
A_long total );

PF_CHECKOUT_PARAM

在指定的时间获取参数值或源视频层。After Effects 基于参数的检出状态做出缓存决策。

分配一个新的 PF_ParamDef 来保存结果; 传递给插件的文件是只读的。如果您检出一个设置为 的层参数,则返回的层将填充为0 。遮罩不包含在检出层中。

在 UI 事件处理期间不要检出层参数。

1
2
3
4
5
6
7
cpp复制代码PF_Err PF_CHECKOUT_PARAM (
PF_InData *in_data,
PF_ParamIndex index,
A_long what_time,
A_long step,
A_long time_scale,
PF_ParamDef *param);

如果检查出源层,将返回一个去隔行帧。如果您询问引用上字段(upper field)的时间,您将收到返回的上字段和用于生成额外扫描线的过滤器。例如,假设第 0 行和第 2 行是上字段,第 1 行是下字段,如果您查看上字段,第 0 行和第 2 行将直接从源镜头返回,第 1 行将通过对第 0 行和第 2 行进行平均计算。如果您想重新组合一个包含两个字段的完整分辨率源帧,可以调用 PF_CHECKOUT_PARAM 两次来获取两个字段,并重新交错镜头。

当检出一个没有帧对齐的图层时,会发生什么? 所有项目本质上都具有无限的时间分辨率,所以当 AE 询问任何时间值时,它都会渲染该物品。对于一个合成,这涉及到插值所有关键帧的值到子帧时间。对于连续镜头, AE 返回一个与所询问的时间相对应的完整图像,这是离左边最近的帧。如果用户在那个图层上进行帧混合,就会生成一个插值帧。

PF_CHECKIN_PARAM

PF_CHECKIN_PARAM 匹配每个 PF_CHECKOUT_PARAM

不这样做会导致糟糕的性能和内存泄漏。一旦检入,PF_ParamDef 中的字段将不再有效。

1
2
3
cpp复制代码PF_Err PF_CHECKIN_PARAM (
PF_InData *in_data,
PF_ParamDef *param );

PF_REGISTER_UI

注册一个自定义用户界面元素。参见 Effect UI & Events 。注意:不支持 PF_UIAlignment 标志。

1
2
3
cpp复制代码PF_Err PF_REGISTER_UI (
PF_InData *in_data,
PF_CustomUIInfo *cust_info );

PF_CHECKOUT_LAYER_AUDIO

给定一个 indexstart_time, duration, time_scale, rate, bytes_per_sample, num_channels*,和 *fmt_signed, After Effects 将返回一个对应的 PF_LayerAudio 。After Effects 将执行任何必要的重采样。

1
2
3
4
5
6
7
8
9
10
11
cpp复制代码PF_Err PF_CHECKOUT_LAYER_AUDIO (
PF_InData *in_data,
PF_ParamIndex index,
A_long start_time,
A_long duration,
A_u_long time_scale,
PF_UFixed rate,
A_long bytes_per_sample,
A_long num_channels,
A_long fmt_signed,
PF_LayerAudio *audio);

PF_CHECKIN_LAYER_AUDIO

将所有对 PF_CHECKOUT_LAYER_AUDIO 的调用与对PF_CHECKIN_LAYER_AUDIO 的调用进行匹配,无论错误条件如何。

1
2
3
cpp复制代码PF_Err PF_CHECKIN_LAYER_AUDIO (
PF_InData *in_data,
PF_LayerAudio audio );

PF_GET_AUDIO_DATA

返回关于 PF_LayerAudio 的信息。

audio 之后的所有参数都是可选的; 为任何您不感兴趣的值传递 0 。rate0 是无符号的,fmt_signed0 对于有符号应该是非零,对于无符号应该是零。这个回调用于读取音频信息的视觉效果。要改变音频,写一个音频过滤器。

1
2
3
4
5
6
7
8
9
cpp复制代码PF_Err PF_GET_AUDIO_DATA (
PF_InData *in_data,
PF_LayerAudio audio,
PF_SndSamplePtr *data0,
A_long *num_samples0,
PF_UFixed *rate0,
A_long *bytes_per_sample0,
A_long *num_channels0,
A_long *fmt_signed0);

参数检验与参数零

在效果控制(和合成)面板中,效果按 0 到 n 的顺序应用于图像。

effect[n-1] 的输出是 effect[n] 的输入(param[0])。

另一方面,当一个正常效果使用 PF_CHECKOUT_PARAM 检查一个层时,它会收到原始(未添加效果的)源层,而不管它的顺序。

但是,当 SmartFX 效果检出它的输入参数(params[0])时,将应用先前的效果。

参数检出行为

不管图层的进点和出点(in and out point)是否被修剪过,你都会从源画面的开始到结束得到有效的帧,在此之前和之后都是透明的。

与被检出的合成相比,帧率较低的图层参数只在需要时刷新。

在 30 帧/秒的合成中,10 帧/秒的图层只需要每三帧刷新一次。尽管是静态输入层,如果你的效果想要改变它的输出,你只需要设置PF_Outflag_NON_PARAM_VARY

当一个效果检出一个连续栅格化的 Adobe Illustrator 图层时,After Effects 在合成大小的缓冲区中渲染 Illustrator 图层并应用几何图形。

参数检出与重入

插件在不同时间检出层,可以生成可重入行为。考虑一个实例,其中 Checkout 示例插件应用于合成 B 中的一个层,而 B 被预合成为合成 A , Checkout 也会应用于合成 A。

当合成 A 被渲染时,将会发送 PF_Cmd_RENDER 到 Checkout[A] ,在此期间内,它将从当前时间以外的时间检出一个层(合成 B )。

为了提供这个检出层,After Effects 会发送 PF_Cmd_RENDER 到 Checkout[B]。

转眼间, 递归!

如果要检出参数,效果必须适当地处理可重入的渲染请求。

不要使用全局变量,也不要读写静态变量……但你不会这么做的,对吧?

迭代期间的进度

After Effects 力求尽可能地响应用户交互,甚至在渲染时。通过适当使用PF_ITERATE() 实现相同的操作。例如,您可能在响应 PF_Cmd_RENDER 期间使用了三次 PF_ITERATE 函数。

在这种情况下,你可以这样开始:

1
2
3
cpp复制代码lines_per_iterateL = in_data->extent_hint.top - in_data->extent_hint.bottom;
total_linesL = 3 * lines_per_iterateL;
lines_so_farL = 0;

在每次迭代之后,将已经完成的代码行添加到当前位置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
cpp复制代码suites.iterate8suite()->iterate( lines_so_farL,
total_linesL,
input_worldP,
&output->extent_hint,
refcon,
WhizBangPreProcessFun,
output_worldP);

lines_so_farL += lines_per_iterateL;

ERR(PF_PROGRESS(lines_so_farL, total_linesL));

suites.iterate8suite()->iterate( lines_so_farL,
total_linesL,
input_worldP,
&output->extent_hint,
refcon,
WhizBangRenderFunc,
output_worldP);

lines_so_far += lines_per_iterateL;

ERR(PF_PROGRESS(lines_so_farL, total_linesL));

suites.iterate8suite()->iterate( lines_so_farL,
total_linesL,
input_worldP,
&output->extent_hint,
refcon,
WhizBangPostProcessFunc,
output_worldP);

ERR(PF_PROGRESS(lines_so_farL, total_linesL));

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%