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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
use crate::*;
define_suite!(
/// A parameter's value (not just UI) can be modified during `Command::UserChangedParam` and during `Command::Event` (*PF_Event_DO_CLICK*, *PF_Event_DRAG*, & *PF_Event_KEYDOWN*).
/// After Effects will not honor changes made at other times.
///
/// When changing parameter *values* (and not just the UI), modify the original parameter, and set ``PF_Paramdef.uu.change_flags`` to ``PF_ChangeFlag_CHANGED_VALUE``.
///
/// This change will be also update the UI, and will be undoable by the user. Note that ``PF_ChangeFlag_CHANGED_VALUE`` isn't supported for layer parameters.
///
/// This suite is provided to give effect plug-ins some access to their parameter streams, without requiring AEGP suite usage.
/// At least some of these functions are provided by several third-party hosts. These functions are especially handy for effects with supervised parameters.
///
///
/// ### [`current_state()`](Self::current_state) / [`are_states_identical()`](Self::are_states_identical)
/// This API lets you determine if a set of your inputs (either layers, other properties, or both) are different between when you first called [`current_state()`](Self::current_state) and a current call, so it can/ be used for caching.
/// You can specify a range of time to consider or all of time.
///
/// For effects that do simulation across time and therefore set PF_OutFlag2_AUTOMATIC_WIDE_TIME_INPUT, when you ask about a time range, it will be expanded to include any times needed to produce that range.
///
/// IMPORTANT: as of 13.5 to avoid threading deadlock problems, [`current_state()`](Self::current_state) returns a random state
/// if used in the context of UPDATE_PARAMS_UI only. In other selectors this will behave normally.
///
/// # Parameters & Floating Point Values
///
/// We have something to admit to you; for years, even though we've given you 8 bit color values,
/// we've internally used floating point representations behind your back.
///
/// That's right, even with over-bright colors, we'd only ever tell you '255, 255, 255'. Yeah, right.
///
/// Use the [`AngleParamSuite`](crate::pf::suites::AngleParam) to get floating point values for angle parameters.
///
/// Use the [`ColorParamSuite`](crate::pf::suites::ColorParam) to get floating point values for color parameters.
///
/// Use the [`PointParamSuite`](crate::pf::suites::PointParam) to get floating point values for point parameters.
ParamUtilsSuite,
PF_ParamUtilsSuite3,
kPFParamUtilsSuite,
kPFParamUtilsSuiteVersion3
);
impl ParamUtilsSuite {
/// Acquire this suite from the host. Returns error if the suite is not available.
/// Suite is released on drop.
pub fn new() -> Result<Self, Error> {
crate::Suite::new()
}
/// Force After Effects to refresh the parameter's UI, in the effect controls palette.
///
/// Starting in CC 2014, After Effects will now honor a change to a custom UI height. Simply change the ui_height of your custom UI PF_ParamDef and then call PF_UpdateParamUI.
/// The effect's custom UI height will be updated in the Effect Control Window.
///
/// Starting in CS6, when a plug-in disables a parameter, we now save that state in the UI flags so that the plug-in can check that flag in the future to see if it is disabled.
///
/// NOTE: Never pass param\[0\] to this function.
///
/// You can call this function for each param whose UI settings you want to change when handling a `Command::UserChangedParam` or `Command::UpdateParamsUi`.
/// These changes are cosmetic only, and don't go into the undo buffer.
///
/// The ONLY fields that can be changed in this way are:
/// PF_ParamDef
/// ui_flags: `PF_PUI_ECW_SEPARATOR`, `PF_PUI_DISABLED` only (and `PF_PUI_INVISIBLE` in Premiere).
/// ui_width
/// ui_height
/// name
/// flags: `PF_ParamFlag_COLLAPSE_TWIRLY` only
/// PF_ParamDefUnion:
/// slider_min, slider_max, precision, display_flags of any slider type
/// For `PF_PUI_STD_CONTROL_ONLY` params, you can also change the value field by setting `PF_ChangeFlag_CHANGED_VALUE` before returning.
/// But you are not allowed to change the value during `PF_Cmd_UPDATE_PARAMS_UI`.
pub fn update_param_ui(&self, effect_ref: impl AsPtr<ae_sys::PF_ProgPtr>, param_index: i32, param_def: &ParamDef) -> Result<(), Error> {
call_suite_fn!(self, PF_UpdateParamUI, effect_ref.as_ptr(), param_index, param_def.as_ref())
}
/// This API, combined with [`are_states_identical()`](Self::are_states_identical) below, lets you determine if a set of inputs (either layers, other properties, or both)
/// are different between when you first called [`current_state()`](Self::current_state) and a current call, so it can be used for caching.
/// You can specify a range of time to consider or all of time.
///
/// Updated in CS6 to add `param_index`, `start`, and `duration`. Pre-defined constants for `param_index` are as follows:
///
/// - [`PARAM_INDEX_CHECK_ALL`] - check every parameter, including every layer referred to by a layer parameter.
/// - [`PARAM_INDEX_CHECK_ALL_EXCEPT_LAYER_PARAMS`] - omit all layers. Pass a specific layer parameter index to include that as the only layer parameter tested.
/// - [`PARAM_INDEX_CHECK_ALL_HONOR_EXCLUDE`] - Similar to CHECK_ALL, but honor `PF_ParamFlag_EXCLUDE_FROM_HAVE_INPUTS_CHANGED`.
///
/// Passing in `None` for both start and duration indicates all time.
/// For effects that do simulation across time and therefore set `PF_OutFlag2_AUTOMATIC_WIDE_TIME_INPUT`, when you ask about a time range,
/// it will be expanded to include any times needed to produce that range.
///
/// Populates a `PF_State`, an opaque data type used as a receipt for the current state of the effect's parameters (the `PF_State` is used in our internal frame caching database).
pub fn current_state(&self, effect_ref: impl AsPtr<ae_sys::PF_ProgPtr>, param_index: i32, start: Option<Time>, duration: Option<Time>) -> Result<ae_sys::PF_State, Error> {
call_suite_fn_single!(self,
PF_GetCurrentState -> ae_sys::PF_State,
effect_ref.as_ptr(),
param_index,
start.map(Into::into).as_ref().map_or(std::ptr::null(), |t| t),
duration.map(Into::into).as_ref().map_or(std::ptr::null(), |t| t)
)
}
/// New in CS6. Compare two different states, retrieved using `PF_GetCurrentState`, above.
pub fn are_states_identical(&self, effect_ref: impl AsPtr<ae_sys::PF_ProgPtr>, state1: &ae_sys::PF_State, state2: &ae_sys::PF_State) -> Result<bool, Error> {
Ok(call_suite_fn_single!(self, PF_AreStatesIdentical -> ae_sys::A_Boolean, effect_ref.as_ptr(), state1, state2)? != 0)
}
/// Returns `true` if a parameter's value is the same at the two passed times.
///
/// Note: the times need not be contiguous; there could be different intervening values.
pub fn is_identical_checkout(&self, effect_ref: impl AsPtr<ae_sys::PF_ProgPtr>, param_index: i32, what_time1: i32, time_step1: i32, time_scale1: u32, what_time2: i32, time_step2: i32, time_scale2: u32) -> Result<bool, Error> {
Ok(call_suite_fn_single!(self, PF_IsIdenticalCheckout -> ae_sys::PF_Boolean, effect_ref.as_ptr(), param_index, what_time1, time_step1, time_scale1, what_time2, time_step2, time_scale2)? != 0)
}
/// Searches (in the specified direction) for the next keyframe in the parameter's stream. The last three parameters are optional.
///
/// Returns a tuple containing: (found, key_index, key_time, key_timescale)
pub fn find_keyframe_time(&self, effect_ref: impl AsPtr<ae_sys::PF_ProgPtr>, param_index: i32, what_time: i32, time_scale: u32, time_dir: TimeDir) -> Result<(bool, i32, i32, u32), Error> {
let mut found: ae_sys::PF_Boolean = 0;
let mut key_index: ae_sys::PF_KeyIndex = 0;
let mut key_time: ae_sys::A_long = 0;
let mut key_timescale: ae_sys::A_u_long = 0;
call_suite_fn!(self, PF_FindKeyframeTime, effect_ref.as_ptr(), param_index, what_time, time_scale, time_dir.into(), &mut found, &mut key_index, &mut key_time, &mut key_timescale)?;
Ok((
found != 0,
key_index as i32,
key_time as i32,
key_timescale as u32
))
}
/// Returns the number of keyframes in the parameter's stream.
pub fn keyframe_count(&self, effect_ref: impl AsPtr<ae_sys::PF_ProgPtr>, param_index: i32) -> Result<i32, Error> {
Ok(call_suite_fn_single!(self, PF_GetKeyframeCount -> ae_sys::PF_KeyIndex, effect_ref.as_ptr(), param_index)? as i32)
}
/// Checks a keyframe for the specified parameter out of our keyframe database. `param_index` is zero-based. You can request time, timescale, or neither; useful if you're performing your own motion blur.
pub fn checkout_keyframe(&self, effect_ref: impl AsPtr<ae_sys::PF_ProgPtr>, param_index: i32, key_index: i32) -> Result<(i32, u32, ae_sys::PF_ParamDef), Error> {
let mut key_time: ae_sys::A_long = 0;
let mut key_timescale: ae_sys::A_u_long = 0;
let param = call_suite_fn_single!(self, PF_CheckoutKeyframe -> ae_sys::PF_ParamDef, effect_ref.as_ptr(), param_index, key_index, &mut key_time, &mut key_timescale)?;
Ok((key_time, key_timescale, param))
}
/// All calls to `checkout_keyframe` must be balanced with this check-in, or pain will ensue.
pub fn checkin_keyframe(&self, effect_ref: impl AsPtr<ae_sys::PF_ProgPtr>, mut param: ae_sys::PF_ParamDef) -> Result<(), Error> {
call_suite_fn!(self, PF_CheckinKeyframe, effect_ref.as_ptr(), &mut param as *mut _)
}
/// Returns the time (and timescale) of the specified keyframe.
pub fn key_index_to_time(&self, effect_ref: impl AsPtr<ae_sys::PF_ProgPtr>, param_index: i32, key_index: i32) -> Result<(i32, u32), Error> {
let (time, timesale) = call_suite_fn_double!(self, PF_KeyIndexToTime -> ae_sys::A_long, ae_sys::A_u_long, effect_ref.as_ptr(), param_index, key_index)?;
Ok((
time as i32,
timesale as u32
))
}
}
define_suite!(
/// Use this suite to get floating point values for angle parameters.
AngleParamSuite,
PF_AngleParamSuite1,
kPFAngleParamSuite,
kPFAngleParamSuiteVersion1
);
impl AngleParamSuite {
/// Acquire this suite from the host. Returns error if the suite is not available.
/// Suite is released on drop.
pub fn new() -> Result<Self, Error> {
crate::Suite::new()
}
pub fn floating_point_value_from_angle_def(&self, effect_ref: impl AsPtr<ae_sys::PF_ProgPtr>, angle_def: *const ae_sys::PF_ParamDef) -> Result<f64, Error> {
call_suite_fn_single!(self, PF_GetFloatingPointValueFromAngleDef -> ae_sys::A_FpLong, effect_ref.as_ptr(), angle_def)
}
}
define_suite!(
/// Use this suite to get floating point values for color parameters.
ColorParamSuite,
PF_ColorParamSuite1,
kPFColorParamSuite,
kPFColorParamSuiteVersion1
);
impl ColorParamSuite {
/// Acquire this suite from the host. Returns error if the suite is not available.
/// Suite is released on drop.
pub fn new() -> Result<Self, Error> {
crate::Suite::new()
}
pub fn floating_point_value_from_color_def(&self, effect_ref: impl AsPtr<ae_sys::PF_ProgPtr>, color_def: *const ae_sys::PF_ParamDef) -> Result<PixelF32, Error> {
call_suite_fn_single!(self, PF_GetFloatingPointColorFromColorDef -> ae_sys::PF_PixelFloat, effect_ref.as_ptr(), color_def)
}
}
define_suite!(
/// Use this suite to get floating point values for point parameters.
PointParamSuite,
PF_PointParamSuite1,
kPFPointParamSuite,
kPFPointParamSuiteVersion1
);
impl PointParamSuite {
/// Acquire this suite from the host. Returns error if the suite is not available.
/// Suite is released on drop.
pub fn new() -> Result<Self, Error> {
crate::Suite::new()
}
pub fn floating_point_value_from_point_def(&self, effect_ref: impl AsPtr<ae_sys::PF_ProgPtr>, point_def: *const ae_sys::PF_ParamDef) -> Result<ae_sys::A_FloatPoint, Error> {
call_suite_fn_single!(self, PF_GetFloatingPointValueFromPointDef -> ae_sys::A_FloatPoint, effect_ref.as_ptr(), point_def)
}
}
// ――――――――――――――――――――――――――――――――――――――― Types ――――――――――――――――――――――――――――――――――――――――
pub const PARAM_INDEX_NONE: i32 = ae_sys::PF_ParamIndex_NONE;
/// check every parameter, including every layer referred to by a layer parameter
pub const PARAM_INDEX_CHECK_ALL: i32 = ae_sys::PF_ParamIndex_CHECK_ALL;
/// omit all layers. Pass a specific layer parameter index to include that as the only layer parameter tested.
pub const PARAM_INDEX_CHECK_ALL_EXCEPT_LAYER_PARAMS: i32 = ae_sys::PF_ParamIndex_CHECK_ALL_EXCEPT_LAYER_PARAMS;
/// Similar to CHECK_ALL, but honor PF_ParamFlag_EXCLUDE_FROM_HAVE_INPUTS_CHANGED.
pub const PARAM_INDEX_CHECK_ALL_HONOR_EXCLUDE: i32 = ae_sys::PF_ParamIndex_CHECK_ALL_HONOR_EXCLUDE;
define_enum! {
ae_sys::PF_TimeDir,
TimeDir {
GreaterThan = ae_sys::PF_TimeDir_GREATER_THAN,
LessThan = ae_sys::PF_TimeDir_LESS_THAN,
GreaterThanOrEqual = ae_sys::PF_TimeDir_GREATER_THAN_OR_EQUAL,
LessThanOrEqual = ae_sys::PF_TimeDir_LESS_THAN_OR_EQUAL,
}
}