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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
use crate::*;
use crate::aegp::*;
use ae_sys::{ PR_RenderContextH, AEGP_RenderLayerContextH };
define_suite!(
/// [`render_texture()`](Self::render_texture) supplies the raw pixels of a layer, untransformed, into an arbitrarily-sized buffer.
///
/// [`render_layer_plus()`](Self::render_layer_plus) invokes the entire After Effects render pipeline, including transforms, masking, et cetera, providing the layer as it appears in its composition, in a composition-sized buffer.
///
/// If the layer being rendered is 3D, the default (Standard 3D) Artisan is invoked to perform any 3D geometrics.
///
/// Your Artisan can use this to render track matte layers, and apply them only in a strictly 2D sense, to the transformed 3D layer.
///
/// Before rendering, the Artisans that ship with After Effects apply an inverse transform to get square pixels, then re-apply the transform before display.
///
/// For example, if the pixel aspect ratio is 10/11 (DV NTSC), we multiply by 11/10 to get square pixels. We process and composite 3D layers, then re-divide to get back to the original pixel aspect ratio.
///
/// The following suite supplies the layers, compositions, texture and destination buffers. This is a vital suite for all artisans.
CanvasSuite,
AEGP_CanvasSuite8,
kAEGPCanvasSuite,
kAEGPCanvasSuiteVersion8
);
impl CanvasSuite {
/// 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()
}
/// Given the render context provided to the Artisan at render time, returns a handle to the composition.
pub fn comp_to_render(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<CompHandle, Error> {
Ok(CompHandle::from_raw(
call_suite_fn_single!(self, AEGP_GetCompToRender -> ae_sys::AEGP_CompH, render_ctx.as_ptr())?
))
}
/// Given the render context, returns the number of layers the Artisan needs to render.
pub fn num_layers_to_render(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<u32, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetNumLayersToRender -> i32, render_ctx.as_ptr())? as u32)
}
/// Used to build a list of layers to render after determining the total number of layers that need rendering by the Artisan.
pub fn nth_layer_context_to_render(&self, render_ctx: impl AsPtr<PR_RenderContextH>, n: u32) -> Result<RenderLayerContextHandle, Error> {
Ok(RenderLayerContextHandle::from_raw(
call_suite_fn_single!(self,
AEGP_GetNthLayerContextToRender -> ae_sys::AEGP_RenderLayerContextH,
render_ctx.as_ptr(),
n as i32
)?,
))
}
/// Given a [`RenderContextHandle`](pr::RenderContextHandle), retrieves the associated [`LayerHandle`] (required by many suite functions).
pub fn layer_from_layer_context(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>) -> Result<LayerHandle, Error> {
Ok(LayerHandle::from_raw(
call_suite_fn_single!(self,
AEGP_GetLayerFromLayerContext -> ae_sys::AEGP_LayerH,
render_ctx.as_ptr(),
layer_ctx.as_ptr()
)?
))
}
/// Allows for rendering of sub-layers (as within a Photoshop file).
pub fn layer_and_sub_layer_from_layer_context(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>) -> Result<(LayerHandle, u32), Error> {
let (layer_handle, sub_layer) = call_suite_fn_double!(self,
AEGP_GetLayerAndSubLayerFromLayerContext -> ae_sys::AEGP_LayerH, ae_sys::AEGP_SubLayerIndex,
render_ctx.as_ptr(),
layer_ctx.as_ptr()
)?;
Ok((
LayerHandle::from_raw(layer_handle),
sub_layer as u32
))
}
/// With collapsed geometrics "on" this gives the layer in the root composition containing the layer context.
///
/// With collapsed geometrics off this is the same as [`layer_from_layer_context()`](Self::layer_from_layer_context).
pub fn top_layer_from_layer_context(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>) -> Result<LayerHandle, Error> {
Ok(LayerHandle::from_raw(
call_suite_fn_single!(self, AEGP_GetTopLayerFromLayerContext -> ae_sys::AEGP_LayerH, render_ctx.as_ptr(), layer_ctx.as_ptr())?
))
}
/// Given the render context, returns the current point in (composition) time to render.
pub fn comp_render_time(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<(Time, Time), Error> {
let (shutter_frame_start, shutter_frame_duration) =
call_suite_fn_double!(self, AEGP_GetCompRenderTime -> ae_sys::A_Time, ae_sys::A_Time, render_ctx.as_ptr())?;
Ok((shutter_frame_start.into(), shutter_frame_duration.into()))
}
/// Given the render context, returns a buffer in which to place the final rendered output.
pub fn comp_destination_buffer(&self, render_ctx: impl AsPtr<PR_RenderContextH>, comp_handle: CompHandle) -> Result<WorldHandle, Error> {
Ok(WorldHandle::from_raw(
call_suite_fn_single!(self, AEGP_GetCompDestinationBuffer -> ae_sys::AEGP_WorldH, render_ctx.as_ptr(), comp_handle.as_ptr())?
))
}
/// Given the render context provided to the Artisan at render time, returns a handle to the composition.
pub fn region_of_interest(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<Rect, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetROI -> ae_sys::A_LegacyRect, render_ctx.as_ptr())?.into())
}
/// Given the render context and layer, returns the layer texture.
///
/// The returned [`WorldHandle`] can be null.
///
/// [`RenderHints::NoTransferMode`] prevents application of opacity & transfer mode; for use with `RenderLayer` calls.
pub fn render_texture(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, render_hints: RenderHints, suggested_scale: Option<FloatPoint>, suggested_src_rect: Option<FloatRect>, src_matrix: Option<Matrix3>) -> Result<WorldHandle, Error> {
Ok(WorldHandle::from_raw(
call_suite_fn_single!(self,
AEGP_RenderTexture -> ae_sys::AEGP_WorldH,
render_ctx.as_ptr(),
layer_ctx.as_ptr(),
render_hints.into(),
suggested_scale .map(Into::into).as_mut().map_or(std::ptr::null_mut(), |x| x),
suggested_src_rect.map(Into::into).as_mut().map_or(std::ptr::null_mut(), |x| x),
src_matrix .map(Into::into).as_mut().map_or(std::ptr::null_mut(), |x| x)
)?
))
}
/// Disposes of an acquired layer texture.
pub fn dispose_texture(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, world_handle: WorldHandle) -> Result<(), Error> {
call_suite_fn!(self, AEGP_DisposeTexture, render_ctx.as_ptr(), layer_ctx.as_ptr(), world_handle.as_ptr())
}
/// Returns the field settings of the given [`RenderContextHandle`](pr::RenderContextHandle).
pub fn field_render(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<ae_sys::PF_Field, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetFieldRender -> ae_sys::PF_Field, render_ctx.as_ptr())?)
}
/// Given the render context provided to the Artisan at render time, returns a handle to the composition.
///
/// Note: this is NOT thread-safe on macOS; only use this function when the current thread ID is 0.
pub fn report_artisan_progress(&self, render_ctx: impl AsPtr<PR_RenderContextH>, count: i32, total: i32) -> Result<(), Error> {
call_suite_fn!(self, AEGP_ReportArtisanProgress, render_ctx.as_ptr(), count, total)
}
/// Returns the downsample factor of the [`RenderContextHandle`](pr::RenderContextHandle).
pub fn render_downsample_factor(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<ae_sys::AEGP_DownsampleFactor, Error> {
let dsf = call_suite_fn_single!(self, AEGP_GetRenderDownsampleFactor -> ae_sys::AEGP_DownsampleFactor, render_ctx.as_ptr())?;
Ok(dsf.into())
}
pub fn set_render_downsample_factor(&self, render_ctx: impl AsPtr<PR_RenderContextH>, mut dsf: ae_sys::AEGP_DownsampleFactor) -> Result<(), Error> {
call_suite_fn!(self, AEGP_SetRenderDownsampleFactor, render_ctx.as_ptr(), &mut dsf as *mut _)
}
/// Determines whether the [`RenderContextHandle`](pr::RenderContextHandle) is blank (empty).
pub fn is_blank_canvas(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<bool, Error> {
Ok(call_suite_fn_single!(self, AEGP_IsBlankCanvas -> ae_sys::A_Boolean, render_ctx.as_ptr())? != 0)
}
/// Given a render context and a layer (at a given time), retrieves the 4 by 4 transform to move between their coordinate spaces.
pub fn render_layer_to_world_xform(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, comp_time: Time) -> Result<Matrix4, Error> {
let matrix = call_suite_fn_single!(self, AEGP_GetRenderLayerToWorldXform -> ae_sys::A_Matrix4, render_ctx.as_ptr(), layer_ctx.as_ptr(), &comp_time.into() as *const _)?;
Ok(matrix.into())
}
/// Retrieves the bounding rectangle of the layer_contextH (at a given time) within the [`RenderContextHandle`](pr::RenderContextHandle).
pub fn render_layer_bounds(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, comp_time: Time) -> Result<Rect, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetRenderLayerBounds -> ae_sys::A_LegacyRect, render_ctx.as_ptr(), layer_ctx.as_ptr(), &comp_time.into() as *const _)?.into())
}
/// Returns the opacity of the given layer context at the given time, within the render context.
pub fn render_opacity(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, comp_time: Time) -> Result<f64, Error> {
call_suite_fn_single!(self, AEGP_GetRenderOpacity -> f64, render_ctx.as_ptr(), layer_ctx.as_ptr(), &comp_time.into() as *const _)
}
/// Returns whether or not a given layer context is active within the render context, at the given time.
pub fn is_render_layer_active(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, comp_time: Time) -> Result<bool, Error> {
Ok(call_suite_fn_single!(self, AEGP_IsRenderLayerActive -> ae_sys::A_Boolean, render_ctx.as_ptr(), layer_ctx.as_ptr(), &comp_time.into() as *const _)? != 0)
}
/// Sets the progress information for a rendering Artisan.
///
/// * `count` is the number of layers completed
/// * `num_layers` is the total number of layers the Artisan is rendering
pub fn set_artisan_layer_progress(&self, render_ctx: impl AsPtr<PR_RenderContextH>, count: i32, num_layers: i32) -> Result<(), Error> {
call_suite_fn!(self, AEGP_SetArtisanLayerProgress, render_ctx.as_ptr(), count, num_layers)
}
/// Invokes the entire After Effects render pipeline, including transforms, masking, et cetera,
/// providing the layer as it appears in its composition, in a composition-sized buffer.
pub fn render_layer_plus(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_handle: LayerHandle, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, render_hints: RenderHints) -> Result<WorldHandle, Error> {
Ok(WorldHandle::from_raw(
call_suite_fn_single!(self, AEGP_RenderLayerPlus -> ae_sys::AEGP_WorldH, render_ctx.as_ptr(), layer_handle.as_ptr(), layer_ctx.as_ptr(), render_hints.into())?
))
}
/// Retrieves the [`RenderLayerContextHandle`] for the specified render and fill contexts.
pub fn track_matte_context(&self, render_ctx: impl AsPtr<PR_RenderContextH>, fill_ctx: RenderLayerContextHandle) -> Result<RenderLayerContextHandle, Error> {
Ok(RenderLayerContextHandle::from_raw(
call_suite_fn_single!(self, AEGP_GetTrackMatteContext -> ae_sys::AEGP_RenderLayerContextH, render_ctx.as_ptr(), fill_ctx.as_ptr())?
))
}
/// Renders a texture into an [`WorldHandle`], and provides an [`RenderReceiptHandle`] for the operation.
pub fn render_texture_with_receipt(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, render_hints: RenderHints, num_effects: RenderNumEffects, suggested_scale: Option<FloatPoint>, suggested_src_rect: Option<FloatRect>, src_matrix: Option<Matrix3>) -> Result<(RenderReceiptHandle, WorldHandle), Error> {
let suggested_scale = suggested_scale .map(Into::into).as_mut().map_or(std::ptr::null_mut(), |x| x);
let suggested_src_rect = suggested_src_rect.map(Into::into).as_mut().map_or(std::ptr::null_mut(), |x| x);
let src_matrix = src_matrix .map(Into::into).as_mut().map_or(std::ptr::null_mut(), |x| x);
let (receipt, world) = call_suite_fn_double!(self,
AEGP_RenderTextureWithReceipt -> ae_sys::AEGP_RenderReceiptH, ae_sys::AEGP_WorldH,
render_ctx.as_ptr(),
layer_ctx.as_ptr(),
render_hints.into(),
num_effects.into(),
suggested_scale,
suggested_src_rect,
src_matrix
)?;
Ok((
RenderReceiptHandle::from_raw(receipt),
WorldHandle::from_raw(world)
))
}
/// Returns the number of software effects applied in the given [`RenderLayerContextHandle`].
pub fn number_of_software_effects(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>) -> Result<i32, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetNumberOfSoftwareEffects -> i16, render_ctx.as_ptr(), layer_ctx.as_ptr())? as i32)
}
/// An improvement over [`render_layer_plus()`](Self::render_layer_plus), this function also provides an [`RenderReceiptHandle`] for caching purposes.
pub fn render_layer_plus_with_receipt(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_handle: LayerHandle, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, render_hints: RenderHints) -> Result<(RenderReceiptHandle, WorldHandle), Error> {
let (receipt, world) = call_suite_fn_double!(self,
AEGP_RenderLayerPlusWithReceipt -> ae_sys::AEGP_RenderReceiptH, ae_sys::AEGP_WorldH,
render_ctx.as_ptr(),
layer_handle.as_ptr(),
layer_ctx.as_ptr(),
render_hints.into()
)?;
Ok((
RenderReceiptHandle::from_raw(receipt),
WorldHandle::from_raw(world))
)
}
/// Frees an [`ae_sys::AEGP_RenderReceiptH`]
///
/// This is called automatically on [`RenderReceiptHandle::drop()`]
pub fn dispose_render_receipt(&self, render_receipt_handle: ae_sys::AEGP_RenderReceiptH) -> Result<(), Error> {
call_suite_fn!(self, AEGP_DisposeRenderReceipt, render_receipt_handle)
}
/// Checks with After Effects' internal caching to determine whether a given [`RenderReceiptHandle`] is still valid.
pub fn check_render_receipt(&self, current_render_ctx: impl AsPtr<PR_RenderContextH>, current_layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, old_render_receipt_handle: RenderReceiptHandle, check_geometrics: bool, num_effects: RenderNumEffects) -> Result<RenderReceiptStatus, Error> {
Ok(call_suite_fn_single!(self,
AEGP_CheckRenderReceipt -> ae_sys::AEGP_RenderReceiptStatus,
current_render_ctx.as_ptr(),
current_layer_ctx.as_ptr(),
old_render_receipt_handle.as_ptr(),
check_geometrics as i32 as _,
num_effects.into()
)?.into())
}
/// Generates a [`RenderReceiptHandle`] for a layer as if the first `num_effects` have been rendered.
pub fn generate_render_receipt(&self, current_render_ctx: impl AsPtr<PR_RenderContextH>, current_layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, num_effects: RenderNumEffects) -> Result<RenderReceiptHandle, Error> {
Ok(RenderReceiptHandle::from_raw(
call_suite_fn_single!(self,
AEGP_GenerateRenderReceipt -> ae_sys::AEGP_RenderReceiptH,
current_render_ctx.as_ptr(),
current_layer_ctx.as_ptr(),
num_effects.into()
)?
))
}
/// Returns the number of bins After Effects wants the artisan to render.
pub fn num_bins_to_render(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<i32, Error> {
call_suite_fn_single!(self, AEGP_GetNumBinsToRender -> i32, render_ctx.as_ptr())
}
/// Sets the given render context to be the n-th bin to be rendered by After Effects.
pub fn set_nth_bin(&self, render_ctx: impl AsPtr<PR_RenderContextH>, n: i32) -> Result<(), Error> {
call_suite_fn!(self, AEGP_SetNthBin, render_ctx.as_ptr(), n)
}
/// Retrieves the type of the given bin.
pub fn bin_type(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<BinType, Error> {
Ok(call_suite_fn_single!(self,
AEGP_GetBinType -> ae_sys::AEGP_BinType,
render_ctx.as_ptr()
)?.into())
}
/// Retrieves the transform to correctly orient the layer being rendered with the output world.
///
/// Pass `true` for `only_2dB` to constrain the transform to two dimensions.
pub fn render_layer_to_world_xform_2d_3d(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, comp_time: Time, only_2d: bool) -> Result<Matrix4, Error> {
Ok(call_suite_fn_single!(self,
AEGP_GetRenderLayerToWorldXform2D3D -> ae_sys::A_Matrix4,
render_ctx.as_ptr(),
layer_ctx.as_ptr(),
&comp_time.into() as *const _,
if only_2d { 1 } else { 0 }
)?.into())
}
/// Retrieves the platform-specific window context into which to draw the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
pub fn platform_window_ref(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<ae_sys::AEGP_PlatformWindowRef, Error> {
call_suite_fn_single!(self, AEGP_GetPlatformWindowRef -> ae_sys::AEGP_PlatformWindowRef, render_ctx.as_ptr())
}
/// Retrieves the source-to-frame downsample factor for the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
pub fn viewport_scale(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<(f64, f64), Error> {
call_suite_fn_double!(self, AEGP_GetViewportScale -> f64, f64, render_ctx.as_ptr())
}
/// Retrieves to origin of the source, within the frame (necessary to translate between the two), for the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
pub fn viewport_origin(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<(i32, i32), Error> {
call_suite_fn_double!(self, AEGP_GetViewportOrigin -> i32, i32, render_ctx.as_ptr())
}
/// Retrieves the bounding rectangle for the area to be drawn, for the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
pub fn viewport_rect(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<Rect, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetViewportRect -> ae_sys::A_LegacyRect, render_ctx.as_ptr())?.into())
}
/// Retrieves the color used for the fallow regions in the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
pub fn fallow_color(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<ae_sys::PF_Pixel8, Error> {
call_suite_fn_single!(self, AEGP_GetFallowColor -> ae_sys::PF_Pixel8, render_ctx.as_ptr())
}
pub fn interactive_buffer(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<WorldHandle, Error> {
Ok(WorldHandle::from_raw(
call_suite_fn_single!(self, AEGP_GetInteractiveBuffer -> ae_sys::AEGP_WorldH, render_ctx.as_ptr())?
))
}
/// Retrieves whether or not the checkerboard is currently active for the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
pub fn interactive_checkerboard(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<bool, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetInteractiveCheckerboard -> ae_sys::A_Boolean, render_ctx.as_ptr())? != 0)
}
/// Retrieves the colors used in the checkerboard.
///
/// This function is valid for interactive artisans only.
pub fn interactive_checkerboard_colors(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<(Pixel8, Pixel8), Error> {
let (px1, px2) = call_suite_fn_double!(self, AEGP_GetInteractiveCheckerboardColors -> ae_sys::PF_Pixel, ae_sys::PF_Pixel, render_ctx.as_ptr())?;
Ok((
px1.into(),
px2.into()
))
}
/// Retrieves the width and height of one checkerboard square.
///
/// This function is valid for interactive artisans only.
pub fn interactive_checkerboard_size(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<(u32, u32), Error> {
call_suite_fn_double!(self, AEGP_GetInteractiveCheckerboardSize -> u32, u32, render_ctx.as_ptr())
}
/// Retrieves the cached AEGP_WorldH last used for the [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
pub fn interactive_cached_buffer(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<WorldHandle, Error> {
Ok(WorldHandle::from_raw(
call_suite_fn_single!(self, AEGP_GetInteractiveCachedBuffer -> ae_sys::AEGP_WorldH, render_ctx.as_ptr())?
))
}
/// Determines whether or not the artisan must render the current [`RenderLayerContextHandle`] as a layer.
///
/// This function is valid for interactive artisans only.
pub fn artisan_must_render_as_layer(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>) -> Result<bool, Error> {
Ok(call_suite_fn_single!(self, AEGP_ArtisanMustRenderAsLayer -> ae_sys::A_Boolean, render_ctx.as_ptr(), layer_ctx.as_ptr())? != 0)
}
/// Returns which channels should be displayed by the interactive artisan.
///
/// This function is valid for interactive artisans only.
pub fn interactive_display_channel(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<DisplayChannel, Error> {
Ok(call_suite_fn_single!(self, AEGP_GetInteractiveDisplayChannel -> ae_sys::AEGP_DisplayChannelType, render_ctx.as_ptr())?.into())
}
/// Returns the exposure for the given [`RenderContextHandle`](pr::RenderContextHandle), expressed as a floating point number.
///
/// This function is valid for interactive artisans only.
pub fn interactive_exposure(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<f64, Error> {
call_suite_fn_single!(self, AEGP_GetInteractiveExposure -> f64, render_ctx.as_ptr())
}
// TODO: what's xform?
/// Returns the color transform for the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
pub fn color_transform(&self, render_ctx: impl AsPtr<PR_RenderContextH>, xform: *mut std::ffi::c_void) -> Result<(bool, u32), Error> {
let mut cms_on = 0;
let mut xform_key = 0;
call_suite_fn!(self, AEGP_GetColorTransform, render_ctx.as_ptr(), &mut cms_on, &mut xform_key, xform)?;
Ok((cms_on != 0, xform_key))
}
/// Returns the shutter angle for the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
pub fn comp_shutter_time(&self, render_ctx: impl AsPtr<PR_RenderContextH>) -> Result<(Time, Time), Error> {
let (shutter_time, shutter_dur) = call_suite_fn_double!(self,
AEGP_GetCompShutterTime -> ae_sys::A_Time, ae_sys::A_Time,
render_ctx.as_ptr()
)?;
Ok((shutter_time.into(), shutter_dur.into()))
}
/// New in CC. Unlike [`suites::Layer::convert_comp_to_layer_time()`](aegp::suites::Layer::convert_comp_to_layer_time), this handles time remapping with collapsed or nested comps.
///
/// This function is valid for interactive artisans only.
pub fn map_comp_to_layer_time(&self, render_ctx: impl AsPtr<PR_RenderContextH>, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, comp_time: Time) -> Result<Time, Error> {
Ok(call_suite_fn_single!(self, AEGP_MapCompToLayerTime -> ae_sys::A_Time, render_ctx.as_ptr(), layer_ctx.as_ptr(), &comp_time.into() as *const _)?.into())
}
}
// ――――――――――――――――――――――――――――――――――――――― Types ――――――――――――――――――――――――――――――――――――――――
register_handle!(AEGP_RenderLayerContextH);
define_handle_wrapper!(RenderLayerContextHandle, AEGP_RenderLayerContextH);
define_enum! {
ae_sys::AEGP_RenderHints,
RenderHints {
None = ae_sys::AEGP_RenderHints_NONE,
IgnoreExtents = ae_sys::AEGP_RenderHints_IGNORE_EXTENTS,
NoTransferMode = ae_sys::AEGP_RenderHints_NO_TRANSFER_MODE,
}
}
define_enum! {
ae_sys::AEGP_BinType,
BinType {
None = ae_sys::AEGP_BinType_NONE,
TwoD = ae_sys::AEGP_BinType_2D,
ThreeD = ae_sys::AEGP_BinType_3D,
}
}
define_enum! {
ae_sys::AEGP_DisplayChannelType,
DisplayChannel {
None = ae_sys::AEGP_DisplayChannel_NONE,
Red = ae_sys::AEGP_DisplayChannel_RED,
Green = ae_sys::AEGP_DisplayChannel_GREEN,
Blue = ae_sys::AEGP_DisplayChannel_BLUE,
Alpha = ae_sys::AEGP_DisplayChannel_ALPHA,
RedAlt = ae_sys::AEGP_DisplayChannel_RED_ALT,
GreenAlt = ae_sys::AEGP_DisplayChannel_GREEN_ALT,
BlueAlt = ae_sys::AEGP_DisplayChannel_BLUE_ALT,
AlphaAlt = ae_sys::AEGP_DisplayChannel_ALPHA_ALT,
}
}
pub enum RenderNumEffects {
AllEffects,
NumEffects(u16)
}
impl Into<i16> for RenderNumEffects {
fn into(self) -> i16 {
match self {
RenderNumEffects::AllEffects => -1,
RenderNumEffects::NumEffects(x) => x as i16
}
}
}
define_enum! {
ae_sys::AEGP_RenderReceiptStatus,
RenderReceiptStatus {
Invalid = ae_sys::AEGP_RenderReceiptStatus_INVALID,
Valid = ae_sys::AEGP_RenderReceiptStatus_VALID,
ValidButIncomplete = ae_sys::AEGP_RenderReceiptStatus_VALID_BUT_INCOMPLETE,
}
}
#[derive(Clone, Debug, Hash)]
pub struct RenderReceiptHandle(after_effects_sys::AEGP_RenderReceiptH);
impl RenderReceiptHandle {
pub fn from_raw(raw_handle: after_effects_sys::AEGP_RenderReceiptH) -> Self { Self(raw_handle) }
pub fn as_ptr(&self) -> after_effects_sys::AEGP_RenderReceiptH { self.0 }
}
impl Drop for RenderReceiptHandle {
fn drop(&mut self) {
if let Ok(s) = CanvasSuite::new() {
let _ = s.dispose_render_receipt(self.0);
}
}
}
define_suite_item_wrapper!(
ae_sys::PR_RenderContextH, pr::RenderContextHandle,
suite: CanvasSuite,
/// [`render_texture()`](Self::render_texture) supplies the raw pixels of a layer, untransformed, into an arbitrarily-sized buffer.
///
/// [`render_layer_plus()`](Self::render_layer_plus) invokes the entire After Effects render pipeline, including transforms, masking, et cetera, providing the layer as it appears in its composition, in a composition-sized buffer.
///
/// If the layer being rendered is 3D, the default (Standard 3D) Artisan is invoked to perform any 3D geometrics.
///
/// Your Artisan can use this to render track matte layers, and apply them only in a strictly 2D sense, to the transformed 3D layer.
///
/// Before rendering, the Artisans that ship with After Effects apply an inverse transform to get square pixels, then re-apply the transform before display.
///
/// For example, if the pixel aspect ratio is 10/11 (DV NTSC), we multiply by 11/10 to get square pixels. We process and composite 3D layers, then re-divide to get back to the original pixel aspect ratio.
///
/// The following suite supplies the layers, compositions, texture and destination buffers. This is a vital suite for all artisans.
Canvas {
dispose: ;
/// Given the render context provided to the Artisan at render time, returns a handle to the composition.
comp_to_render() -> CompHandle => suite.comp_to_render,
/// Given the render context, returns the number of layers the Artisan needs to render.
num_layers_to_render() -> u32 => suite.num_layers_to_render,
/// Used to build a list of layers to render after determining the total number of layers that need rendering by the Artisan.
nth_layer_context_to_render(n: u32) -> RenderLayerContextHandle => suite.nth_layer_context_to_render,
/// Given a [`RenderContextHandle`](pr::RenderContextHandle), retrieves the associated [`LayerHandle`] (required by many suite functions).
layer_from_layer_context(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>) -> LayerHandle => suite.layer_from_layer_context,
/// Allows for rendering of sub-layers (as within a Photoshop file).
layer_and_sub_layer_from_layer_context(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>) -> (LayerHandle, u32) => suite.layer_and_sub_layer_from_layer_context,
/// With collapsed geometrics "on" this gives the layer in the root composition containing the layer context.
///
/// With collapsed geometrics off this is the same as [`layer_from_layer_context()`](Self::layer_from_layer_context).
top_layer_from_layer_context(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>) -> LayerHandle => suite.top_layer_from_layer_context,
/// Given the render context, returns the current point in (composition) time to render.
comp_render_time() -> (Time, Time) => suite.comp_render_time,
/// Given the render context, returns a buffer in which to place the final rendered output.
comp_destination_buffer(comp_handle: CompHandle) -> WorldHandle => suite.comp_destination_buffer,
/// Given the render context provided to the Artisan at render time, returns a handle to the composition.
region_of_interest() -> Rect => suite.region_of_interest,
/// Given the render context and layer, returns the layer texture.
///
/// The returned [`WorldHandle`] can be null.
///
/// [`RenderHints::NoTransferMode`] prevents application of opacity & transfer mode; for use with `RenderLayer` calls.
render_texture(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, render_hints: RenderHints, suggested_scale: Option<FloatPoint>, suggested_src_rect: Option<FloatRect>, src_matrix: Option<Matrix3>) -> WorldHandle => suite.render_texture,
/// Disposes of an acquired layer texture.
dispose_texture(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, world_handle: WorldHandle) -> () => suite.dispose_texture,
/// Returns the field settings of the given [`RenderContextHandle`](pr::RenderContextHandle).
field_render() -> ae_sys::PF_Field => suite.field_render,
/// Given the render context provided to the Artisan at render time, returns a handle to the composition.
///
/// Note: this is NOT thread-safe on macOS; only use this function when the current thread ID is 0.
report_artisan_progress(count: i32, total: i32) -> () => suite.report_artisan_progress,
/// Returns the downsample factor of the [`RenderContextHandle`](pr::RenderContextHandle).
render_downsample_factor() -> ae_sys::AEGP_DownsampleFactor => suite.render_downsample_factor,
set_render_downsample_factor(dsf: ae_sys::AEGP_DownsampleFactor) -> () => suite.set_render_downsample_factor,
/// Determines whether the [`RenderContextHandle`](pr::RenderContextHandle) is blank (empty).
is_blank_canvas() -> bool => suite.is_blank_canvas,
/// Given a render context and a layer (at a given time), retrieves the 4 by 4 transform to move between their coordinate spaces.
render_layer_to_world_xform(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, comp_time: Time) -> Matrix4 => suite.render_layer_to_world_xform,
/// Retrieves the bounding rectangle of the layer_contextH (at a given time) within the [`RenderContextHandle`](pr::RenderContextHandle).
render_layer_bounds(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, comp_time: Time) -> Rect => suite.render_layer_bounds,
/// Returns the opacity of the given layer context at the given time, within the render context.
render_opacity(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, comp_time: Time) -> f64 => suite.render_opacity,
/// Returns whether or not a given layer context is active within the render context, at the given time.
is_render_layer_active(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, comp_time: Time) -> bool => suite.is_render_layer_active,
/// Sets the progress information for a rendering Artisan.
///
/// * `count` is the number of layers completed
/// * `num_layers` is the total number of layers the Artisan is rendering
set_artisan_layer_progress(count: i32, num_layers: i32) -> () => suite.set_artisan_layer_progress,
/// Invokes the entire After Effects render pipeline, including transforms, masking, et cetera,
/// providing the layer as it appears in its composition, in a composition-sized buffer.
render_layer_plus(layer_handle: LayerHandle, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, render_hints: RenderHints) -> WorldHandle => suite.render_layer_plus,
/// Retrieves the [`RenderLayerContextHandle`] for the specified render and fill contexts.
track_matte_context(fill_ctx: RenderLayerContextHandle) -> RenderLayerContextHandle => suite.track_matte_context,
/// Renders a texture into an [`WorldHandle`], and provides an [`RenderReceiptHandle`] for the operation.
render_texture_with_receipt(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, render_hints: RenderHints, num_effects: RenderNumEffects, suggested_scale: Option<FloatPoint>, suggested_src_rect: Option<FloatRect>, src_matrix: Option<Matrix3>) -> (RenderReceiptHandle, WorldHandle) => suite.render_texture_with_receipt,
/// Returns the number of software effects applied in the given [`RenderLayerContextHandle`].
number_of_software_effects(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>) -> i32 => suite.number_of_software_effects,
/// An improvement over [`render_layer_plus()`](Self::render_layer_plus), this function also provides an [`RenderReceiptHandle`] for caching purposes.
render_layer_plus_with_receipt(layer_handle: LayerHandle, layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, render_hints: RenderHints) -> (RenderReceiptHandle, WorldHandle) => suite.render_layer_plus_with_receipt,
/// Returns the number of bins After Effects wants the artisan to render.
num_bins_to_render() -> i32 => suite.num_bins_to_render,
/// Sets the given render context to be the n-th bin to be rendered by After Effects.
set_nth_bin(n: i32) -> () => suite.set_nth_bin,
/// Retrieves the type of the given bin.
bin_type() -> BinType => suite.bin_type,
/// Retrieves the transform to correctly orient the layer being rendered with the output world.
///
/// Pass `true` for `only_2dB` to constrain the transform to two dimensions.
render_layer_to_world_xform_2d_3d(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, comp_time: Time, only_2d: bool) -> Matrix4 => suite.render_layer_to_world_xform_2d_3d,
/// Retrieves the platform-specific window context into which to draw the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
platform_window_ref() -> ae_sys::AEGP_PlatformWindowRef => suite.platform_window_ref,
/// Retrieves the source-to-frame downsample factor for the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
viewport_scale() -> (f64, f64) => suite.viewport_scale,
/// Retrieves to origin of the source, within the frame (necessary to translate between the two), for the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
viewport_origin() -> (i32, i32) => suite.viewport_origin,
/// Retrieves the bounding rectangle for the area to be drawn, for the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
viewport_rect() -> Rect => suite.viewport_rect,
/// Retrieves the color used for the fallow regions in the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
fallow_color() -> ae_sys::PF_Pixel8 => suite.fallow_color,
interactive_buffer() -> WorldHandle => suite.interactive_buffer,
/// Retrieves whether or not the checkerboard is currently active for the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
interactive_checkerboard() -> bool => suite.interactive_checkerboard,
/// Retrieves the colors used in the checkerboard.
///
/// This function is valid for interactive artisans only.
interactive_checkerboard_colors() -> (Pixel8, Pixel8) => suite.interactive_checkerboard_colors,
/// Retrieves the width and height of one checkerboard square.
///
/// This function is valid for interactive artisans only.
interactive_checkerboard_size() -> (u32, u32) => suite.interactive_checkerboard_size,
/// Retrieves the cached AEGP_WorldH last used for the [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
interactive_cached_buffer() -> WorldHandle => suite.interactive_cached_buffer,
/// Determines whether or not the artisan must render the current [`RenderLayerContextHandle`] as a layer.
///
/// This function is valid for interactive artisans only.
artisan_must_render_as_layer(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>) -> bool => suite.artisan_must_render_as_layer,
/// Returns which channels should be displayed by the interactive artisan.
///
/// This function is valid for interactive artisans only.
interactive_display_channel() -> DisplayChannel => suite.interactive_display_channel,
/// Returns the exposure for the given [`RenderContextHandle`](pr::RenderContextHandle), expressed as a floating point number.
///
/// This function is valid for interactive artisans only.
interactive_exposure() -> f64 => suite.interactive_exposure,
// TODO: what's xform?
/// Returns the color transform for the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
color_transform(xform: *mut std::ffi::c_void) -> (bool, u32) => suite.color_transform,
/// Returns the shutter angle for the given [`RenderContextHandle`](pr::RenderContextHandle).
///
/// This function is valid for interactive artisans only.
comp_shutter_time() -> (Time, Time) => suite.comp_shutter_time,
/// New in CC. Unlike [`suites::Layer::convert_comp_to_layer_time()`](aegp::suites::Layer::convert_comp_to_layer_time), this handles time remapping with collapsed or nested comps.
///
/// This function is valid for interactive artisans only.
map_comp_to_layer_time(layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, comp_time: Time) -> Time => suite.map_comp_to_layer_time,
}
);
impl Canvas {
// dispose_render_receipt(&self, render_receipt_handle: ae_sys::AEGP_RenderReceiptH) -> () => suite.
// check_render_receipt(&self, current_render_ctx: impl AsPtr<PR_RenderContextH>, current_layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, old_render_receipt_handle: RenderReceiptHandle, check_geometrics: bool, num_effects: RenderNumEffects) -> RenderReceiptStatus => suite.
// generate_render_receipt(&self, current_render_ctx: impl AsPtr<PR_RenderContextH>, current_layer_ctx: impl AsPtr<AEGP_RenderLayerContextH>, num_effects: RenderNumEffects) -> RenderReceiptHandle => suite.
}