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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use crate::*;
/// Effects modules use callbacks to define their parameters.
/// When invoked, they will be given the parameters values at the particular invocation moment,
/// but some effects may need to ask for the parameter values at other times (notably of layer parameters for, say, a visual echo).
///
/// While running, effects modules are responsible for checking for user interrupts.
/// This checking can be done with either the abort callback, which will return a value indicating if the user has taken any action,
/// or with the progress callback, which performs user interrupt checking just like the abort callback, and also displays a progress display.
///
/// At the bottom of this section are macros for accessing these callback routines.
/// The first parameter to each macro is a pointer to a PF_InData structure, defined below.
/// This pointer will be passed to your effect.
pub struct InteractCallbacks(InData);
impl InteractCallbacks {
pub fn new(in_data: InData) -> Self {
Self(in_data)
}
/// The checkout_param callback allows you to inquire param values at times other than the current one, and allows you to access layer params other
/// than the default input layer and the output layer. See the notes on the "params" structure at the end of this file.
///
/// If you checkout a layer parameter and the layer popup is currently set
/// to `<none>`, the return value will be filled with zeros. You can check the "data" pointer. If it is `NULL`, then the layer param is set to `<none>`
/// and you should do something like faking an all alpha zero layer or some such nonsense.
///
/// IMPORTANT: Due to 13.5 threading changes, checking out a layer param that is not `<none>` inside of `UPDATE_PARAMS_UI` will return
/// a frame with black pixels to avoid render requests and possible deadlock.
/// In other selectors the actual render will be triggered as it did before.
pub fn checkout_param(&self, index: i32, what_time: i32, time_step: i32, time_scale: u32) -> Result<ae_sys::PF_ParamDef, Error> {
let in_data = unsafe { &(*self.0.as_ptr()) };
let mut param: ae_sys::PF_ParamDef = unsafe { std::mem::zeroed() };
param.param_type = ae_sys::PF_Param_RESERVED;
match unsafe { in_data.inter.checkout_param.unwrap()(in_data.effect_ref, index as _, what_time as _, time_step as _, time_scale as _, &mut param) } {
0 => Ok(param),
e => Err(Error::from(e)),
}
}
/// When you have called `checkout_param`, you must call `checkin_param` when you are done, so After Effects can clean up after itself and you.
/// This is very important for smooth functioning and also to save memory where possible.
/// Once checked in, the fields in the `PF_ParamDef` will no longer be valid.
pub fn checkin_param(&self, param: &ae_sys::PF_ParamDef) -> Result<(), Error> {
let in_data = unsafe { &(*self.0.as_ptr()) };
match unsafe { in_data.inter.checkin_param.unwrap()(in_data.effect_ref, param as *const _ as *mut _) } {
0 => Ok(()),
e => Err(Error::from(e)),
}
}
/// When given the [`Command::ParamsSetup`] message, the effect will generally make a series of calls to the `add_param` routine
/// to define the interface that the After Effects user will see. See the `PF_ParamDefs` defined above.
/// Currently you can only add params at the end, and only at [`Command::ParamsSetup`] time.
pub fn add_param(&self, index: i32, def: &ae_sys::PF_ParamDef) -> Result<(), Error> {
let in_data = unsafe { &(*self.0.as_ptr()) };
match unsafe { in_data.inter.add_param.unwrap()(in_data.effect_ref, index as _, def as *const _ as *mut _) } {
0 => Ok(()),
e => Err(Error::from(e)),
}
}
/// Periodically, you should check if the user wants to interrupt the current processing.
/// The abort proc here will return non-zero if the effects module should suspend its current processing.
/// If you call this routine and it returns a value other than zero, you should return that value when your effect returns.
/// That will let us know if the effect completed rendering or not.
pub fn abort(&self) -> Result<(), Error> {
let in_data = unsafe { &(*self.0.as_ptr()) };
match unsafe { in_data.inter.abort.unwrap()(in_data.effect_ref) } {
0 => Ok(()),
e => Err(Error::from(e)),
}
}
/// Alternatively, you may wish to display a progress bar while you are processing the image.
/// This routine combines the abort proc user interrupt checking with code that will display a progress bar for you.
/// The current and total params represent a fraction (current/total) that describes how far you are along in your processing.
///
/// Current should equal total when done.
///
/// Additionally, this routine will return non-zero if you should suspend/abort your current processing.
/// You should probably try not to call this too frequently (e.g. at every pixel).
/// It is better to call it, say, once per scanline, unless your filter is really really slow.
pub fn progress(&self, current: i32, total: i32) -> Result<(), Error> {
let in_data = unsafe { &(*self.0.as_ptr()) };
match unsafe { in_data.inter.progress.unwrap()(in_data.effect_ref, current as _, total as _) } {
0 => Ok(()),
e => Err(Error::from(e)),
}
}
/// Register a custom user interface element. See [Effect UI and events](https://ae-plugins.docsforadobe.dev/effect-ui-events/effect-ui-events.html). Note: The `PF_UIAlignment` flags are not honored.
pub fn register_ui(&self, custom_ui_info: CustomUIInfo) -> Result<(), Error> {
let in_data = unsafe { &(*self.0.as_ptr()) };
match unsafe { in_data.inter.register_ui.unwrap()(in_data.effect_ref, custom_ui_info.as_ptr() as _) } {
0 => Ok(()),
e => Err(Error::from(e)),
}
}
// fn checkout_layer_audio(effect_ref: PF_ProgPtr, index: PF_ParamIndex, start_time: A_long, duration: A_long, time_scale: A_u_long, rate: PF_UFixed, bytes_per_sample: A_long, num_channels: A_long, fmt_signed: A_long, audio: *mut PF_LayerAudio) -> PF_Err,
// fn checkin_layer_audio(effect_ref: PF_ProgPtr, audio: PF_LayerAudio) -> PF_Err,
// fn audio_data(effect_ref: PF_ProgPtr, audio: PF_LayerAudio, data0: *mut PF_SndSamplePtr, num_samples0: *mut A_long, rate0: *mut PF_UFixed, bytes_per_sample0: *mut A_long, num_channels0: *mut A_long, fmt_signed0: *mut A_long) -> PF_Err,
}