交互的回调函数
PF_InData
中提供了非宏的(un-macro’d)函数指针,使用提供的宏来访问它们。
交互回调函数
PF_ADD_PARAM
在 PF_Cmd_PARAM_SETUP
期间,将插件的参数枚举到 After Effects,多次调用此函数, 。
注意: 不能完全清除 PF_ADD_PARAM()
之前的 PF_ParamDef
的话,会导致很多问题。在添加参数之前总是使用 AEFX_CLR_STRUCT
。
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
循环中。
PF_Err PF_ABORT (PF_InData *in_data);
复制代码
PF_PROGRESS
在处理过程中显示进度条; current
和 total
描述完成的百分比。如果您应该暂停或中止当前处理,则返回非零; 将该值返回给 After Effects 。每扫描线调用一次,除非您的效果非常慢。
如果 total
为 0 ,则使用 PF_ABORT
(为用户提供不同的选择)。
PF_Err PF_PROGRESS (
PF_InData *in_data,
A_long current,
A_long total );
复制代码
PF_CHECKOUT_PARAM
在指定的时间获取参数值或源视频层。After Effects 基于参数的检出状态做出缓存决策。
分配一个新的 PF_ParamDef
来保存结果; 传递给插件的文件是只读的。如果您检出一个设置为 的层参数,则返回的层将填充为0 。遮罩不包含在检出层中。
在 UI 事件处理期间不要检出层参数。
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
中的字段将不再有效。
PF_Err PF_CHECKIN_PARAM (
PF_InData *in_data,
PF_ParamDef *param );
复制代码
PF_REGISTER_UI
注册一个自定义用户界面元素。参见 Effect UI & Events 。注意:不支持 PF_UIAlignment
标志。
PF_Err PF_REGISTER_UI (
PF_InData *in_data,
PF_CustomUIInfo *cust_info );
复制代码
PF_CHECKOUT_LAYER_AUDIO
给定一个 index,start_time, duration, time_scale, rate, bytes_per_sample, num_channels,和 fmt_signed, After Effects 将返回一个对应的 PF_LayerAudio
。After Effects 将执行任何必要的重采样。
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
的调用进行匹配,无论错误条件如何。
PF_Err PF_CHECKIN_LAYER_AUDIO (
PF_InData *in_data,
PF_LayerAudio audio );
复制代码
PF_GET_AUDIO_DATA
返回关于 PF_LayerAudio
的信息。
audio
之后的所有参数都是可选的; 为任何您不感兴趣的值传递 0 。rate0
是无符号的,fmt_signed0
对于有符号应该是非零,对于无符号应该是零。这个回调用于读取音频信息的视觉效果。要改变音频,写一个音频过滤器。
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
函数。
在这种情况下,你可以这样开始:
lines_per_iterateL = in_data->extent_hint.top - in_data->extent_hint.bottom;
total_linesL = 3 * lines_per_iterateL;
lines_so_farL = 0;
复制代码
在每次迭代之后,将已经完成的代码行添加到当前位置:
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));
复制代码