after_effects/pf/
parameters.rs

1use super::*;
2use std::ffi::{ CStr, CString };
3use ae_sys::PF_PathID;
4use serde::{de::DeserializeOwned, Serialize};
5
6define_enum! {
7    ae_sys::PF_ParamType,
8    ParamType {
9        Reserved      = ae_sys::PF_Param_RESERVED,
10        Layer         = ae_sys::PF_Param_LAYER,
11        Slider        = ae_sys::PF_Param_SLIDER,
12        FixSlider     = ae_sys::PF_Param_FIX_SLIDER,
13        Angle         = ae_sys::PF_Param_ANGLE,
14        CheckBox      = ae_sys::PF_Param_CHECKBOX,
15        Color         = ae_sys::PF_Param_COLOR,
16        Point         = ae_sys::PF_Param_POINT,
17        PopUp         = ae_sys::PF_Param_POPUP,
18        Custom        = ae_sys::PF_Param_CUSTOM,
19        NoData        = ae_sys::PF_Param_NO_DATA,
20        FloatSlider   = ae_sys::PF_Param_FLOAT_SLIDER,
21        ArbitraryData = ae_sys::PF_Param_ARBITRARY_DATA,
22        Path          = ae_sys::PF_Param_PATH,
23        GroupStart    = ae_sys::PF_Param_GROUP_START,
24        GroupEnd      = ae_sys::PF_Param_GROUP_END,
25        Button        = ae_sys::PF_Param_BUTTON,
26        Reserved2     = ae_sys::PF_Param_RESERVED2,
27        Reserved3     = ae_sys::PF_Param_RESERVED3,
28        Point3D       = ae_sys::PF_Param_POINT_3D,
29    }
30}
31
32bitflags! {
33    pub struct ParamUIFlags: ae_sys::A_long {
34        const NONE = ae_sys::PF_PUI_NONE as ae_sys::A_long;
35        /// Effect has custom UI and wants events for this params' title (portion visible when twirled up).
36        const TOPIC = ae_sys::PF_PUI_TOPIC as ae_sys::A_long;
37        /// Effect has custom UI and wants events for this params' control (portion invisible when twirled up).
38        const CONTROL = ae_sys::PF_PUI_CONTROL as ae_sys::A_long;
39        /// Param will be used as UI only, no data.
40        const CONTROL_ONLY = ae_sys::PF_PUI_STD_CONTROL_ONLY as ae_sys::A_long;
41        /// Stop param from appearing in Effect Controls (which in PPro also means you won't see a keyframe track there).
42        const NO_ECW_UI = ae_sys::PF_PUI_NO_ECW_UI as ae_sys::A_long;
43        /// Draw a thick separating line above this param; not used by Ae.
44        const ECW_SEPARATOR = ae_sys::PF_PUI_ECW_SEPARATOR as ae_sys::A_long;
45        /// Disable (gray-out) UI for this parameter.
46        const DISABLED = ae_sys::PF_PUI_DISABLED as ae_sys::A_long;
47        /// Ae will not erase the ECW topic, it's up to the FX to erase/draw every pixel.
48        /// Handy if FX author implements an offscreen, prevents flashing.
49        const DO_NOT_ERASE_TOPIC = ae_sys::PF_PUI_DONT_ERASE_TOPIC as ae_sys::A_long;
50        const DO_NOT_ERASE_CONTROL = ae_sys::PF_PUI_DONT_ERASE_CONTROL as ae_sys::A_long;
51        /// Display as a radio-button group; only valid for PF_Param_POPUP; ignored by Ae.
52        const RADIO_BUTTON = ae_sys::PF_PUI_RADIO_BUTTON as ae_sys::A_long;
53        /// In Ae as of CS6, this hides the parameter UI in both the Effect Controls and Timeline.
54        /// in Premiere since earlier than that, this hides the parameter UI in the Effect Controls,
55        /// which includes the keyframe track; for PPro only, the flag is dynamic and can be cleared to make the parameter visible again.
56        const INVISIBLE = ae_sys::PF_PUI_INVISIBLE as ae_sys::A_long;
57    }
58}
59
60bitflags! {
61    pub struct ParamFlag: ae_sys::A_long {
62        /// If this is passed, the parameter will not be allowed to vary over time -- no keyframe controller will appear at the right.
63        const CANNOT_TIME_VARY = ae_sys::PF_ParamFlag_CANNOT_TIME_VARY as ae_sys::A_long;
64        /// If this is passed, parameter values are not interpolated between. You can still use no interp and discontinuous interp.
65        const CANNOT_INTERP = ae_sys::PF_ParamFlag_CANNOT_INTERP as ae_sys::A_long;
66        /// Set this flag if you want the parameter's twirly arrow in the Effect Control Window to be twirled up by default when the effect is first applied.
67        /// New in AE 4.0: you can now set & clear this bit when handling `PF_Cmd_UPDATE_PARAMS_UI` and `PF_Cmd_USER_CHANGED_PARAM` messages, so as to twirl your parameters and groups up and down at will.
68        ///
69        /// Same as [`ParamFlag::START_COLLAPSED`]
70        const TWIRLY = ae_sys::PF_ParamFlag_COLLAPSE_TWIRLY as ae_sys::A_long;
71        /// If this is passed, PF_Cmd_USER_CHANGED_PARAM will be sent when this parameter changes.
72        const SUPERVISE = ae_sys::PF_ParamFlag_SUPERVISE as ae_sys::A_long;
73        /// Set this flag if you want the parameter's twirly arrow in the Effect Control Window to be twirled up by default when the effect is first applied.
74        /// New in AE 4.0: you can now set & clear this bit when handling `PF_Cmd_UPDATE_PARAMS_UI` and `PF_Cmd_USER_CHANGED_PARAM` messages, so as to twirl your parameters and groups up and down at will.
75        ///
76        /// Same as [`ParamFlag::TWIRLY`]
77        const START_COLLAPSED = ae_sys::PF_ParamFlag_START_COLLAPSED as ae_sys::A_long;
78        /// This only affects the loading of projects saved with an older version of the effect which lacks parameters added later.
79        /// When set, the PF_ParamDef "value" field set in PF_ADD_PARAM will be used to initialize the missing parameter,
80        /// but the "dephault" field will still be used for initial value of the parameter when the effect is newly applied or reset.
81        /// This is useful for when you want a parameter to default to one value but need it set to something else to preserve rendering behaviour for older projects.
82        ///
83        /// This flag is valid for all PF_Param types except PF_Param_LAYER
84        const USE_VALUE_FOR_OLD_PROJECTS = ae_sys::PF_ParamFlag_USE_VALUE_FOR_OLD_PROJECTS as ae_sys::A_long;
85        /// For PF_Param_LAYER, this flag indicates that the layer parameter is to be presented as a track matte. Supported by Premiere, ignored in AE.
86        const LAYER_PARAM_IS_TRACKMATTE = ae_sys::PF_ParamFlag_LAYER_PARAM_IS_TRACKMATTE as ae_sys::A_long;
87        /// See doc for [`pf::suites::ParamUtils::are_states_identical()`].
88        const EXCLUDE_FROM_HAVE_INPUTS_CHANGED = ae_sys::PF_ParamFlag_EXCLUDE_FROM_HAVE_INPUTS_CHANGED as ae_sys::A_long;
89        /// When this param is "un hidden" (cuz it may hide and show), then the GUI is NOT to cause the parameter to be "revealed", ie: it won't twirl down it's parents and scroll it into view
90        const SKIP_REVEAL_WHEN_UNHIDDEN = ae_sys::PF_ParamFlag_SKIP_REVEAL_WHEN_UNHIDDEN as ae_sys::A_long;
91    }
92}
93
94bitflags! {
95    pub struct ChangeFlag: ae_sys::A_long {
96        const NONE = ae_sys::PF_ChangeFlag_NONE as ae_sys::A_long;
97        /// Set this flag for each param whose value you change when handling a `PF_Cmd_USER_CHANGED_PARAM` or specific `PF_Cmd_EVENT` events (`PF_Event_DO_CLICK`, `PF_Event_DRAG`, & `PF_Event_KEYDOWN`).
98        /// If set during `PF_Cmd_EVENT`, but sure to also set `PF_EO_HANDLED_EVENT` before returning.
99        ///
100        /// You can change as many params as you want at once. These changes are undoable and re-doable by the user.
101        ///
102        /// Exception: do not set PF_PUI_STD_CONTROL_ONLY param values with this flag, use PF_UpdateParamUI() instead.
103        const CHANGED_VALUE = ae_sys::PF_ChangeFlag_CHANGED_VALUE as ae_sys::A_long;
104        /// Not yet implemented.  Same restrictions as PF_ChangeFlag_CHANGED_VALUE.
105        const SET_TO_VARY = ae_sys::PF_ChangeFlag_SET_TO_VARY as ae_sys::A_long;
106        /// Not yet implemented.  Same restrictions as PF_ChangeFlag_CHANGED_VALUE.
107        const SET_TO_CONSTANT = ae_sys::PF_ChangeFlag_SET_TO_CONSTANT as ae_sys::A_long;
108    }
109}
110
111bitflags! {
112    pub struct ValueDisplayFlag: u16 {
113        const NONE = ae_sys::PF_ValueDisplayFlag_NONE as u16;
114        /// Append % to value display for A_FpShort sliders (for fixed-point sliders, also maps range into 0-100%)
115        const PERCENT = ae_sys::PF_ValueDisplayFlag_PERCENT as u16;
116        /// Assume 0..1 is a pixel value, either 0..255,  0..32768, or 0..1.0 in UI (value will always be 0..1),
117        const PIXEL = ae_sys::PF_ValueDisplayFlag_PIXEL as u16;
118        /// Presentation negates values. eg: a true -5 would be presented as "5", and typing in "22" would store in the model as -22
119        const REVERSE = ae_sys::PF_ValueDisplayFlag_REVERSE as u16;
120    }
121}
122
123bitflags! {
124    pub struct FSliderFlag: u16 {
125        const NONE = ae_sys::PF_FSliderFlag_NONE as u16;
126        /// Works for audio effects only
127        const WANT_PHASE = ae_sys::PF_FSliderFlag_WANT_PHASE as u16;
128    }
129}
130
131// ―――――――――――――――――――――――――――――――――――― Angle ―――――――――――――――――――――――――――――――――――――
132define_param_wrapper! {
133    PF_Param_ANGLE, PF_AngleDef, ad,
134    Param::Angle,
135    AngleDef { },
136    impl value: Fixed,
137}
138impl AngleDef<'_> {
139    pub fn set_default(&mut self, v: f32) -> &mut Self {
140        self.def.dephault = Fixed::from(v).as_fixed();
141        self
142    }
143    pub fn default(&self) -> f32 {
144        Fixed::from_fixed(self.def.dephault).into()
145    }
146    pub fn float_value(&self) -> Result<f64, Error> {
147        if self._in_data.is_null() || self._parent_ptr.is_none() {
148            return Err(Error::InvalidParms);
149        }
150        Ok(pf::suites::AngleParam::new()?
151            .floating_point_value_from_angle_def(unsafe { (*self._in_data).effect_ref }, self._parent_ptr.unwrap())?)
152    }
153}
154// ―――――――――――――――――――――――――――――――――――― Angle ―――――――――――――――――――――――――――――――――――――
155
156// ―――――――――――――――――――――――――――――――――――― Button ―――――――――――――――――――――――――――――――――――――
157define_param_wrapper! {
158    PF_Param_BUTTON, PF_ButtonDef, button_d,
159    Param::Button,
160    ButtonDef {
161        label: CString,
162    },
163    impl label: String,
164}
165// ―――――――――――――――――――――――――――――――――――― Button ―――――――――――――――――――――――――――――――――――――
166
167// ――――――――――――――――――――――――――――――――――― Checkbox ――――――――――――――――――――――――――――――――――――
168define_param_wrapper! {
169    PF_Param_CHECKBOX, PF_CheckBoxDef, bd,
170    Param::CheckBox,
171    CheckBoxDef {
172        label: CString,
173    },
174    impl value: bool,
175    fn init(param) {
176        param.set_label(" ");
177    }
178}
179impl<'a> CheckBoxDef<'_> {
180    pub fn set_default(&mut self, v: bool) -> &mut Self {
181        self.def.dephault = if v { 1 } else { 0 };
182        self
183    }
184    pub fn default(&self) -> bool {
185        self.def.dephault != 0
186    }
187    pub fn set_label(&mut self, v: &str) -> &mut Self {
188        self.label = CString::new(v).unwrap();
189        self.def.u.nameptr = self.label.as_ptr();
190        self
191    }
192    pub fn label(&self) -> &str {
193        unsafe { CStr::from_ptr(self.def.u.nameptr).to_str().unwrap() }
194    }
195}
196// ――――――――――――――――――――――――――――――――――― Checkbox ――――――――――――――――――――――――――――――――――――
197
198// ―――――――――――――――――――――――――――――――――――― Color ――――――――――――――――――――――――――――――――――――――
199define_param_wrapper! {
200    PF_Param_COLOR, PF_ColorDef, cd,
201    Param::Color,
202    ColorDef { },
203    impl value: Pixel8,
204    impl default: Pixel8,
205}
206impl ColorDef<'_> {
207    pub fn float_value(&self) -> Result<PixelF32, Error> {
208        if self._in_data.is_null() || self._parent_ptr.is_none() {
209            return Err(Error::InvalidParms);
210        }
211        Ok(pf::suites::ColorParam::new()?
212            .floating_point_value_from_color_def(unsafe { (*self._in_data).effect_ref }, self._parent_ptr.unwrap())?)
213    }
214}
215// ―――――――――――――――――――――――――――――――――――― Color ――――――――――――――――――――――――――――――――――――――
216
217// ―――――――――――――――――――――――――――――――――――― Slider ―――――――――――――――――――――――――――――――――――――
218define_param_wrapper! {
219    PF_Param_SLIDER, PF_SliderDef, sd,
220    Param::Slider,
221    SliderDef { },
222    impl value: i32,
223    impl default: i32,
224    impl valid_min: i32,
225    impl valid_max: i32,
226    impl slider_min: i32,
227    impl slider_max: i32,
228    impl value_str: ShortString,
229    impl value_desc: ShortString,
230}
231// ―――――――――――――――――――――――――――――――――――― Slider ―――――――――――――――――――――――――――――――――――――
232
233// Adobe recommends not using fixed (point) sliders any more and instead use float sliders.
234// Do not define FixedSliderDef
235
236// ―――――――――――――――――――――――――――――――――― FloatSlider ――――――――――――――――――――――――――――――――――
237define_param_wrapper! {
238    PF_Param_FLOAT_SLIDER, PF_FloatSliderDef, fs_d,
239    Param::FloatSlider,
240    FloatSliderDef { },
241    impl value: f64,
242    impl phase: f64,
243    impl default: f64,
244    impl precision: i16,
245    impl curve_tolerance: f32,
246    impl valid_min: f32,
247    impl valid_max: f32,
248    impl slider_min: f32,
249    impl slider_max: f32,
250    impl value_desc: ShortString,
251}
252impl FloatSliderDef<'_> {
253    pub fn set_display_flags(&mut self, flags: ValueDisplayFlag) -> &mut Self {
254        self.def.display_flags = flags.bits() as _;
255        self
256    }
257    pub fn display_flags(&self) -> ValueDisplayFlag {
258        ValueDisplayFlag::from_bits_truncate(self.def.display_flags as _)
259    }
260    pub fn set_flags(&mut self, flags: FSliderFlag) -> &mut Self {
261        self.def.fs_flags = flags.bits() as _;
262        self
263    }
264    pub fn flags(&self) -> FSliderFlag {
265        FSliderFlag::from_bits_truncate(self.def.fs_flags as _)
266    }
267    pub fn set_exponent(&mut self, v: f32) -> &mut Self {
268        self.def.exponent = v;
269        self.def.useExponent = 1;
270        self
271    }
272    pub fn exponent(&self) -> Option<f32> {
273        if self.def.useExponent == 1 {
274            Some(self.def.exponent)
275        } else {
276            None
277        }
278    }
279}
280// ―――――――――――――――――――――――――――――――――― FloatSlider ――――――――――――――――――――――――――――――――――
281
282// ―――――――――――――――――――――――――――――――――――― Path ―――――――――――――――――――――――――――――――――――――――
283define_param_wrapper! {
284    PF_Param_PATH, PF_PathDef, path_d,
285    Param::Path,
286    /// Path parameters give access to the mask/path/shapes of the layer on which the effect is applied.
287    /// For more information on how to use these paths, see the `PF_PathQuerySuite`, and the `PF_PathDataSuite`
288    /// * `path_id` - to be used with `PF_CheckoutPath()` note that path_id != `PF_PathID_NONE` does not guarantee that `PF_CheckoutPath` will return a valid path (it may have been deleted)
289    /// * `default` - 0 means that the default is NONE, other numbers are the 1-based index of the path, if the path doesn't exist, the `path_id` value will be `PF_PathID_NONE`.
290    PathDef { },
291    impl path_id: PF_PathID,
292    impl default: i32,
293}
294// ―――――――――――――――――――――――――――――――――――― Path ―――――――――――――――――――――――――――――――――――――――
295
296// ―――――――――――――――――――――――――――――――――――― Point ――――――――――――――――――――――――――――――――――――――
297define_param_wrapper! {
298    PF_Param_POINT, PF_PointDef, td,
299    Param::Point,
300    /// The values for the point use the source's coordinate system, with the origin at the top left.
301    ///
302    /// The defaults are expressed as percentages with the origin at the top left.
303    /// The percent can be negative, but should not be smaller than -600%. It should not be greater than 600%.
304    ///
305    /// If restrict_bounds is `true`, the user will not be allowed to specify points outside the bounds of the layer to which they are applying the effect.
306    /// If this is `true`, the dephaults should be between 0.0 and 100.0.
307    PointDef { },
308    impl restrict_bounds: bool,
309    impl x_value: Fixed,
310    impl y_value: Fixed,
311}
312impl PointDef<'_> {
313    pub fn set_default_x(&mut self, v: f32) -> &mut Self { self.def.x_dephault = Fixed::from(v).as_fixed(); self }
314    pub fn set_default_y(&mut self, v: f32) -> &mut Self { self.def.y_dephault = Fixed::from(v).as_fixed(); self }
315    pub fn default_x(&self) -> f32 { Fixed::from_fixed(self.def.x_dephault).into() }
316    pub fn default_y(&self) -> f32 { Fixed::from_fixed(self.def.y_dephault).into() }
317
318    pub fn set_default(&mut self, v: (f32, f32)) -> &mut Self {
319        self.def.x_dephault = Fixed::from(v.0).as_fixed();
320        self.def.y_dephault = Fixed::from(v.1).as_fixed();
321        self
322    }
323    pub fn default(&self) -> (f32, f32) {
324        (Fixed::from_fixed(self.def.x_dephault).into(), Fixed::from_fixed(self.def.y_dephault).into())
325    }
326
327    pub fn set_value(&mut self, v: (f32, f32)) -> &mut Self {
328        self.def.x_value = Fixed::from(v.0).as_fixed();
329        self.def.y_value = Fixed::from(v.1).as_fixed();
330        self
331    }
332    pub fn value(&self) -> (f32, f32) {
333        (Fixed::from_fixed(self.def.x_value).into(), Fixed::from_fixed(self.def.y_value).into())
334    }
335    pub fn float_value(&self) -> Result<ae_sys::A_FloatPoint, Error> {
336        if self._in_data.is_null() || self._parent_ptr.is_none() {
337            return Err(Error::InvalidParms);
338        }
339        Ok(pf::suites::PointParam::new()?
340            .floating_point_value_from_point_def(unsafe { (*self._in_data).effect_ref }, self._parent_ptr.unwrap())?)
341    }
342}
343
344define_param_wrapper! {
345    PF_Param_POINT_3D, PF_Point3DDef, point3d_d,
346    Param::Point3D,
347    /// Just like POINT, with an extra dimension. Supported in AE starting with version 10.5 (CS 5.5).
348    /// * `x_dephault` - percentage of layer width; note: use 50 for halfway, not 0.5; this matches the old PF_PointDef behavior
349    /// * `y_dephault` - percentage of layer height
350    /// * `z_dephault` - percentage of layer _height_ (since typical layers are zero depth)
351    Point3DDef { },
352    impl x_value: f64,
353    impl y_value: f64,
354    impl z_value: f64,
355}
356impl Point3DDef<'_> {
357    pub fn set_default_x(&mut self, v: f64) -> &mut Self { self.def.x_dephault = v; self }
358    pub fn set_default_y(&mut self, v: f64) -> &mut Self { self.def.y_dephault = v; self }
359    pub fn set_default_z(&mut self, v: f64) -> &mut Self { self.def.z_dephault = v; self }
360    pub fn default_x(&self) -> f64 { self.def.x_dephault }
361    pub fn default_y(&self) -> f64 { self.def.y_dephault }
362    pub fn default_z(&self) -> f64 { self.def.z_dephault }
363
364    pub fn set_default(&mut self, v: (f64, f64, f64)) -> &mut Self {
365        self.def.x_dephault = v.0;
366        self.def.y_dephault = v.1;
367        self.def.z_dephault = v.2;
368        self
369    }
370    pub fn default(&self) -> (f64, f64, f64) {
371        (self.def.x_dephault, self.def.y_dephault, self.def.z_dephault)
372    }
373
374    pub fn set_value(&mut self, v: (f64, f64, f64)) -> &mut Self {
375        self.def.x_value = v.0;
376        self.def.y_value = v.1;
377        self.def.z_value = v.2;
378        self
379    }
380    pub fn value(&self) -> (f64, f64, f64) {
381        (self.def.x_value, self.def.y_value, self.def.z_value)
382    }
383}
384// ―――――――――――――――――――――――――――――――――――― Point ――――――――――――――――――――――――――――――――――――――
385
386// ―――――――――――――――――――――――――――――――――――― Popup ―――――――――――――――――――――――――――――――――――――
387define_param_wrapper! {
388    PF_Param_POPUP, PF_PopupDef, pd,
389    Param::Popup,
390    PopupDef {
391        options: CString,
392    },
393    impl value: i32,
394    impl default: i32,
395}
396impl<'a> PopupDef<'a> {
397    pub fn set_options(&mut self, options: &[&str]) {
398        // Build a string in the format "list|of|choices|", the format Ae expects.
399        self.options = CString::new(options.join("|")).unwrap();
400        self.def.u.namesptr = self.options.as_ptr();
401        self.def.num_choices = options.len().try_into().unwrap();
402    }
403    pub fn options(&self) -> Vec<&str> {
404        let options = unsafe { CStr::from_ptr(self.def.u.namesptr).to_str().unwrap() };
405        options.split('|').collect()
406    }
407}
408// ―――――――――――――――――――――――――――――――――――― Popup ―――――――――――――――――――――――――――――――――――――
409
410// ―――――――――――――――――――――――――――――――――――― Layer ―――――――――――――――――――――――――――――――――――――
411define_param_wrapper! {
412    PF_Param_LAYER, PF_LayerDef, ld,
413    Param::Layer,
414    LayerDef { },
415}
416impl<'a> LayerDef<'a> {
417    pub fn set_default_to_this_layer(&mut self) {
418        self.def.dephault = ae_sys::PF_LayerDefault_MYSELF;
419    }
420    pub fn value(&self) -> Option<Layer> {
421        if self.def.data.is_null() {
422            None
423        } else {
424            Some(Layer::from_raw(&*self.def as *const _ as _, self._in_data, None))
425        }
426    }
427}
428// ―――――――――――――――――――――――――――――――――――― Layer ―――――――――――――――――――――――――――――――――――――
429
430// ―――――――――――――――――――――――――――――――――――― Null ―――――――――――――――――――――――――――――――――――――
431#[allow(dead_code)]
432pub struct NullDef<'a>(&'a ());
433impl<'a> NullDef<'a> {
434    pub fn new() -> Self {
435        Self(&())
436    }
437}
438impl<'p> Into<Param<'p>> for NullDef<'p> {
439    fn into(self) -> Param<'p> {
440        Param::Null(self)
441    }
442}
443// ―――――――――――――――――――――――――――――――――――― Null ―――――――――――――――――――――――――――――――――――――
444
445// ―――――――――――――――――――――――――――――――――― Arbitrary ―――――――――――――――――――――――――――――――――――
446define_param_wrapper! {
447    PF_Param_ARBITRARY_DATA, PF_ArbitraryDef, arb_d,
448    Param::Arbitrary,
449    ArbitraryDef { },
450    impl pad: i16,
451}
452impl ArbitraryDef<'_> {
453    pub fn set_default<T>(&mut self, value: T) -> Result<&mut Self, Error> {
454        self.def.dephault = Handle::into_raw(Handle::new(value)?);
455        Ok(self)
456    }
457
458    pub fn set_value<T>(&mut self, value: T) -> Result<&mut Self, Error> {
459        if !self.def.value.is_null() {
460            let _ = Handle::<T>::from_raw(self.def.value, true);
461        }
462        self.def.value = Handle::into_raw(Handle::new(value)?);
463        self.set_value_changed();
464        Ok(self)
465    }
466    pub fn value<T>(&self) -> Result<BorrowedHandleLock<T>, Error> {
467        if self.def.value.is_null() {
468            return Err(Error::InvalidParms);
469        }
470        BorrowedHandleLock::<T>::from_raw(self.def.value)
471    }
472
473    pub fn set_refcon(&mut self, refcon: *mut std::ffi::c_void) -> &mut Self {
474        self.def.refconPV = refcon as _;
475        self
476    }
477}
478// ―――――――――――――――――――――――――――――――――― Arbitrary ―――――――――――――――――――――――――――――――――――
479
480pub trait ArbitraryData<T> {
481    fn interpolate(&self, other: &T, value: f64) -> T;
482}
483
484define_struct_wrapper!(ArbParamsExtra, PF_ArbParamsExtra);
485
486impl std::fmt::Debug for ArbParamsExtra {
487    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
488        f.debug_struct("ArbParamsExtra")
489            .field("id", &self.id())
490            .field("refcon", &self.refcon())
491            .field("which_function", &self.which_function())
492            .finish()
493    }
494}
495
496impl ArbParamsExtra {
497    pub fn id(&self) -> i16 {
498        self.as_ref().id as _
499    }
500
501    pub fn refcon(&self) -> *mut std::ffi::c_void {
502        unsafe { self.as_ref().u.new_func_params.refconPV }
503    }
504
505    pub fn which_function(&self) -> u32 {
506        self.as_ref().which_function as _
507    }
508
509    pub fn dispatch<T, P>(&mut self, param: P) -> Result<(), Error>
510    where T: ArbitraryData<T> + Default + DeserializeOwned + Serialize + PartialEq + PartialOrd,
511          P: Eq + PartialEq + Hash + Copy + Debug
512    {
513        let param_id = Parameters::param_id(param) as i16;
514        if self.id() != param_id {
515            // Not our param, nothing to do
516            return Ok(());
517        }
518        match self.as_ref().which_function as _ {
519            ae_sys::PF_Arbitrary_NEW_FUNC => unsafe {
520                assert!(!self.as_ref().u.new_func_params.arbPH.is_null());
521                // log::info!("NEW FUNC");
522                // Create a new instance, serialize it to a Vec<u8>
523                // pass it to a FlatHandle and turn that into a raw
524                // Ae handle that we stash in the PF_ArbParamsExtra
525                // struct wrapper.
526                self.as_ref()
527                    .u
528                    .new_func_params
529                    .arbPH
530                    .write(Handle::into_raw(Handle::<T>::new(T::default())?));
531            },
532
533            ae_sys::PF_Arbitrary_DISPOSE_FUNC => {
534                // log::info!("DISPOSE_FUNC");
535
536                // Create a new handle from the raw Ae handle. This
537                // disposes then handle when it goes out of scope
538                // and is dropped just after.
539                if unsafe { !self.as_ref().u.dispose_func_params.arbH.is_null() } {
540                    Handle::<T>::from_raw(unsafe { self.as_ref().u.dispose_func_params.arbH }, true)?;
541                }
542            }
543
544            ae_sys::PF_Arbitrary_COPY_FUNC => unsafe {
545                // log::info!("COPY_FUNC");
546                // Create a new handle wraper from the sources,
547                // get a referece to that as a slice create a new
548                // handle from that and write that to the
549                // destination pointer.
550
551                if self.as_ref().u.copy_func_params.src_arbH.is_null() {
552                    // Create a new default value
553                    self.as_ref()
554                        .u
555                        .copy_func_params
556                        .dst_arbPH
557                        .write(Handle::into_raw(Handle::<T>::new(T::default())?));
558                    return Ok(());
559                }
560
561                let mut src_handle = Handle::<T>::from_raw(self.as_ref().u.copy_func_params.src_arbH, false)?;
562                let lock = src_handle.lock()?;
563
564                let serialized = bincode::serialize::<T>(lock.as_ref()?).map_err(|_| Error::InternalStructDamaged)?;
565                let deserialized = bincode::deserialize::<T>(&serialized).map_err(|_| Error::InternalStructDamaged)?;
566                let new_handle = Handle::<T>::new(deserialized)?;
567
568                self.as_ref()
569                    .u
570                    .copy_func_params
571                    .dst_arbPH
572                    .write(Handle::into_raw(new_handle));
573            },
574
575            ae_sys::PF_Arbitrary_FLAT_SIZE_FUNC => unsafe {
576                // log::info!("FLAT_SIZE_FUNC");
577
578                let mut handle = Handle::<T>::from_raw(self.as_ref().u.flat_size_func_params.arbH, false)?;
579                let lock = handle.lock()?;
580
581                let serialized = bincode::serialize::<T>(lock.as_ref()?).map_err(|_| Error::InternalStructDamaged)?;
582
583                self.as_ref()
584                    .u
585                    .flat_size_func_params
586                    .flat_data_sizePLu
587                    .write(serialized.len() as _);
588            },
589
590            ae_sys::PF_Arbitrary_FLATTEN_FUNC => unsafe {
591                // log::info!("FLATTEN_FUNC");
592                assert!(!self.as_ref().u.unflatten_func_params.flat_dataPV.is_null());
593
594                let mut handle = Handle::<T>::from_raw(self.as_ref().u.flatten_func_params.arbH, false)?;
595                let lock = handle.lock()?;
596
597                let serialized = bincode::serialize::<T>(lock.as_ref()?).map_err(|_| Error::InternalStructDamaged)?;
598
599                assert!(
600                    serialized.len() <= self.as_ref().u.flatten_func_params.buf_sizeLu as _
601                );
602
603                std::ptr::copy_nonoverlapping(
604                    serialized.as_ptr(),
605                    self.as_ref().u.flatten_func_params.flat_dataPV as _,
606                    serialized.len(),
607                );
608            }
609
610            ae_sys::PF_Arbitrary_UNFLATTEN_FUNC => unsafe {
611                // log::info!("UNFLATTEN_FUNC");
612                assert!(!self.as_ref().u.unflatten_func_params.flat_dataPV.is_null());
613
614                let serialized = std::slice::from_raw_parts(
615                    self.as_ref().u.unflatten_func_params.flat_dataPV as *mut u8,
616                    self.as_ref().u.unflatten_func_params.buf_sizeLu as _
617                );
618                let t = bincode::deserialize::<T>(serialized).map_err(|_| Error::InternalStructDamaged)?;
619                let handle = Handle::<T>::new(t)?;
620
621                self.as_ref()
622                    .u
623                    .unflatten_func_params
624                    .arbPH
625                    .write(Handle::into_raw(handle));
626            },
627
628            ae_sys::PF_Arbitrary_INTERP_FUNC => unsafe {
629                // log::info!("INTERP_FUNC");
630
631                let mut left = Handle::<T>::from_raw(self.as_ref().u.interp_func_params.left_arbH, false)?;
632                let left_lock = left.lock()?;
633
634                let mut right = Handle::<T>::from_raw(self.as_ref().u.interp_func_params.right_arbH, false)?;
635                let right_lock = right.lock()?;
636
637                let interpolated = Handle::<T>::new(
638                    left_lock.as_ref()?.interpolate(right_lock.as_ref()?, self.as_ref().u.interp_func_params.tF)
639                )?;
640
641                self.as_ref()
642                    .u
643                    .interp_func_params
644                    .interpPH
645                    .write(Handle::into_raw(interpolated));
646            },
647
648            ae_sys::PF_Arbitrary_COMPARE_FUNC => {
649                // log::info!("COMPARE_FUNC");
650
651                let mut handle_a = Handle::<T>::from_raw(unsafe { self.as_ref().u.compare_func_params.a_arbH }, false)?;
652                let handle_a_lock = handle_a.lock()?;
653                let a = handle_a_lock.as_ref()?;
654
655                let mut handle_b = Handle::<T>::from_raw(unsafe { self.as_ref().u.compare_func_params.b_arbH }, false)?;
656                let handle_b_lock = handle_b.lock()?;
657                let b = handle_b_lock.as_ref()?;
658
659                if a < b {
660                    unsafe {
661                        self.as_ref()
662                            .u
663                            .compare_func_params
664                            .compareP
665                            .write(ae_sys::PF_ArbCompare_LESS as _);
666                    }
667                } else if a > b {
668                    unsafe {
669                        self.as_ref()
670                            .u
671                            .compare_func_params
672                            .compareP
673                            .write(ae_sys::PF_ArbCompare_MORE as _);
674                    }
675                } else if a == b {
676                    unsafe {
677                        self.as_ref()
678                            .u
679                            .compare_func_params
680                            .compareP
681                            .write(ae_sys::PF_ArbCompare_EQUAL as _);
682                    }
683                } else {
684                    unsafe {
685                        self.as_ref()
686                            .u
687                            .compare_func_params
688                            .compareP
689                            .write(ae_sys::PF_ArbCompare_NOT_EQUAL as _);
690                    }
691                }
692            }
693
694            ae_sys::PF_Arbitrary_PRINT_SIZE_FUNC => unsafe {
695                // log::info!("PRINT_SIZE_FUNC");
696
697                let mut handle = Handle::<T>::from_raw(self.as_ref().u.print_size_func_params.arbH, false)?;
698                let lock = handle.lock()?;
699
700                let serialized = serde_json::to_string::<T>(lock.as_ref()?).map_err(|_| Error::InternalStructDamaged)?;
701                let cstr = std::ffi::CString::new(serialized).unwrap();
702
703                self.as_ref().u.print_size_func_params.print_sizePLu.write(
704                    cstr.as_bytes_with_nul().len() as _,
705                );
706            },
707
708            // Print arbitrary data into a string as JSON.
709            // Note that we could use any text-based serializer here.
710            ae_sys::PF_Arbitrary_PRINT_FUNC => unsafe {
711                // log::info!("PRINT_FUNC");
712
713                let mut handle = Handle::<T>::from_raw(self.as_ref().u.print_func_params.arbH, false)?;
714                let lock = handle.lock()?;
715
716                let serialized = serde_json::to_string::<T>(lock.as_ref()?).map_err(|_| Error::InternalStructDamaged)?;
717                let cstr = std::ffi::CString::new(serialized).unwrap();
718                let cstr = cstr.as_bytes_with_nul();
719
720                if cstr.len() <= self.as_ref().u.print_func_params.print_sizeLu as _ && self.as_ref().u.print_func_params.print_flags == 0 {
721                    std::ptr::copy_nonoverlapping(
722                        cstr.as_ptr(),
723                        self.as_ref().u.print_func_params.print_bufferPC as _,
724                        cstr.len(),
725                    );
726                }
727            }
728            ae_sys::PF_Arbitrary_SCAN_FUNC => unsafe {
729                // log::info!("SCAN_FUNC");
730
731                let cstr = CStr::from_ptr(self.as_ref().u.scan_func_params.bufPC).to_str().map_err(|_| Error::InternalStructDamaged)?;
732
733                let t = serde_json::from_str::<T>(cstr).map_err(|_| Error::InternalStructDamaged)?;
734                let handle = Handle::<T>::new(t)?;
735
736                self.as_ref()
737                    .u
738                    .scan_func_params
739                    .arbPH
740                    .write(Handle::into_raw(handle));
741            },
742            _ => {
743                return Err(Error::Generic);
744            }
745        }
746        Ok(())
747    }
748}
749
750macro_rules! define_param_cast {
751    ($name:tt, $enm:ident, $type:ty) => {
752        paste::item! {
753            pub fn [<as_ $name>]<'a>(&'a self) -> Result<$type<'a>, Error> where 'p: 'a {
754                match self.as_param()? {
755                    Param::$enm(x) => Ok(x),
756                    x => {
757                        log::error!("Invalid param type! Requested {:?}, but the param is {:?}", stringify!($name), x);
758                        Err(Error::InvalidParms)
759                    }
760                }
761            }
762            pub fn [<as_ $name _mut>]<'a>(&'a mut self) -> Result<$type<'a>, Error> where 'p: 'a {
763                match self.as_param_mut()? {
764                    Param::$enm(x) => Ok(x),
765                    x => {
766                        log::error!("Invalid param type! Requested {:?}, but the param is {:?}", stringify!($name), x);
767                        Err(Error::InvalidParms)
768                    }
769                }
770            }
771        }
772    };
773}
774
775pub enum Param<'p> {
776    Angle(AngleDef<'p>),
777    Arbitrary(ArbitraryDef<'p>),
778    Button(ButtonDef<'p>),
779    CheckBox(CheckBoxDef<'p>),
780    Color(ColorDef<'p>),
781    FloatSlider(FloatSliderDef<'p>),
782    Path(PathDef<'p>),
783    Point(PointDef<'p>),
784    Point3D(Point3DDef<'p>),
785    Popup(PopupDef<'p>),
786    Slider(SliderDef<'p>),
787    Layer(LayerDef<'p>),
788    Null(NullDef<'p>),
789}
790
791impl Debug for Param<'_> {
792    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
793        match self {
794            Param::Angle(_)       => write!(f, "Angle"),
795            Param::Arbitrary(_)   => write!(f, "Arbitrary"),
796            Param::Button(_)      => write!(f, "Button"),
797            Param::CheckBox(_)    => write!(f, "CheckBox"),
798            Param::Color(_)       => write!(f, "Color"),
799            Param::FloatSlider(_) => write!(f, "FloatSlider"),
800            Param::Path(_)        => write!(f, "Path"),
801            Param::Point(_)       => write!(f, "Point"),
802            Param::Point3D(_)     => write!(f, "Point3D"),
803            Param::Popup(_)       => write!(f, "Popup"),
804            Param::Slider(_)      => write!(f, "Slider"),
805            Param::Layer(_)       => write!(f, "Layer"),
806            Param::Null(_)        => write!(f, "Null"),
807        }
808    }
809}
810
811#[derive(Clone)]
812pub struct ParamDef<'p> {
813    param_def: Ownership<'p, ae_sys::PF_ParamDef>,
814    checkin_on_drop: bool,
815    index: Option<i32>,
816    in_data: InData,
817}
818
819impl<'p> ParamDef<'p> {
820    pub fn new(in_data: InData) -> Self {
821        Self {
822            param_def: Ownership::Rust(unsafe { std::mem::zeroed() }),
823            checkin_on_drop: false,
824            in_data,
825            index: None,
826        }
827    }
828
829    pub fn as_ref(&self) -> &ae_sys::PF_ParamDef {
830        &*self.param_def
831    }
832    pub fn as_mut(&mut self) -> &mut ae_sys::PF_ParamDef {
833        &mut *self.param_def
834    }
835
836    pub fn index(&self) -> Option<i32> {
837        self.index
838    }
839
840    pub fn update_param_ui(&self) -> Result<(), Error> {
841        if let Some(index) = self.index {
842            self.in_data.effect().update_param_ui(index, self)
843        } else {
844            Err(Error::InvalidIndex)
845        }
846    }
847    pub fn keyframe_count(&self) -> Result<i32, Error> {
848        if let Some(index) = self.index {
849            pf::suites::ParamUtils::new()?
850                .keyframe_count(self.in_data.effect_ref(), index)
851        } else {
852            Err(Error::InvalidIndex)
853        }
854    }
855
856    pub fn from_raw(in_data: InData, param_def: &'p mut ae_sys::PF_ParamDef, index: Option<i32>) -> Self {
857        Self {
858            param_def: Ownership::AfterEffectsMut(param_def),
859            checkin_on_drop: false,
860            in_data,
861            index,
862        }
863    }
864
865    pub fn add(&mut self, index: i32) -> Result<(), Error> {
866        self.in_data.interact().add_param(index, &*self.param_def)?;
867        if index != -1 {
868            self.index = Some(index);
869        }
870        Ok(())
871    }
872
873    pub fn checkout(in_data: InData, index: i32, what_time: i32, time_step: i32, time_scale: u32, expected_type: Option<ParamType>) -> Result<Self, Error> {
874        let mut param_def = in_data.interact().checkout_param(index, what_time, time_step, time_scale)?;
875        if param_def.param_type == ae_sys::PF_Param_RESERVED {
876            return Err(Error::InvalidIndex);
877        }
878
879        // For some reason the checked out param_type is 0 so we need to override using the info we have from params map.
880        if index > 0 && expected_type.is_some() {
881            param_def.param_type = expected_type.unwrap().into();
882        }
883
884        Ok(Self {
885            param_def: Ownership::Rust(param_def),
886            checkin_on_drop: true,
887            in_data,
888            index: Some(index),
889        })
890    }
891
892    pub fn set_param(&mut self, param: &Param) {
893        match param {
894            Param::Popup(pd) => {
895                self.param_def.u.pd = *pd.def;
896                self.param_def.param_type = ae_sys::PF_Param_POPUP;
897            }
898            Param::Angle(ad) => {
899                self.param_def.u.ad = *ad.def;
900                self.param_def.param_type = ae_sys::PF_Param_ANGLE;
901            }
902            Param::CheckBox(bd) => {
903                self.param_def.u.bd = *bd.def;
904                self.param_def.param_type = ae_sys::PF_Param_CHECKBOX;
905            }
906            Param::Color(cd) => {
907                self.param_def.u.cd = *cd.def;
908                self.param_def.param_type = ae_sys::PF_Param_COLOR;
909            }
910            Param::Slider(sd) => {
911                self.param_def.u.sd = *sd.def;
912                self.param_def.param_type = ae_sys::PF_Param_SLIDER;
913            }
914            Param::FloatSlider(fs_d) => {
915                self.param_def.u.fs_d = *fs_d.def;
916                self.param_def.param_type = ae_sys::PF_Param_FLOAT_SLIDER;
917            }
918            Param::Button(button_d) => {
919                self.param_def.u.button_d = *button_d.def;
920                self.param_def.param_type = ae_sys::PF_Param_BUTTON;
921            }
922            Param::Path(path_d) => {
923                self.param_def.u.path_d = *path_d.def;
924                self.param_def.param_type = ae_sys::PF_Param_PATH;
925            }
926            Param::Point(td) => {
927                self.param_def.u.td = *td.def;
928                self.param_def.param_type = ae_sys::PF_Param_POINT;
929            }
930            Param::Point3D(point3d_d) => {
931                self.param_def.u.point3d_d = *point3d_d.def;
932                self.param_def.param_type = ae_sys::PF_Param_POINT_3D;
933            }
934            Param::Arbitrary(arb_d) => {
935                self.param_def.u.arb_d = *arb_d.def;
936                self.param_def.param_type = ae_sys::PF_Param_ARBITRARY_DATA;
937            }
938            Param::Layer(ld) => {
939                self.param_def.u.ld = *ld.def;
940                self.param_def.param_type = ae_sys::PF_Param_LAYER;
941            }
942            Param::Null(_) => {
943                self.param_def.param_type = ae_sys::PF_Param_NO_DATA;
944            }
945        }
946    }
947
948    define_param_cast!("popup",        Popup,       PopupDef);
949    define_param_cast!("angle",        Angle,       AngleDef);
950    define_param_cast!("checkbox",     CheckBox,    CheckBoxDef);
951    define_param_cast!("color",        Color,       ColorDef);
952    define_param_cast!("slider",       Slider,      SliderDef);
953    define_param_cast!("float_slider", FloatSlider, FloatSliderDef);
954    define_param_cast!("button",       Button,      ButtonDef);
955    define_param_cast!("arbitrary",    Arbitrary,   ArbitraryDef);
956    define_param_cast!("point",        Point,       PointDef);
957    define_param_cast!("point3d",      Point3D,     Point3DDef);
958    define_param_cast!("path",         Path,        PathDef);
959    define_param_cast!("layer",        Layer,       LayerDef);
960    define_param_cast!("null",         Null,        NullDef);
961
962    pub fn as_param<'a>(&'a self) -> Result<Param<'a>, Error> where 'p: 'a {
963        let param_def = &*self.param_def;
964        let parent_ptr = param_def as *const _;
965        unsafe {
966            match param_def.param_type {
967                ae_sys::PF_Param_ANGLE          => Ok(Param::Angle      (AngleDef      ::from_ref(&param_def.u.ad,        self.in_data.as_ptr(), parent_ptr))),
968                ae_sys::PF_Param_ARBITRARY_DATA => Ok(Param::Arbitrary  (ArbitraryDef  ::from_ref(&param_def.u.arb_d,     self.in_data.as_ptr(), parent_ptr))),
969                ae_sys::PF_Param_BUTTON         => Ok(Param::Button     (ButtonDef     ::from_ref(&param_def.u.button_d,  self.in_data.as_ptr(), parent_ptr))),
970                ae_sys::PF_Param_CHECKBOX       => Ok(Param::CheckBox   (CheckBoxDef   ::from_ref(&param_def.u.bd,        self.in_data.as_ptr(), parent_ptr))),
971                ae_sys::PF_Param_COLOR          => Ok(Param::Color      (ColorDef      ::from_ref(&param_def.u.cd,        self.in_data.as_ptr(), parent_ptr))),
972                ae_sys::PF_Param_FLOAT_SLIDER   => Ok(Param::FloatSlider(FloatSliderDef::from_ref(&param_def.u.fs_d,      self.in_data.as_ptr(), parent_ptr))),
973                ae_sys::PF_Param_POPUP          => Ok(Param::Popup      (PopupDef      ::from_ref(&param_def.u.pd,        self.in_data.as_ptr(), parent_ptr))),
974                ae_sys::PF_Param_SLIDER         => Ok(Param::Slider     (SliderDef     ::from_ref(&param_def.u.sd,        self.in_data.as_ptr(), parent_ptr))),
975                ae_sys::PF_Param_POINT          => Ok(Param::Point      (PointDef      ::from_ref(&param_def.u.td,        self.in_data.as_ptr(), parent_ptr))),
976                ae_sys::PF_Param_POINT_3D       => Ok(Param::Point3D    (Point3DDef    ::from_ref(&param_def.u.point3d_d, self.in_data.as_ptr(), parent_ptr))),
977                ae_sys::PF_Param_PATH           => Ok(Param::Path       (PathDef       ::from_ref(&param_def.u.path_d,    self.in_data.as_ptr(), parent_ptr))),
978                ae_sys::PF_Param_LAYER          => Ok(Param::Layer      (LayerDef      ::from_ref(&param_def.u.ld,        self.in_data.as_ptr(), parent_ptr))),
979                ae_sys::PF_Param_NO_DATA        => Ok(Param::Null       (NullDef       ::new())),
980                _ => {
981                    log::error!("Invalid parameter type: {}", param_def.param_type);
982                    Err(Error::InvalidParms)
983                }
984            }
985        }
986    }
987
988    pub fn as_param_mut<'a>(&'a mut self) -> Result<Param<'a>, Error> where 'p: 'a {
989        let param_def = &mut *self.param_def;
990        let parent_ptr = param_def as *const _;
991        unsafe {
992            match param_def.param_type {
993                ae_sys::PF_Param_ANGLE          => Ok(Param::Angle      (AngleDef      ::from_mut(&mut param_def.u.ad,        self.in_data.as_ptr(), parent_ptr))),
994                ae_sys::PF_Param_ARBITRARY_DATA => Ok(Param::Arbitrary  (ArbitraryDef  ::from_mut(&mut param_def.u.arb_d,     self.in_data.as_ptr(), parent_ptr))),
995                ae_sys::PF_Param_BUTTON         => Ok(Param::Button     (ButtonDef     ::from_mut(&mut param_def.u.button_d,  self.in_data.as_ptr(), parent_ptr))),
996                ae_sys::PF_Param_CHECKBOX       => Ok(Param::CheckBox   (CheckBoxDef   ::from_mut(&mut param_def.u.bd,        self.in_data.as_ptr(), parent_ptr))),
997                ae_sys::PF_Param_COLOR          => Ok(Param::Color      (ColorDef      ::from_mut(&mut param_def.u.cd,        self.in_data.as_ptr(), parent_ptr))),
998                ae_sys::PF_Param_FLOAT_SLIDER   => Ok(Param::FloatSlider(FloatSliderDef::from_mut(&mut param_def.u.fs_d,      self.in_data.as_ptr(), parent_ptr))),
999                ae_sys::PF_Param_POPUP          => Ok(Param::Popup      (PopupDef      ::from_mut(&mut param_def.u.pd,        self.in_data.as_ptr(), parent_ptr))),
1000                ae_sys::PF_Param_SLIDER         => Ok(Param::Slider     (SliderDef     ::from_mut(&mut param_def.u.sd,        self.in_data.as_ptr(), parent_ptr))),
1001                ae_sys::PF_Param_POINT          => Ok(Param::Point      (PointDef      ::from_mut(&mut param_def.u.td,        self.in_data.as_ptr(), parent_ptr))),
1002                ae_sys::PF_Param_POINT_3D       => Ok(Param::Point3D    (Point3DDef    ::from_mut(&mut param_def.u.point3d_d, self.in_data.as_ptr(), parent_ptr))),
1003                ae_sys::PF_Param_PATH           => Ok(Param::Path       (PathDef       ::from_mut(&mut param_def.u.path_d,    self.in_data.as_ptr(), parent_ptr))),
1004                ae_sys::PF_Param_LAYER          => Ok(Param::Layer      (LayerDef      ::from_mut(&mut param_def.u.ld,        self.in_data.as_ptr(), parent_ptr))),
1005                ae_sys::PF_Param_NO_DATA        => Ok(Param::Null       (NullDef       ::new())),
1006                _ => {
1007                    log::error!("Invalid parameter type: {}", param_def.param_type);
1008                    Err(Error::InvalidParms)
1009                }
1010            }
1011        }
1012    }
1013
1014    pub fn is_valid(&self) -> bool {
1015        matches!(
1016            self.param_def.param_type,
1017            ae_sys::PF_Param_ANGLE
1018                | ae_sys::PF_Param_ARBITRARY_DATA
1019                | ae_sys::PF_Param_BUTTON
1020                | ae_sys::PF_Param_CHECKBOX
1021                | ae_sys::PF_Param_COLOR
1022                | ae_sys::PF_Param_FIX_SLIDER
1023                | ae_sys::PF_Param_FLOAT_SLIDER
1024                | ae_sys::PF_Param_GROUP_START
1025                | ae_sys::PF_Param_GROUP_END
1026                | ae_sys::PF_Param_POPUP
1027                | ae_sys::PF_Param_SLIDER
1028                | ae_sys::PF_Param_POINT
1029                | ae_sys::PF_Param_POINT_3D
1030                | ae_sys::PF_Param_PATH
1031                | ae_sys::PF_Param_LAYER
1032                | ae_sys::PF_Param_NO_DATA
1033        )
1034    }
1035    pub fn param_type(&self) -> ParamType {
1036        self.param_def.param_type.into()
1037    }
1038
1039    pub unsafe fn layer_def(&mut self) -> *mut ae_sys::PF_LayerDef {
1040        &mut self.param_def.u.ld
1041    }
1042
1043    pub fn set_name(&mut self, name: &str) {
1044        let name_cstr = CString::new(name).unwrap();
1045        let name_slice = name_cstr.to_bytes_with_nul();
1046        assert!(name_slice.len() <= 32);
1047        self.param_def.name[0..name_slice.len()].copy_from_slice(unsafe { std::mem::transmute(name_slice) });
1048    }
1049
1050    pub fn set_flags       (&mut self, f: ParamFlag)    { self.param_def.flags           = f.bits() as _; }
1051    pub fn set_change_flags(&mut self, f: ChangeFlag)   { self.param_def.uu.change_flags = f.bits() as _; }
1052    pub fn set_ui_flags    (&mut self, f: ParamUIFlags) { self.param_def.ui_flags        = f.bits() as _; }
1053
1054    pub fn set_flag       (&mut self, f: ParamFlag,    set: bool) { let mut v = self.flags();        v.set(f, set); self.set_flags(v);        }
1055    pub fn set_change_flag(&mut self, f: ChangeFlag,   set: bool) { let mut v = self.change_flags(); v.set(f, set); self.set_change_flags(v); }
1056    pub fn set_ui_flag    (&mut self, f: ParamUIFlags, set: bool) { let mut v = self.ui_flags();     v.set(f, set); self.set_ui_flags(v);     }
1057
1058    pub fn flags       (&self) -> ParamFlag    {    ParamFlag::from_bits_truncate(self.param_def.flags) }
1059    pub fn change_flags(&self) -> ChangeFlag   {   ChangeFlag::from_bits_truncate(unsafe { self.param_def.uu.change_flags }) }
1060    pub fn ui_flags    (&self) -> ParamUIFlags { ParamUIFlags::from_bits_truncate(self.param_def.ui_flags) }
1061
1062    pub fn set_ui_width(&mut self, width: u16) {
1063        self.param_def.ui_width = width as _;
1064    }
1065    pub fn set_ui_height(&mut self, height: u16) {
1066        self.param_def.ui_height = height as _;
1067    }
1068
1069    pub fn set_id(&mut self, id: i32) {
1070        self.param_def.uu.id = id;
1071        if self.param_def.param_type == ae_sys::PF_Param_ARBITRARY_DATA {
1072            self.param_def.u.arb_d.id = id as i16; // this truncates the int, but it should be fine
1073        }
1074    }
1075
1076    pub fn set_value_changed(&mut self) {
1077        self.param_def.uu.change_flags = ChangeFlag::CHANGED_VALUE.bits();
1078    }
1079}
1080
1081impl Drop for ParamDef<'_> {
1082    fn drop(&mut self) {
1083        if self.checkin_on_drop {
1084            self.in_data.interact().checkin_param(&*self.param_def).unwrap()
1085        }
1086    }
1087}
1088impl Debug for ParamDef<'_> {
1089    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1090        f.debug_struct("ParamDef")
1091            .field("type", &self.param_type())
1092            .field("checkin_on_drop", &self.checkin_on_drop)
1093            .field("in_data_ptr", &self.in_data.as_ptr())
1094            .finish()
1095    }
1096}
1097
1098use std::collections::HashMap;
1099use std::fmt::Debug;
1100use std::hash::Hash;
1101
1102#[derive(Clone, Debug)]
1103pub struct ParamMapInfo {
1104    pub index: usize,
1105    pub type_: ParamType,
1106}
1107impl ParamMapInfo {
1108    fn new(index: usize, type_: ParamType) -> Self {
1109        Self { index, type_ }
1110    }
1111}
1112
1113#[derive(Clone)]
1114pub struct Parameters<'p, P: Eq + PartialEq + Hash + Copy + Debug> {
1115    num_params: usize,
1116    in_data: *const ae_sys::PF_InData,
1117    pub map: Ownership<'p, HashMap<P, ParamMapInfo>>,
1118    params: Vec<ParamDef<'p>>,
1119}
1120impl<P: Eq + PartialEq + Hash + Copy + Debug> Default for Parameters<'_, P> {
1121    fn default() -> Self {
1122        Self::new()
1123    }
1124}
1125impl<'p, P: Eq + PartialEq + Hash + Copy + Debug> Parameters<'p, P> {
1126    pub fn len(&self) -> usize {
1127        self.map.len()
1128    }
1129    pub fn set_in_data(&mut self, in_data: *const ae_sys::PF_InData) {
1130        self.in_data = in_data;
1131    }
1132    pub fn in_data(&self) -> InData {
1133        InData::from_raw(self.in_data)
1134    }
1135    pub fn new() -> Self {
1136        Self {
1137            in_data: std::ptr::null(),
1138            num_params: 1,
1139            map: Ownership::Rust(Default::default()),
1140            params: Vec::new(),
1141        }
1142    }
1143    pub fn with_params(in_data: *const ae_sys::PF_InData, params: &'p [*mut ae_sys::PF_ParamDef], map: Option<&'p HashMap<P, ParamMapInfo>>, num_params: usize) -> Self {
1144        let in_data_obj = InData::from_raw(in_data);
1145        Self {
1146            in_data,
1147            params: if params.is_empty() || params[0].is_null() {
1148                Vec::new()
1149            } else {
1150                params
1151                    .into_iter()
1152                    .enumerate()
1153                    .map(|(i, p)| { debug_assert!(!p.is_null()); ParamDef::from_raw(in_data_obj, unsafe { &mut **p }, Some(i as i32)) })
1154                    .collect::<Vec<_>>()
1155            },
1156            num_params,
1157            map: map.map_or_else(|| Ownership::Rust(HashMap::new()), Ownership::AfterEffects),
1158        }
1159    }
1160
1161    fn param_id(type_: P) -> i32 {
1162        use hash32::Murmur3Hasher;
1163        use std::hash::Hasher;
1164        let mut hasher = Murmur3Hasher::default();
1165        format!("{type_:?}").hash(&mut hasher);
1166        hasher.finish() as i32
1167    }
1168
1169    pub fn add_group<F: FnOnce(&mut Self) -> Result<(), Error>>(&mut self, type_start: P, type_end: P, name: &str, start_collapsed: bool, inner_cb: F) -> Result<(), Error> {
1170        assert!(!self.in_data.is_null());
1171
1172        let mut param_def = ParamDef::new(InData::from_raw(self.in_data));
1173        param_def.set_name(name);
1174        param_def.as_mut().param_type = ParamType::GroupStart.into();
1175        param_def.set_id(Self::param_id(type_start));
1176        if start_collapsed {
1177            param_def.set_flags(ParamFlag::START_COLLAPSED);
1178        }
1179        param_def.add(-1)?;
1180        self.map.insert(type_start, ParamMapInfo::new(self.num_params, ParamType::GroupStart));
1181        self.num_params += 1;
1182
1183        inner_cb(self)?;
1184
1185        let mut param_def = ParamDef::new(InData::from_raw(self.in_data));
1186        param_def.as_mut().param_type = ParamType::GroupEnd.into();
1187        param_def.set_id(Self::param_id(type_end));
1188        param_def.add(-1)?;
1189        self.map.insert(type_end, ParamMapInfo::new(self.num_params, ParamType::GroupEnd));
1190        self.num_params += 1;
1191        Ok(())
1192    }
1193
1194    pub fn add<'a>(&mut self, type_: P, name: &str, def: impl Into<Param<'a>>) -> Result<(), Error> {
1195        assert!(!self.in_data.is_null());
1196
1197        let param = def.into(); // This must outlive the call to .add()
1198
1199        let mut param_def = ParamDef::new(InData::from_raw(self.in_data));
1200        param_def.set_name(name);
1201        param_def.set_param(&param);
1202        let param_type = param_def.param_type();
1203        param_def.set_id(Self::param_id(type_));
1204        if matches!(param, Param::Button(_)) {
1205            param_def.set_flags(ParamFlag::SUPERVISE);
1206        }
1207        param_def.add(-1)?;
1208        self.map.insert(type_, ParamMapInfo::new(self.num_params, param_type));
1209        self.num_params += 1;
1210        Ok(())
1211    }
1212
1213    pub fn add_with_flags<'a>(&mut self, type_: P, name: &str, def: impl Into<Param<'a>>, flags: ParamFlag, ui_flags: ParamUIFlags) -> Result<(), Error> {
1214        assert!(!self.in_data.is_null());
1215
1216        let param = def.into(); // This must outlive the call to .add()
1217
1218        let mut param_def = ParamDef::new(InData::from_raw(self.in_data));
1219        param_def.set_name(name);
1220        param_def.set_param(&param);
1221        let param_type = param_def.param_type();
1222        param_def.set_id(Self::param_id(type_));
1223        param_def.set_flags(flags);
1224        param_def.set_ui_flags(ui_flags);
1225        param_def.add(-1)?;
1226        self.map.insert(type_, ParamMapInfo::new(self.num_params, param_type));
1227        self.num_params += 1;
1228        Ok(())
1229    }
1230
1231    pub fn add_customized<'a, F: FnOnce(&mut ParamDef) -> i32>(&mut self, type_: P, name: &str, def: impl Into<Param<'a>>, cb: F) -> Result<(), Error> {
1232        assert!(!self.in_data.is_null());
1233
1234        let param = def.into(); // This must outlive the call to .add()
1235
1236        let mut param_def = ParamDef::new(InData::from_raw(self.in_data));
1237        param_def.set_name(name);
1238        param_def.set_param(&param);
1239        let param_type = param_def.param_type();
1240        param_def.set_id(Self::param_id(type_));
1241        let mut index = cb(&mut param_def);
1242        param_def.add(index)?;
1243        if index == -1 {
1244            index = self.num_params as i32;
1245        }
1246        self.map.insert(type_, ParamMapInfo::new(index as usize, param_type));
1247        self.num_params += 1;
1248        Ok(())
1249    }
1250
1251    #[inline(always)]
1252    pub fn get(&self, type_: P) -> Result<ReadOnlyOwnership<ParamDef<'p>>, Error> {
1253        self.get_at(type_, None, None, None)
1254    }
1255
1256    #[inline(always)]
1257    pub fn get_mut(&mut self, type_: P) -> Result<Ownership<ParamDef<'p>>, Error> {
1258        self.get_mut_at(type_, None, None, None)
1259    }
1260
1261    #[inline(always)]
1262    pub fn checkout(&self, type_: P) -> Result<Ownership<ParamDef<'p>>, Error> {
1263        self.checkout_at(type_, None, None, None)
1264    }
1265
1266    pub fn get_at(&self, type_: P, time: Option<i32>, time_step: Option<i32>, time_scale: Option<u32>) -> Result<ReadOnlyOwnership<ParamDef<'p>>, Error> {
1267        if self.params.is_empty() || time.is_some() {
1268            match self.checkout_at(type_, time, time_step, time_scale) {
1269                Ok(Ownership::Rust(param)) => Ok(ReadOnlyOwnership::Rust(param)),
1270                Ok(_) => unreachable!(),
1271                Err(e) => Err(e)
1272            }
1273        } else {
1274            let index = self.index(type_).ok_or(Error::InvalidIndex)?;
1275            Ok(ReadOnlyOwnership::AfterEffects(self.params.get(index).ok_or(Error::InvalidIndex)?))
1276        }
1277    }
1278
1279    pub fn get_mut_at(&mut self, type_: P, time: Option<i32>, time_step: Option<i32>, time_scale: Option<u32>) -> Result<Ownership<ParamDef<'p>>, Error> {
1280        if self.params.is_empty() || time.is_some() {
1281            self.checkout_at(type_, time, time_step, time_scale)
1282        } else {
1283            let index = self.index(type_).ok_or(Error::InvalidIndex)?;
1284            Ok(Ownership::AfterEffectsMut(self.params.get_mut(index).ok_or(Error::InvalidIndex)?))
1285        }
1286    }
1287
1288    pub fn checkout_at(&self, type_: P, time: Option<i32>, time_step: Option<i32>, time_scale: Option<u32>) -> Result<Ownership<ParamDef<'p>>, Error> {
1289        let index = self.index(type_).ok_or(Error::InvalidIndex)?;
1290        let type_ = self.raw_param_type(type_).ok_or(Error::InvalidIndex)?;
1291        let in_data = self.in_data();
1292        let param = ParamDef::checkout(
1293            in_data,
1294            index as i32,
1295            time.unwrap_or(in_data.current_time()),
1296            time_step.unwrap_or(in_data.time_step()),
1297            time_scale.unwrap_or(in_data.time_scale()),
1298            Some(type_)
1299        )?;
1300        if !param.is_valid() {
1301            return Err(Error::InvalidParms);
1302        }
1303        Ok(Ownership::Rust(param))
1304    }
1305
1306    pub fn num_params(&self) -> usize {
1307        self.num_params
1308    }
1309
1310    pub fn index(&self, type_: P) -> Option<usize> {
1311        self.map.get(&type_).map(|x| x.index)
1312    }
1313    pub fn type_at(&self, index: usize) -> P {
1314        *self.map.iter().find(|(_, v)| v.index == index).unwrap().0
1315    }
1316
1317    pub fn raw_params(&self) -> &[ParamDef<'p>] {
1318        &self.params
1319    }
1320    pub fn raw_param_type(&self, type_: P) -> Option<ParamType> {
1321        self.map.get(&type_).map(|x| x.type_)
1322    }
1323
1324    pub fn cloned(&self) -> Parameters<'p, P> {
1325        Parameters::<'p, P> {
1326            in_data: self.in_data.clone(),
1327            num_params: self.num_params,
1328            map: self.map.clone(),
1329            params: self.params.iter().cloned().collect(),
1330        }
1331    }
1332}