After Effects CC 2015 SDK Guide
After Effects CC 2015 SDK Guide
SDK Guide
Release 1
The information in this document is furnished for informational use only, is subject to
change without notice, and should not be construed as a commitment by Adobe Systems
Incorporated. Adobe Systems Incorporated assumes no responsibility or liability for any
errors or inaccuracies that may appear in this document. The software described in this
document is furnished under license and may only be used or copied in accordance with the
terms of such license.
Adobe, Adobe After Effects, Adobe Premiere Pro, Adobe Photoshop, Adobe Illustrator,
Adobe Type Manager, ATM and PostScript are trademarks of Adobe Systems Incorporated
that may be registered in certain jurisdictions. Macintosh and Apple are registered
trademarks, and Mac OS are trademarks of Apple Computer, Inc. Microsoft, Excel, and
Windows are registered trademarks of Microsoft Corporation. All other products or name
brands are trademarks of their respective holders.
The material in this document is supplied by the Adobe Digital Video API Engineering
team.
August 1994 Dave Herbstman Version 2.0.1 – Added support for PowerPC.
Dan Wilk
5 March 1996 Brian Andrews Version 3.0 – Preliminary release for the After Effects developer
kitchen.
13 Nov. 1996 Brian Andrews Version 3.1 SDK Release 2 – Minor updates.
17 April 1997 Brian Andrews Version 3.1 SDK Release 3 – First public release (really a pre-
release) of the SDK for Windows development.
1 May 1998 Bruce Bullis Version 3.1 SDK Release 6 - Editorial changes only
1 January 1999 Bruce Bullis Version 4.0 SDK Release 1 - Added information on new global
flags, custom data types, utilization of PICA suites, CustomUI
messaging and parameter supervision, new callbacks. many
editorial changes.
9 September 1999 Bruce Bullis Revised for 4.1; added General plug-ins and AEGP information.
Added information on new selectors, resize handle.
1 December 2001 Bruce Bullis 5.5 release. Added information on new outflags, PiPL changes,
and additions and changes to the AEGP API. Numerous
clarifications and edits.
4 March 2002 Bruce Bullis Updated Mac OS X details, expanded AEIO and AEGP
documentation.
20 July 2003 Bruce Bullis Major overhauls for After Effects 6.0. Added documentation for
all new (and some old) suites, and many supporting details for
effects.
4 April 2004 Bruce Bullis Updated for 6.5. Expanded and corrected all documentation.
Added documentation of all new AEGP functions.
1 December 2005 Bruce Bullis Updated for 7.0. Added SmartFX documentation. Noted current
suite version numbers throughout. Numerous editorial changes.
Documented many new AEGP suite functions.
4 April 2006 Bruce Bullis Updated to reference new development system requirements and
XCode-specific issues. Some editing.
4 May 2009 Zac Lam CS4 (9.0) release. Complete reorganization of first three chapters.
Fleshed out documentation on Premiere Pro.
28 April 2010 Zac Lam CS5 (10.0) release. 64-bit porting info. Drawbot.
26 April 2012 Zac Lam CS6 (11.0) release. Big reorganization of the AEGP and Artisan
chapters. Many additions throughout.
15 July 2013 Zac Lam CC (12.0) release. API version changes, misc small clarifications,
more details in AEIO chapter.
12 June 2014 Zac Lam CC 2014 (13.0) release. Corrections for accuracy. Removed old
version references.
This document has changed much over the years. Part encyclopedia, part how-to guide, with
multiple sedimentary layers of accreted information from more than two decades of API
development and refinement. Yes, there does need to be one source of information about
every last niggling detail of the After Effects APIs. However, since no human in their right
mind would ever want to read such a document, we’ve tried to keep it involving and
interesting. As opportunity allows, we’ll try to include more diagrams, illustrations, and
purdy pickshurs explaining API intricacies. As always, your input is valued and appreciated.
ORGANIZATION
The Introduction provides an overview of the integration possibilities with After Effects. It
explains what plug-ins are, and how they work with After Effects. It describes the sample
projects, and how to modify them. It explains where to install plug-ins, and what resources
they use.
The basics of effect plug-ins are discussed in chapter 2. This overview provides information
on the function parameters passed to and from an effect plug-in’s entry point. It describes
capability flags, effect parameters, and image buffers.
Chapter 3 dives into the details of developing a complete effect plug-in using the many
provided callback functions. It also provides many testing ideas to ensure the plug-in is
stabile.
SmartFX is the extension to the effect plug-in API to support 32-bit floating point images,
and is covered in chapter 4.
Chapter 5 covers events sent to effect plug-ins, how to incorporate custom user interface
elements, parameter supervision, and the reliance of custom data parameter types on Custom
UI messaging.
Chapter 7 details the After Effects General Plug-in (AEGP) API. Provided callback
functions, hooking into internal messaging, manipulating the current contents of open
projects and handling menu commands are all covered at length.
Chapter 9 documents AEIOs, specialized AEGPs which handle file input and output.
DOCUMENTATION CONVENTIONS
Functions, structure names and general C/C++ code are in Courier; MyStruct and
MyFunction();
Because we use the public APIs for our own plug-ins, our coding guidelines are apparent
throughout the SDK. Here’s a description of the pseudo-neo-post-Hungarian notation we
use. Of course, you’re welcome to code however you like. If you feel strongly that we should
change our internal coding standards, please post your requests at
comp.sys.programmer.better.things.to.do.with.your.time , and we’ll
carefully consider them before not making any changes.
Boolean B visibleB
Float F degreesF
Long L offsetL
short S indexS
char C digitC
rectangle R boundsR
ratio Rt scale_factorRt
void * PV refconPV
1: Introduction
Welcome to the Adobe® After Effects® CC 2015 Software Development Kit! This is a living
document, and is constantly being updated and edited. The latest public version of the SDK
is available at: http://www.adobe.com/devnet/aftereffects/
While we’ve tried to organize this document in a logical order and provide plenty of cross
references, your specific needs may vary. Searching through this document based on
keywords will often lead you to your answer. If you need more information, your question
may already be answered on the After Effects SDK forum:
http://forums.adobe.com/community/aftereffects_general_discussion/aftereffects_sdk.
Use the search box there, and post a new question if your question hasn’t already been
answered.
This SDK describes the Application Programming Interface (API) that developers use to
build plug-ins. These plug-ins can extend the capabilities of After Effects and other
applications that support the After Effects API. Plug-ins may also be used to bridge the gap
between After Effects and another application.
Effect plug-ins can be applied to video or audio in a composition, to process video and/or
audio data. Some examples of built-in effects are Brightness and Contast, Hue/Saturation,
Gaussian Blur, and Warp Stabilizer. Effect plug-ins can provide a set of parameter controls
for the user to fine-tune the effect. These parameter values can vary over time, and effects
may use other layers and parameters at different times to calculate the output. Oftentimes, it
is thought that plug-ins = effects. But effects are just one type of plug-in used by After
Effects.
After Effects General Plug-ins (AEGPs) can read and modify nearly every element of After
Effects projects and preferences. They can add menu items, ‘hook’ (register themselves to
receive) and trigger After Effects’ internal commands, and add new panels that dock and
After Effects Input/Output (AEIO) plug-ins provide support for new media file types. Unless
you need a custom setup dialog to specify interpretation settings, the Premiere Pro importer
API provides similar functionality, and is preferable in many cases. AEIOs use the AEGP
API along with certain APIs specific to AEIOs. While After Effects still supports Photoshop
format plug-ins and filters, as well as Foreign Project Format (FPF) plug-ins, these APIs
have been long deprecated in favor of the AEIO API.
BlitHook plug-ins output video to external hardware for broadcast quality monitoring and
playback to tape. The EMP sample project provides a starting point. In After Effects CC
2014 and later, Mercury Transmit is the recommended API.
Artisans provide rendered output of 3D layers, taking over 3D rendering from After Effects
(which still handles all rendering of 2D layers). Artisans use the AEGP API along with
certain APIs specific to Artisans.
Didn’t see the type of integration you need described above? After Effects is very flexible, and
there are several other ways to integrate with After Effects.
Effects plug-ins appear in both the Effect menu and the Effects & Presets panel, in the effect
category specified in their PiPL. Once they’re applied, the effect’s parameter controls (sliders,
pop-ups, etc.) appear in the Effect Controls panel (ECP).
After Effects General Plug-ins (AEGPs) can add items to any After Effects menu, and
additional panels listed in the Window menu. These menu items are indistinguishable from
After Effects’ own menu items.
AEIOs and Photoshop Format plug-ins can appear in the File > Import menu, or in the
Import File dialog in the Files of type drop-down, depending on the type of importer. AEIOs
and Format plug-ins can also appear as available output formats in the render queue.
BlitHook plug-ins are automatically loaded and used by AE, but do not appear in any menu
or dialog. The plug-in may optionally provide a menu item that opens it’s own custom
settings dialog. It would register and update the menu item using the AEGP API. It can
registered to be called by After Effects to update the menu with
AEGP_RegisterUpdateMenuHook(), and it can dim/activate the menu item using
AEGP_EnableCommand()/ DisableCommand().
Plug-ins, written in C or C++, are bundle packages on Mac OS and DLLs on Windows.
They must contain a Plug-in Property List (PiPL) resource on both platforms. The plug-ins
must be located in one of a few specific folders in order to be loaded and used by After
Effects.
For effects plug-ins, After Effects sends command selectors (and relevant information) to the
plug-in entry point function designated in the effects’ PiPL resource. Selectors are sent in
response to actions the user takes—applying the effect, changing parameters, scrubbing
through frames in the timeline, and rendering all prompt different sequences of selectors.
After Effects creates multiple instances of effects, with settings and input data unique to each
sequence. All instances share the same global data, and can share data between all frames
within their sequence. After Effects doesn’t process all image data as soon as the user applies
an effect; it invokes effects only when their output is required.
After Effects General Plug-ins (AEGPs) have their entry point function called during
application launch, and register for whatever messaging they need at that time. Further calls
to the AEGP are initiated by user actions, as part of the plug-in’s response to menu
commands or UI events. Depending on their features, plug-ins may need to respond to OS-
specific entry points as well, for UI work and thread management.
For BlitHook plug-ins, frames are pushed as they're displayed in the Composition panel.
Users can initiate a RAM preview on an area of the timeline so that it is rendered to RAM,
and then it all gets played out at full speed.
SDK CONTENTS
The SDK contains headers defining the After Effects APIs, sample projects demonstrating
integration features, and this SDK Guide.
They are compiled with the SDK header files, which expose various After Effects
functionality to be used by the plug-in.
Although this SDK describes the majority of integration possibilities with After Effects,
there are other possibilities not to be overlooked.
SCRIPTING
Scripting is a relatively nimble and lightweight means to perform automated tasks with After
Effects. ScriptUI is one way you can provide UI integration with custom dialogs and panels
(see HTML5 panels too). And scripting may be used in tandem with plug-in development, in
the cases where a certain function is made available via scripting and not via the C APIs
described in this document.
Scripting in After Effects is done using ExtendScript, based on JavaScript. After Effects
includes the ExtendScript ToolKit, a convenient interface for creating and testing your own
scripts. Scripts may be compiled into .jsxbin binary files, to protect intellectual property.
You may download the After Effects Scripting Guide, and find a link to the scripting forums,
on the Adobe Developer Connection website at: http://www.adobe.com/devnet/aftereffects/
After Effects can be driven by executing scripts from the commandline. In your script, you
can open the project and run script actions on it. So for example, you can execute the
following statement to run a script from the command line directly:
AfterFX -s "app.quit()"
Or you can execute this statement to run a .jsx script that includes a quit at the end:
AfterFX -r path_to_jsx_script
On Windows, AfterFX.com is the way to get feedback to the console, because AfterFX.com
is a command line application.
HTML5 PANELS
Starting in CC 2014 and later, After Effects supports HTML5 panels. They are accessed in
After Effects from Window > Extensions > (your panel name). Panels can be resized and
docked just like any other panel in After Effects. Panels are built using HTML5, After
Effects Scripting, and JavaScript. You may download the After Effects Panel SDK from the
the Adobe Developer Connection website at: http://www.adobe.com/devnet/aftereffects/
Closely coupled with scripting is the command line interface offered by aerender. aerender is
primarily suited to allow automated renders, but can be used to execute any sequence of
scripting commands from the command line. An overview is available in the After Effects
help documents here: http://help.adobe.com/en_US/aftereffects/cs/using/WS8A8CD670-
4A72-4fb5-AE8E-CB9E232EC0B5a.html
Premiere Pro importers provide support for importing media into applications across most
applications in the Adobe Creative Cloud, including Premiere Pro, Media Encoder, Prelude,
and Audition. Because of this broader compatibility, unless you need very specific integration
with After Effects only available via the AEIO API in this SDK, we recommend developing a
Premiere Pro importer. The Premiere Pro SDK is available at: http://www.adobe.com/
devnet/premiere/
One advantage of MediaCore importer plug-ins over AEIOs is its priority system: The
highest priority importer gets first crack at importing a file, and if the particular imported
file isn’t supported, the next-highest priority importer will then have the opportunity to try
importing it, and so on.
MERCURY TRANSMIT
Mercury Transmit plug-ins are used for sending video to output hardware for broadcast-
quality monitoring. Transmitters are support across most applications in the Adobe Creative
Cloud, including Premiere Pro, After Effects (starting in CC 2014), Prelude, and
SpeedGrade. The Mercury Transmit API is documented in the Premiere Pro SDK, available
at: http://www.adobe.com/devnet/premiere/
SDK AUDIENCE
You must be a proficient C/C++ programmer to write After Effects plug-ins. While we’ll
help with issues specific to the After Effects API, we can’t help you learn your IDE or basic
programming concepts.
This SDK guide assumes you understand After Effects from a user’s perspective, and basic
video editing terminology. If you don’t, get the Adobe After Effects Classroom in a Book, or any
of the other fine instructional books on the market. It will help you understand different
DEVELOPMENT REQUIREMENTS
If you require support for obsolete versions of the application or API, use an old SDK (which
we don’t maintain or provide). Six months after the current version is released, we will no
longer provide or support the previous version’s SDK.
The SDK samples are created for XCode 5.0.2 on Mac OS 10.8 or 10.9, and Microsoft
Visual Studio .NET 2010 SP 1 (version 10.0) on Windows 7 64. Yes, we’re being pretty
stringent about using the required IDE. No, it’s never pleasant to move to a new compiler,
but no, we’re not going to continue to help with older build environments.
In order to use Visual Studio, you may need to adjust some installation settings to install the
components for compiling 64-bit plug-ins. Visual Studio Express may be used, but will also
require an additional installation to compile 64-bit plug-ins, as described here:
http://msdn.microsoft.com/en-us/library/9yb4317s.aspx
To compile using newer versions of XCode on newer versions of Mac OS, often all that is
required is to update the Base SDK in the Build Settings.
WHAT’S NEW?
If this is your first time developing an After Effects plug-in, you can skip the What’s New
section and go directly to How to Start Creating Plug-ins.
This release fixes some audio APIs that broke in 13.5 due to threading changes. In 13.5,
when called on the UI thread, AEGP_RenderNewItemSoundData() would return
A_Err_GENERIC. This restores the functionality when called on the UI thread.
This release of After Effects includes major architectural changes to separate the UI (main)
thread from the render thread. The render thread sends selectors such as
PF_Cmd_RENDER, PF_Cmd_SMART_PRERENDER, and
PF_Cmd_SMART_RENDER to effect plug-ins. The UI thread sends selectors such as
PF_Cmd_SEQUENCE_SETUP, PF_Cmd_USER_CHANGED_PARAM,
PF_Cmd_DO_DIALOG, and PF_EVENT_DRAW. PF_Cmd_SEQUENCE_RESETUP is
sent on both render and UI threads.
These changes are to improve interactive performance and responsiveness. At the same time,
the new design introduces some new requirements and may break assumptions that existing
plug-ins relied on. Here are some of the major changes:
1) The project can no longer be modified by the render thread (and in fact the render thread
now has its own local copy of the project)
2) Rendering cannot pass modified sequence data back to the UI thread for custom UI
updates
3) In general the UI thread should no longer do time-consuming operations such as
synchronously rendering frames
Generally, calculations that will persist or update the UI will now have to be pulled from the
UI thread rather than pushed from the render thread. These cases can require use of new
13.5 APIs or different solutions than in past releases.
PF_OutFlag2_SUPPORTS_GET_FLATTENED_SEQUENCE_DATA
PF_Cmd_GET_FLATTENED_SEQUENCE_DATA
This will eventually become required for plug-ins that are rebuilt to be thread-safe (see
PF_OutFlag2_AE13_5_THREADSAFE below). The venerable
PF_Cmd_SEQUENCE_FLATTEN will eventually be unsupported in future versions.
● PF_OutFlag_FORCE_RERENDER Changes
This flag does not work as broadly as before, and we now discourage its usage. Instead we
recommend triggering rerenders using one of the following: GuidMixInPtr() (described in
the next section), arb data, or PF_ChangeFlag_CHANGED_VALUE. All of these work
better with Undo. Once we have the full set of APIs in place needed to manage render state,
we will be able to deprecate FORCE_RERENDER.
PF_OutFlag2_I_MIX_GUID_DEPENDENCIES
GuidMixInPtr()
Used by SmartFX only. Use this if custom UI or PF_Cmd_DO_DIALOG changes sequence
data, or if the render result depends on anything else not factored in, and rerendering may be
needed. During PF_Cmd_SMART_PRERENDER, the effect can call GuidMixInPtr() to
mix any additional state that affects the render into our internal GUID for the cached frame.
Using this GUID, AE can tell whether the frame already exists or if it needs to be rendered.
See an example in SmartyPants sample project.
PF_OutFlag2_CUSTOM_UI_ASYNC_MANAGER
PF_GetContextAsyncManager()
AEGP_CheckoutOrRender_ItemFrame_AsyncManager()
AEGP_CheckoutOrRender_LayerFrame_AsyncManager()
For cases where such renders formerly were triggered by side-effect or cancelled implicity
(such as custom UI histogram drawing), and lifetime is less clear from inside the plug-in, use
the new “Async Manager” which can handle multiple simultaneous async requests for effect
Custom UI and will automatically support interactions with other AE UI behavior.
Note: Async retrieval of frames is preferred for handling passive drawing situations, but not
when a user action will update the project state. If you are (1) responding to a specific user
click, AND 2) you need to update the project as a result, the synchronous
AEGP_RenderAndCheckoutLayerFrame() is recommended.
The new HistoGrid sample in the SDK shows how to do completely asynchronous custom
UI DRAW event handling on the UI thread when 1 or more frame renders are needed. e.g.
for calculating histograms that are shown in the effect pane. Please note there is still a
known bug where drag-changing an upstream param may not refresh the histogram draw
until the mouse hovers over it.
Effects such as keyers or those that draw histograms of post-processed video can retrieve the
needed AEGP_LayerRenderOptionsH using the new function
AEGP_NewFromDownstreamOfEffect() in AEGP_LayerRenderOptionsSuite. This
function may only be called from the UI thread.
We've tightened validation of when AEGP calls could be used dangerously (such as from the
wrong thread or making a change to the project state in render). You may see new errors if
code is hitting such cases. For example, making these calls on the render thread will result in
an error:
suites.UtilitySuite5()->AEGP_StartUndoGroup()
suites.StreamSuite2()->AEGP_GetStreamName()
suites.StreamSuite2()->AEGP_SetExpressionState()
suites.StreamSuite2()->AEGP_SetExpression()
suites.StreamSuite2()->AEGP_GetNewLayerStream()
suites.StreamSuite2()->AEGP_DisposeStream()
suites.EffectSuite3()->AEGP_DisposeEffect()
suites.UtilitySuite5()->AEGP_EndUndoGroup()
During development, it was noticed that deadlocks could occur in specific call usage.
Seatbelts have been introduced to avoid this. The cases occur in
PF_Cmd_UPDATE_PARAMS_UI when using particular calls because of deprecated
synchronous behavior in these calls when used in the UI:
The above uses should be rare, but if this affects you please contact us about workarounds.
● Deprecated
For example, an “Auto Color” button that takes a frame and then adjusts effect params as a
result.
A beta of a progress dialog for this blocking operation if it is slow has been implemented, but
using this call on the UI thread should be limited to this special cases. The dialog design is
not final.
PF_OutFlag2_AE13_5_THREADSAFE
Plug-ins updated for threading should use this flag to tell AE that the plug-in is expected to
be UI thread <> Render thread safe.
This flag tells AE that different threads on different AE project copies can be in the effect at
the same time but not accessing the same instance. While multiple render threads are not yet
in use, this will be useful in future releases.
● Support for Effect Version greater than 7 (new max is MAJOR version 127)
Effects greater than version 7 will now report properly in 13.5 if built with the current SDK
headers. It is possible to use these recompiled effects in AE versions older than 13.5, but
internally the version number will wrap modulo 8 (e.g. AE will internally see effect version 8
as version 0).
This can affect the version shown in error dialog display by older AE and affect usage
reporting.
Since many older plug-ins were made unloadable in AE with the shift to 64-bit, it should be
unlikely this wrapping would cause ambiguity with actual plug-ins in current use (unless
these plug-ins have been rapidly increasing version number over the last few years).
However, building with an older SDK and using an 8 or higher version will result in the
plug-in reporting an incorrect version to AE, which will then cause mismatch with the PiPL
version check for the effect which will have the higher bits set. This is not supported.
If built with an older SDK, you will need to keep the effect version at 7 or below. Increase in
version max has been accomplished by adding 4 new higher significant bits to the version that
only AE 13.5 and above “sees”. These new high version bits are not contiguous with the
original, preexisting MAJOR version bits -- just ignore the intermediate bits. The new
version layout looks like this in hexadecimal or binary.
Developers can find paths to the default location of plug-ins, scripts, and presets on Mac OS
X in a new plist file (same as the paths in the Windows registry): /Library/Preferences/
com.Adobe.After Effects.paths.plist
You can use the values in this plist to direct where your installers or scripts write files, in the
same way that you would use the paths keys in the registry on Windows:
HKEY_LOCAL_MACHINE\SOFTWARE\Adobe\After Effects\13.5
● Work In Progress
AEGP_RenderAndCheckoutLayerFrame_Async()
AEGP_CancelAsyncRequest()
This APIs are in progress, and should not be used yet.
PF_CreateNewAppProgressDialog()
It won't open the dialog unless it detects a slow render. (2 seconds timeout).
Starting in CC 2014, After Effects will now honor a change to a custom UI height made
using PF_UpdateParamUI .
AEGP Effect Suite is now at version 4, adding new functions to work with effect masks.
We added the PF_AngleParamSuite, providing a way to get floating point values for angle
parameters. PF App Suite version 5 adds PF_AppGetLanguage to query the current
language so that a plug-in can use the correct language string, as well as several new
PF_App_ColorType enum values for new elements whose colors can be queried.
AEGP_LayerSuite is now at version 8, adding new functions to set/get the layer sampling
quality. AEGP_CanvasSuite is also now at version 8. The new function
AEGP_MapCompToLayerTime handles time remapping with collapsed or nested comps,
unlike AEGP_ConvertCompToLayerTime.
AEGP_IOInSuite is now at version 5, adding new functions to get/set/clear the native start
time, and to get/set the drop-frame setting of footage.
New in 11.0.1, the AE effect API version has been incremented to 13.3. This allows effects
to distinguish between 11.0 and 11.0.1. There is a bug in 11.0 with the Global Performance
Effects that render a watermark over the output when the plug-in is in trial mode can now
tell After Effects whether watermark rendering mode is on or off, using the new
PF_OutFlag2_OUTPUT_IS_WATERMARKED.
The new Global Performance Cache means you must tell After Effects to discard old cached
frames when changing your effect’s rendering.
PF_GET_PLATFORM_DATA now has new selectors for getting the wide character path of the
executable and resource file: PF_PlatData_EXE_FILE_PATH_W and
PF_PlatData_RES_FILE_PATH_W. The previous non-wide selectors are now deprecated.
AEGP Render Suite is now at version 3, adding a new function to get the GUID for a render
receipt.
For effects running in Premiere Pro CS6, we have added the ability to get 32-bit float and
YUV frames from PF_CHECKOUT_PARAM .
For history this far back, see obsolete copies of the SDK (which we don’t provide; if someone
wants you do develop for antique software, they’d best provide the SDK).
PLAY!
Before you write a line of code, Spend some significant time playing with After Effects, and
with the sample projects. Build the plug-ins into the right folder. Set lots of breakpoints,
read the amusing and informative comments.
PLAN!
After experimenting with the samples, find one that does something like what you want to
do. The temptation to start from scratch may be strong; fight it! For effects, use the Skeleton
template project. Avoid the headache of reconstructing projects (including the troublesome
custom build steps for Windows PiPL resource generation) by grafting your code into an
existing project.
STEAL!
To make the Skeleton sample your own, copy the entire \Skeleton directory, renaming it to
(for example) \WhizBang. Using your text editor of choice, search \WhizBang\*.* (yes, that
includes .NET and XCode project files) for occurrences of Skeleton and SKELETON, and
replace them with WhizBang and WHIZBANG.
You now have a compiling and running plug-in that responds to common commands, handles
8 and 16-bpc color, uses our AEGP_SuiteHandler utility code, and responds to 3D light and
camera information. There, was that so hard?
AEGP developers will do well to start with Projector (for After Effects project creation
support), Easy Cheese for a keyframe assistant, IO for media file format support, and
Persisto for a simple menu command and working with preferences.
TEST!
If only for testing convenience, you should have a project saved with your effect applied, and
all its parameters keyframed to strange values. Between these projects which stress your plug-
in, and the tools provided by your development environment, you’re well on your way to
shipping some tested code.
BLAME!
If you run into behavior that seems wrong, see if you can reproduce the behavior using one of
the unmodified sample projects. This can save you a lot of time, if you can determine whether
the bug behavior was introduced by your modifications, or was already there to begin with.
DEVELOPERS MATTER
Third party developers drive API and SDK improvement and expansion. Your products
enable After Effects to do things we’d never considered. Your efforts make After Effects
better; keep it up!
SAMPLE PROJECTS
There is at least one sample of every type of plug-in supported by the current API, as well as
projects to illustrate particular concepts.
In the sample projects, we’ve kept the code as simple as possible. A showy implementation
might get us good grades in a programming class, but won’t help you understand how to use
API features.
After the break, we explain how to build the sample projects, so keep reading below!
Artie Artie the Artisan takes over rendering of all 3D layers in a given composition.
This is the same API used by our internal 3D renderers; it is very complex, and
exposes a great deal of tacit information about the After Effects rendering
pipeline. Unless you have a compelling reason to replace the way After Effects
handles 3D rendering, you need never work with this sample. Artisans appear in
Composition > Composition Settings, in the Advanced tab, in the Rendering
Plug-in drop-down.
Easy Cheese A keyframer (which shows up on the Animation > Keyframe Assistant
submenu), Easy Cheese shows how to manipulate various characteristics of
keyframes (in a way that, uncannily, resembles our shipping plug-in, Easy Ease...)
FBIO Exercises the After Effects Input/Output (AEIO) API. Similar to the IO
sample, but supports the frame-based .ffk file format. Note that we now
recommend developing a Premiere Pro importer instead.
Grabba Gets frames (formatted as the plug-in requests) from any composition in the
project.
IO Exercises the After Effects Input/Output (AEIO) API. Supports the fictitious
.fak file format, and handles all requests from After Effects for retrieving data
from or outputting to such files. Note that we now recommend developing a
Premiere Pro importer instead.
Mangler Mangler is a keyframer demonstrating the use of an ADM palette, just like our
own.
Persisto Shows how to read and write information from the After Effects preferences file.
ProjDumper Creates a text file representing every element in an After Effects project.
Projector Imports the (fictitious) .sdk file format, and creates a project using AEGP
API calls. Whenever you’re wondering how to get or set some characteristic of a
project element, look here first. Note: There are some hardcoded paths in
Projector.h. If you don't set these to refer to actual media on disk, you WILL get
errors while running this plug-in. Don't blame us; change them!
Sweetie Sweetie uses the PICA (or “Suite Pea”) API to provide a function Suite, for use
by other plug-ins. If you’re writing multiple plug-ins that rely on the same image
processing library, you could provide the library functionality using such a suite.
Effects All effects appear in the Effects & Presets panel, and in the Effect menu.
Checkout Checks out (of After Effects’ frame cache) a frame of input from another layer, at
a specified time. This is an important concept for all effects with layer
parameters. Premiere Pro compatible.
Gamma Table Shows how to manage sequence data, and uses our iteration callbacks. For
nostalgia’s sake, we’re leaving this one sample in C; it’s also compatible with many
third-party plug-in hosts, due to its reliance on version 3.x API features.
Paramarama Exercises wayward param types not used in other sample. Premiere Pro
compatible.
Portable Shows how to detect and respond to several different plug-in hosts. Premiere
Pro compatible.
Resizer Resizer resizes (surprise!) the output buffer. This is useful for effects like glows
and drop shadows, which would be truncated at the layer’s edges if they didn’t
expand the output buffer. Premiere Pro compatible.
SDK Backwards Reverses a layer’s audio, and mixes it with a keyframe-able sine wave.
SDK Noise Premiere Pro compatible, demonstrates 32-bit and YUV rendering in Premiere
Pro.
SmartyPants Demonstrates the SmartFX API, required for support of floating point pixels.
Effect Template
Skeleton Skeleton is the starting point for developing effects. Premiere Pro compatible.
CCU Implements a custom user interface in the composition and layer windows,
supporting pixel aspect ratio and downsample ratios. Premiere Pro compatible.
ColorGrid Shows how to use arbitrary data type parameters. Also has a nice custom UI.
Premiere Pro compatible.
Custom ECW UI Implements a very boring custom user interface in the effect controls window,
and shows how to respond to numerous UI events.
Histogrid New for CC 2015 (13.5). An example of how custom UI can access
asynchronously-rendered upstream frames for lightweight processing in CC
2015 and later. This effect calculates a sampled 10x10 color grid from the
upstream frame, and displays a preview of that color grid. In render, a higher-
quality grid is calculated and used to modify the output image, creating a blend
of a color grid with the original image.
Supervisor Shows how to control parameters (both values and UI) based on the value of
other parameters. Premiere Pro compatible.
BlitHook
EMP External Monitor Preview. Use this as a starting point for adding support to
output video from the composition panel to video hardware.
We’ve combined the sample projects into a single master project, stored in the Examples
folder of the SDK. For Mac OS, it is Buildall.xcodeproj; for Windows, it is
BuildAll.sln.
In your IDE, you’ll need to change the output folder of your project to build into After
Effects’ plug-in folder. For development, we recommend using the following path for Mac
OS:
/Library/Application Support/Adobe/Common/Plug-ins/[version]/MediaCore/
Version is locked at 7.0 for all CC versions, or CSx for earlier versions.
Note that this Windows path is only recommended for development purposes. Windows
installers should follow the guidelines here.
In Xcode, you can set this path once for all projects in the Xcode Preferences > Locations >
Derived Data > Advanced. Under Build Location choose Custom, and fill in the path.
In Visual Studio, for convenience, we have specified the output path for all sample projects
using the environment variable AE_PLUGIN_BUILD_DIR . You’ll need to set this as a user
environment variable for your system. On Windows 7, right-click My Computer > Properties
>and in the left sidebar choose Advanced System Settings. In the new dialog, hit the
Environment Variables button. In the User variables area, create a New variable named
AE_PLUGIN_BUILD_DIR , and with the path described above. Log out of Windows and log
back in so that the variable will be set.
Alternatively, you can set output path for each project individually in Visual Studio by right-
clicking a project in the Solution Explorer, choosing Properties, and then in Configuration
Properties > Linker > General, set the Output File.
DEBUGGING PLUG-INS
The best way to learn the interaction(s) between After Effects and plug-ins is running the
samples in your debugger. Spending some quality time in your compiler’s debugger, and a
sample project that closely resembles your plug-in, can really pay off.
On Windows, in the Visual Studio solution, in the Solution Explorer panel, right-click on
the project, and choose Properties. In Configuration Properties > Debugging > Command,
provide the path to the After Effects executable file.
For Mac OS, in the XCode project, in the Groups and Files panel, in the Executables section,
create a New Custom Executable. Set the Executable Path to the After Effects executable file.
During the course of developing a plug-in, your plug-in may pass settings information to
After Effects, which is then stored in its preferences file. You may delete the preferences and
restart After Effects with a clean slate by holding down Ctrl-Alt-Shift / Cmd-Opt-Shift
during launch.
Generally, you should compile your plug-ins with the latest After Effects SDK headers. This
makes the latest suites and API functionality available to your plug-ins. When a new version
of After Effects is released, you generally will not need to provide a new version unless you
wish to take advantage of new functionality exposed through the new SDK. However, you
should always test your plug-in in new versions of After Effects before claiming compatibility
with new versions.
You should test your plug-in thoroughly in each version of After Effects supported by your
plug-in. If you need to add a conditional block of code to be run only in specific versions of
After Effects, you can always check the API version in PF_InData.version for effects, or
in the major and minor_versionL passed into your AEGP in the EntryPointFunc() .
For even more precise version checking, a plug-in can run a script using
AEGP_ExecuteScript , querying one of the following attributes:
app.version - e.g. 11.0.1x12
app.buildNumber - e.g. 12.
7.0 12.12
5.0 12.5
4.1 12.2
3.1 11.6
Some developers are wary of using each After Effects release’s new API features, to maintain
compatibility with hosts with partial implementations. You can distinguish between host
applications by checking PF_InData>appl_id. After Effects uses the appl_id ‘FXTC’.
Premiere Pro uses ‘PrMr’. As of this writing, no third party hosts support SmartFX, or our
AEGP functions. Also, see the chapter on compatibility with Premiere Pro and other hosts.
PIPL RESOURCES
Originating in Adobe Photoshop over a decade ago, Plug-In Property Lists, or PiPLs, are
resources which provide basic information about a plug-in’s behavior, without executing the
plug-in. PiPLs have been largely supplanted within After Effects by
PF_Cmd_GLOBAL_SETUP and dynamic outflags. However, for archaeological reasons, the
behaviors indicated during PF_Cmd_GLOBAL_SETUP must agree with those in the PiPL.
In the interest of cross-platform compatibility, use a single .r file for both Mac OS and
Windows versions of your plug-in, like the samples do. PiPL properties must always be in
Mac OS-specific byte order. On Windows, PiPLs are compiled by processing a .r file through
pipltool.exe, which converts the .r file into a binary .rc file. The Windows sample
projects all contain custom build steps which generate a .rc file, using a cross-platform .r file
and our cnvtpipl.exe command line utility. Base your development on an existing sample
plug-in and the build step will be correctly implemented.
ENTRY POINT
Your plug-in’s entry point is exported through the PiPL on Windows and Mac OS. If the
plug-in supports multiple platforms (e.g. Windows and Intel Macs), then multiple entry
points must be defined in the PiPL. There is no need for a Windows .def file or manual
exports, unless you’re also designating some other OS-specific entry point. The macros
defined in entry.h (in the \SDK\Examples\Headers directory) take care of exporting each
sample’s entry point function. XCode seems overly concerned about the prospect of a main()
function returning a long; all the sample projects’ entry point functions have been changed to
the seemingly innocuous EntryPointFunc().
To use resources from Microsoft Visual Studio .NET with pipltool-generated resources,
#include the output of the custom build steps into the Microsoft-generated .rc file.
If modifying a sample plug-in, change the name of the file generated by pipltool.exe to
something like WhizBang_PiPL_temp.rc, or it will overwrite the Microsoft resources each
time you build; not good.
MULTIPLE PIPLS
It is possible, but not recommended, to include multiple plug-ins (both AEGPs and effects)
in the same file, using multiple PiPLs. If there are PiPLs for both AEGPs and effects in the
same file, the AEGPs must come first!
For those of you who use C++ and simply must keep your plug-ins loaded all the time (to
avoid having your v-tables trashed, among other hazards), set the PiPL’s
AE_Reserved_Info member to 8. Over the years we’ve been quite stringent, insisting that
plug-ins be good memory citizens and respond gracefully to getting unloaded. We know there
are cases in which being unloaded with no warning can really ruin a plug-in’s day (and v-
tables), and so have provided this work-around. Be nice, perform scrupulous memory
management, and only use your powers for good.
You don’t; After Effects does. If you follow our advice and base your projects on the SDK
samples, you can simply change the .r file containing your PiPL definition(s), and your plug-
in’s resources will be automagically updated the next time you build. Feel the love. Or, if you
ever tinker with the custom build steps, feel the pain.
EXCEPTIONS
Handle all exceptions generated by your plug-in’s code, within your plug-in. Pass those
which didn’t originate in your plug-in’s code to After Effects. After Effects’ APIs are
designed for plug-ins written in C, and don’t expect exceptions. After Effects will crash
immediately if one is thrown from within a plug-in. The effect samples use a firewall around
the switch statement in the main() function, and the AEGPs wrap their function hooks in
try/catch blocks.
Installing your plug-ins in the common location will allow them to be loaded by Premiere
Pro, if installed.
Version is locked at 7.0 for all CC versions, or CSx for earlier versions.
for example: /Library/Application Support/Adobe/Common/Plug-ins/7.0/MediaCore/
Do not use Mac OS aliases or Windows shortcuts, as these are not traversed by Premiere
Pro.
You may have good reason to install your plug-in for only After Effects, for example, if your
plug-in depends on suites and functionality not available in Premiere Pro. We strongly
recommend that you use the common folder whenever possible, but for certain cases, the AE-
specific plug-in folder is still available.
On Windows, the app-specific plug-ins folder can be found (as an explicit path) in the
following registry entry:
\\HKEY_LOCAL_MACHINE\SOFTWARE\Adobe\After
Effects\(version)\PluginInstallPath
When launched, After Effects recursively descends 10 levels deep into subdirectories of its
path. Mac OS aliases are traversed, but Windows shortcuts are not. Directories terminated
by parentheses or preceded by the symbols ¬ (Mac OS) or ~ (Windows) are not scanned.
Try as you might to build a fence between AE and Premiere Pro, users will still find ways to
get across using our lovely integration goodness - Your effects will still be available to
Premiere Pro users who create a dynamically linked AE composition with your effect, and
put it in a Premiere Pro sequence.
Starting in CC, PF App Suite adds PF_AppGetLanguage() to query the current language
so that a plug-in can use the correct language string.
When passing strings to AE, some parts of the API accept Unicode. In other areas, for
example when specifying effect parameter names during PF_Cmd_PARAMS_SETUP, you'll need
to pass the names in a char string. For these non-Unicode strings, AE interprets strings as
being multi-byte encoded using the application's current locale. To build these strings, on
Windows you can use the WideCharToMultiByte() function, specifying CP_OEMCP as
the first argument. On Mac OS, use the encoding returned by
GetApplicationTextEncoding().
For Win, change the system locale to the targeted language (control panel > region and
language > administrative tab > change system locale), restart machine, and then install AE
in the according language.
For Mac, set targeted language to the primary language in the preferred language list, and
then install AE in the according language.
NEXT STEPS
You now have an understanding of what plug-ins are, what they can do, and how After
Effects communicates with them. We will cover the basics of effects plug-ins in the next
chapter.
2: Effect Basics
This chapter will provide all the information you need to know to understand how a basic
effect plug-in works. These details are fundamental to every effect plug-in. By the time you
finish this chapter, you’ll be ready for the fun stuff; modifying pixels!
ENTRY POINT
All communication between After Effects and an effect plug-in is initiated by After Effects,
and it all happens by the host (After Effects) calling a single entry point function. For all
effect plug-ins, the entry point function must have the following signature:
PF_Err main (
PF_Cmd cmd,
PF_InData *in_data,
PF_OutData *out_data,
PF_ParamDef *params[],
PF_LayerDef *output,
void *extra)
The name of the entry point function above is “main”, but it can be whatever is specified in
the PiPL resource.
Before each call to the entry point function, After Effects updates PF_InData and the plug-
in’s parameter array PF_ParamDef[] (except as noted). After the plug-in returns from its
call, After Effects checks PF_OutData for changes and, when appropriate, uses the
PF_LayerDef the effect has rendered.
in_data Information about the application’s state and the data the plug-in is being told
to act upon. Pointers to numerous interface and image manipulation functions
are also provided.
output The output image, to be rendered by the effect plug-in and passed back to
After Effects. Only valid during certain selectors.
extra The extra parameter varies with the command sent or (in the case of
PF_Cmd_EVENT) the event type. Used primarily for event management
and parameter supervision.
COMMAND SELECTORS
Commands are, simply, what After Effects wants your effect to do. Responses to some
selectors are required; most are optional, though recall that we did add them for a reason...
With each command selector sent, effects receive information from After Effects in
PF_InData , input and parameter values in PF_ParamDef[] (an array of parameter
descriptions including the input layer), and access to callbacks and function suites. They send
information back to After Effects in PF_OutData , and (when appropriate) render output to
a PF_LayerDef, also called a PF_EffectWorld . During events, they receive event-specific
information in extra .
CALLING SEQUENCE
Only the first few command selectors are predictable; the rest of the calling sequence is
dictated by user action.
For each frame rendered by a basic non-SmartFX effect, After Effects sends
PF_Cmd_FRAME_SETUP, then PF_Cmd_RENDER, then
PF_Cmd_FRAME_SETDOWN. All effect plug-ins must respond to PF_Cmd_RENDER.
PF_Cmd_ABOUT is sent when the user chooses About… from the Effect Controls Window
(ECW).
PF_Cmd_GLOBAL_SETDOWN Free all global data (only required if you allocated some).
Sequence Selectors
These control sequence data handling.
PF_Cmd_SEQUENCE_FLATTEN Sent when saving and when duplicating the sequence. Flatten
sequence data containing pointers or handles so it can be
written to disk. This will saved with the project file. Free the
unflat data and set the out_data>sequence_data
to point to the new flattened data. Flat data must be correctly
byte-ordered for file storage.
As of 6.0, if an effect’s sequence data has recently been
flattened, the effect may be deleted without receiving an
additional PF_Cmd_SEQUENCE_SETDOWN. In this
case, After Effects will dispose of your flat sequence data.
Frame Selectors
Passed for each frame (or set of audio samples) to be rendered by your plug-in.
PF_Cmd_AUDIO_SETUP Sent before every audio render. Request a time span of input
audio. Allocate and initialize any sequence-specific data. If
your effect requires input from a time span other than the
output time span, update the startsampL and
endsampL field in PF_OutData.
PF_Cmd_SMART_PRE_RENDER SmartFX only. Identify the area(s) of input the effect will
need to produce its output, based on whatever criteria the
effect implements.
PF_Cmd_SMART_RENDER SmartFX only. Perform rendering and provide output for the
area(s) the effect was asked to render.
Messaging
The communication channel between After Effects and your plug-in.
PF_Cmd_EVENT This selector makes use of the extra parameter; the type
of event to be handled is indicated by the e_type field, a
member of the structure pointed to by extra. See Effect
UI & Events.
After Effects communicates system, project, layer and audio information using PF_InData.
This structure is updated before each command selector is sent to a plug-in. Fields valid only
during specific PF_Cmds are noted. Also, don’t worry; although PF_InData is dauntingly
large, you need not memorize each member’s purpose; you’ll use some of the fields some of
the time.
TABLE 5: PF_INDATA
Name Description
inter Callbacks used for user interaction, adding parameters, checking whether the user has
interrupted the effect, displaying a progress bar, and obtaining source frames and
parameter values at times other than the current time being rendered. This very useful
function suite is described in Interaction Callback Functions.
utils Graphical and mathematical callbacks. This pointer is defined at all times.
effect_ref Opaque data that must be passed to most of the various callback routines. After Effects
uses this to identify your plug-in.
version Effects specification version, Indicate the version you need to run successfully during
PF_Cmd_GLOBAL_SETUP.
appl_id The identifier of the invoking application. If your plug-in is running in After Effects,
appl_id contains the application creator code ‘FXTC’. If it is running in Premiere
Pro, it will be ‘PrMr’. Use this to test whether your plug-in, licensed for use with one
application, is being used with another.
what_cpu Under Mac OS this contains the Gestalt value for CPU type (see Inside Macintosh,
volume 6). Undefined on Windows.
what_fpu Under Mac OS this contains the Gestalt value for FPU type. Undefined on Windows.
time_step The duration of the current source frame being rendered. In several situations with
nested compositions, this source frame duration may be different than the time span
between frames in the layer (local_time_step). This value can be converted to
seconds by dividing by time_scale.
When calculating other source frame times, such as for PF_CHECKOUT_PARAM ,
use this value rather than local_time_step.
Can be negative if the layer is time-reversed. Can vary from one frame to the next if time
remapping is applied on a nested composition.
Can differ from local_time_step when source material is stretched or remapped
in a nested composition. For example, this could occur when an inner composition is
nested within an outer composition with a different frame rate, or time remapping is
applied to the outer composition.
This value will be 0 during PF_Cmd_SEQUENCE_SETUP if it is not constant for all
frames. It will be set correctly during PF_Cmd_FRAME_SETUP and
PF_Cmd_FRAME_SETDOWN selectors. WARNING: This can be zero, so check it
before you divide.
total_time Duration of the layer. If the layer is time-stretched longer than 100%, the value will be
adjusted accordingly; but if the layer is time-stretched shorter, the value will not be
affected. If time remapping is enabled, this value will be the duration of the composition.
This value can be converted to seconds by dividing by time_scale.
local_time_step Time difference between frames in the layer. Affected by any time stretch applied to a
layer. Can be negative if the layer is time-reversed. Unlike time_step, this value is
constant from one frame to the next. This value can be converted to seconds by dividing
by time_scale.
For a step value that is constant over the entire frame range of the layer, use
local_time_step, which is based on the composition’s framerate and layer
stretch.
shutter_angle Motion blur shutter angle. Values range from 0 to 1, which represents 360
degrees. Will be zero unless motion blur is enabled and checked for the target
layer. shutter_angle == 180 means the time interval between
current_time and current_time + 1/2 time_step. Valid only if
PF_OutFlag_I_USE_SHUTTER_ANGLE was set during
PF_Cmd_GLOBAL_SETUP.
See the section on Motion Blur for details on how to implement motion blur in
your effect.
width Dimensions of the source layer, which are not necessarily the same as the width and
height fields in the input image parameter. Buffer resizing effects can cause this
height difference. Not affected by downsampling.
extent_hint The intersection of the visible portions of the input and output layers; encloses the
composition rectangle transformed into layer coordinates. Iterating over only this
rectangle of pixels can speed your effect dramatically. See notes later in this chapter
regarding proper usage.
output_origin_x The origin of the output buffer in the input buffer. Non-zero only when the effect
changes the origin.
output_origin_y
downsample_x Point control parameters and layer parameter dimensions are automatically adjusted to
compensate for a user telling After Effects to render only every nth pixel. Effects need
downsample_y the downsampling factors to interpret scalar parameters representing pixel distances in
the image (like sliders). For example, a blur of 4 pixels should be interpreted as a blur of
2 pixels if the downsample factor is 1/2 in each direction (downsample factors are
represented as ratios.) Valid only during
PF_Cmd_SEQUENCE_SETUP,
PF_Cmd_SEQUENCE_RESETUP,
PF_Cmd_FRAME_SETUP and
PF_Cmd_FRAME_RENDER.
in_flags Unused.
frame_data
start_sampL Starting sample number, relative to the start of the audio layer.
pica_basicP Pointer to the PICA Basic suite, used to acquire other suites.
pre_effect_ Origin of the source image in the input buffer. Valid only when sent with a frame
source_origin_x selector. Non-zero only if one or more effects that preceded this effect on the same layer
resized the output buffer and moved the origin. Check for both the resize and the new
pre_effect_ origin to determine output area. This is useful for effects which have implicit spatial
source_origin_y operations (other than point controls), like flipping a file around an image’s center.
NOTE: Checked-out point parameters are adjusted for the pre-effect origin at the
current time, not the time being checked out.
shutter_phase Offset from frame time to shutter open time as a percentage of a frame duration.
EXTENT_HINT USAGE
Use extent_hint to process only those pixels for which output is required; this is one of
the simplest optimizations you can make. Tell After Effects you use
in_data>extent_hint by setting PF_OutFlag_USE_OUTPUT_EXTENT in
PF_OutData during PF_Cmd_GLOBAL_SETUP (and in your PiPL).
Disable caching from the preferences menu before testing extent_hint code, so After
Effects renders your effect whenever anything in your composition changes. Otherwise, the
caching mechanism would obscure your plug-in’s (possibly incorrect) output.
Move the layer within the composition so it’s cropped. The output>extent_hint is the
portion of the layer which is visible in the composition. Add a mask to your layer and move it
around. This changes the extent_hint, which encloses all of the non-zero alpha areas of
the image. The in_data>extent_hint is the intersection of these two rectangles (the
composition and the mask), and changes whenever they do.
Account for downsampling when computing output size; users must be able to render at full
resolution. If the output buffer exceeds 30,000 by 30,000, clamp it to that size, and consider
displaying an alert dialog.
Once your code behaves correctly, enable the cache and see how frequently the effect needs to
re-render. Consider a drop shadow; users frequently apply a static drop shadow to a still
image. The output>extent_hint is ignored, so the cache is used more often.
As of 6.0, the extent_hints passed are 20% larger than the layer itself, to help with our
predictive rendering decisions. Numerous effects expand the buffer “just a touch”, and After
Effects often uses the hint rectangles later.
Effects which expand the output buffer position the original layer’s upper left corner by
setting set output_origin_x/y in PF_InData during PF_Cmd_FRAME_SETUP. This
shift is reported to subsequent effects in the pre_effect_source_origin_x/y . Point
parameters are adjusted for this shift automatically.
Apply a buffer expander such as Gaussian Blur or the Resizer SDK sample, before your
effect, and use a large resize value. If your effect is not handling
pre_effect_source_origin_x/y correctly, turning the blur on and off will shift the
position of the output.
All point parameter values (at any time) have shift values described by
pre_effect_source_origin_x/y. For most effects this works transparently. However, if
a buffer expansion changes over time (as with an animated blur amount), the origin shift will
move non-animated points. Consider this when designing effects which cache point
parameter values between frames.
Communicate changes made by your plug-in to After Effects using PF_OutData. Valid
times for altering these fields are noted.
TABLE 6: PF_OUTDATA
Field Description
my_version Set this flag (using the PF_VERSION macro) to the version of your plug-in
code. After Effects uses this data to decide which of duplicate effects to load.
name Unused.
global_data Handle which will be returned to you in PF_InData with every call. Use
After Effects’ memory allocation functions.
num_params After Effects checks this field against the number of calls made to
PF_ADD_PARAM , as well as the implicit input layer.
flat_sdata_size Unused (After Effects knows the size, because you used its allocation functions
to get the memory in the first place).
width, height, origin Set during PF_Cmd_FRAME_SETUP if the output image size differs from
the input. width and height are the size of the output buffer, and
origin is the point the input should map to in the output. To create a 5-
pixel drop shadow up and left, set origin to (5, 5).
return_msg After Effects displays any C string you put here (checked and cleared after
every command selector).
dur_sampL
dest_snd
These flags communicate capability and status information to After Effects. In previous
versions they were also used to send rudimentary messages, e.g. refresh the UI, send an error
message. These capabilities have been supplanted by function suites, and all new messaging
functions will come in that format. However, capability flags are still contained in the PiPL.
Update both the PiPL and your source code when you make a change. Many of these flags
can be changed during an After Effects session.
TABLE 7: PF_OUTFLAGS
Flag Indicates
PF_OutFlag_KEEP_RESOURCE_OPEN The plug-in’s resources must be available during all
commands. During PF_Cmd_GLOBAL_SETUP , the
plug-in’s resources are always open, but unavailable at all
other times (except during PF_Cmd_ABOUT and
PF_Cmd_DO_DIALOG), unless this flag has been set. Set
if you need access to resources at any time other than during
PF_Cmd_GLOBAL_SETUP. NOTE: We recommend the
plug-in load and store the necessary resources in global data,
rather than keeping the file’s resources open.
PF_OutFlag_NON_PARAM_VARY With this flag set, After Effects will not cache output when
the effect is applied to a still. Otherwise, After Effects will
cache your output to be used to render other frames, if
possible.
Set this flag if output varies based on something besides a
parameter value. If the effect produces changing frames when
applied to a still image and all parameters are constant, that's
a sure sign that this bit should be set (e.g. Wave Warp).
Particle effects, for example, will need this.
Set during PF_Cmd_GLOBAL_SETUP. Can be over-
ridden dynamically if needed during
PF_Cmd_QUERY_DYNAMIC_FLAGS. Turn this off
whenever possible to improve performance.
PF_OutFlag_I_WRITE_INPUT_BUFFER The effect writes into the input buffer. This is of limited use;
while saving an allocation, it invalidates some pipeline
caching. Set during PF_Cmd_GLOBAL_SETUP.
PF_OutFlag_WORKS_IN_PLACE Unused.
PF_OutFlag_SQUARE_PIX_ONLY Unused.
PF_OutFlag_RESERVED5 Unused.
PF_OutFlag_I_AM_OBSOLETE Effect is available for use when working with an old project in
which it was originally applied, but doesn’t appear in the
effect menu.
PF_OutFlag_PiPL_OVERRIDES After Effects will use PiPL outflags, and ignore those set
_OUTDATA_OUTFLAGS during PF_Cmd_GLOBAL_SETUP.
PF_OUTFLAGS2
We added a second set of outflags in After Effects 5.0; partly for room to expand in the
future, and partly to break ourselves of the bad habit of repurposing existing flags. As with
PF_OutFlags, many of these flags can be changed during an After Effects session. And don’t
forget to update both the PiPL and your source code when you make a change.
TABLE 8: PF_OUTFLAGS2
Flag Indicates
PF_OutFlag2_NONE Nothing.
PF_OutFlag2_PARAM_GROUP_START_ This flag in itself doesn’t control the state of the param group
COLLAPSED_FLAG twirlies. The initial collapse state of each individual parameter
group is set during PF_Cmd_PARAM_SETUP, by setting
the PF_ParamFlag_START_COLLAPSED flag in
PF_ParamFlags. But those individual settings will not be
honored unless the effect sets this bit. Otherwise, all parameter
groups will be collapsed by default. Remember to set this flag
in both the PiPL and here during
PF_Cmd_GLOBAL_SETUP.
PF_OutFlag2_REVEALS_ZERO_ALPHA This is the one flag implementors need to pay most attention to
since it represents a change in the default behavior. Set this flag
if the effect can take pixels with zero alpha and reveal the
RGB data in them (like our Set Channels effect). This tells
After Effects not to trim such pixels when determining the
input for the effect. This flag can be changed during
PF_Cmd_QUERY_DYNAMIC_FLAGS. Note that, while
this flag can cause changes to the size of the extent_hint,
it will not change the image buffer size.
As of 6.0, pixels outside the mask’s bounding box are zeroed. If
your effect can reveal such pixels, tell AE not to throw away
these RGB values by setting this flag. If your effect does not
always reveal such pixels, set this bit dynamically.
To see if your effect needs this bit set, apply a mask
significantly smaller than the layer to a solid, then apply the
effect and set it to its alpha-modifying state. If the rectangular
bounding box of the mask becomes visible, this bit needs to be
set.
PARAMETERS
Parameters are streams of values that vary with time; the source image, sliders, angles,
points, colors, paths, and any arbitrary data types the user can manipulate. They are passed
to the plug-in as an array of PF_ParamDefs, though the values in the array are only valid
during certain selectors.
One of the best aspects of the After Effects effect API is the parameter interpolation and
management. How much does the shutter angle change during one-fourth of a 29.97 fps
frame? Not your problem; leave it to After Effects.
PF_Param_COLOR PF_ColorDef RGB value (alpha is not used) that the user can
choose either with the standard color picker or
cd
with an eye dropper tool. For floating point
PF_Pixel accuracy, use the PF Color Param Suite to
retrieve the values.
If your slider seems disabled but not grayed out, check the valid_min, slider_min,
valid_max and slider_max fields. Is the param a PF_Param_FIX_SLIDER ? If so, did
you convert your mins and maxs to reasonable fixed values? If you’re using the macros
provided in AE_Macros.h, they’re expecting to receive ints; passing fixed point values won’t
work.
After Effects modifies any point parameter to account for origin offset, introduced by
“upstream” effects that modify the output dimensions. Even if the ECP UI indicates the
value of the point parameter is (0,0), the offset has already been factored in.
PF_PARAMDEF
After Effects passes effects an array of PF_ParamDefs with each selector, describing the
plug-in’s parameters at the current time. The values in the params array are only valid during
some selectors (this is noted in the selector descriptions).
PARAM ZERO
The first parameter, params[0], is the input image (a PF_EffectWorld ) to which the
effect should be applied.
All parameter types are represented by a PF_ParamDef. Unions are used, so that only the
pertinent parts of the PF_ParamDef need be (or should be) populated.
A_short ui_width Width and height of the parameter’s user interface (for
non-standard parameters only).
A_short ui_height
Control a parameter’s user interface with these flags. Don’t confuse UI flags with behavior
flags; they reside in different fields within your parameter’s definition, and will cause
unpredictable behavior if misapplied.
PF_PUI_CONTROL Set this flag if you handle PF_Cmd_EVENTs for the control
area (area that becomes invisible when you twirl up a
parameter's spinner) in the ECP. If you set this flag, you must
also set PF_OutFlag_CUSTOM_UI at
PF_Cmd_GLOBAL_SETUP time. See Events for more details.
PF_PUI_STD_CONTROL_ONLY Set this flag if you want the standard control only -- No data
stream will be associated with this parameter, and thus no
keyframes will be available in the Timeline panel.
You might want to do this to control something in your
sequence data with a standard control. Or in your arb data, or
custom UI in the comp window, or to group-set multiple other
controls.
This flag cannot be used with PF_Param_CUSTOM,
PF_Param_NO_DATA, PF_Param_LAYER,
PF_Param_ARBITRARY_DATA, PF_Param_PATH.
If you set this flag, you must also set
PF_ParamFlag_SUPERVISE (otherwise you would never
find out about value changes, and the setting would never be
used for anything). This flag does not require that the
PF_OutFlag_CUSTOM_UI flag be set.
If you want a standard control for
PF_Param_ARBITRARY_DATA, just add one (or more) using
PF_PUI_STD_CONTROL_ONLY with the supported param
types, and then when handling
PF_Cmd_USER_CHANGED_PARAM you can modify your
arb data.
PF_PUI_ECW_SEPARATOR Not used in After Effects, but used in Premiere. Set this flag if
you'd like a thick line above this parameter in the effect control
window. This is provided so that parameters can be grouped
visually, if needed (without adding groups). This flag can be
changed at runtime through the PF_UpdateParamUI() method.
Behavior flags and UI flags describe different qualities of a parameter. Set them before adding
the parameter during PF_Cmd_PARAM_SETUP. Flags which may be set during events are
noted.
PF_ParamFlag_CANNOT_INTERP Values are not algebraically interpolated. You can still use
discontinuous (hold) interpolation. Useful for parameters
which are either on or off. Accelerates rendering.
PF_VALUEDISPLAYFLAGS
We know you’d never do anything like this, but if you create a parameter which displays as a
percentage, don’t confuse the user by allowing any range other than 0 to 100. Please. Percent
means ‘out of one hundred’.
rowbytes The length, in bytes, of each row in the image’s block of pixels. The
block of pixels contains height lines each with width pixels
followed by some bytes of padding. The width pixels (times four,
because each pixel is four bytes long) plus optional extra padding adds
up to rowbytes bytes. Use this value to traverse the image data.
Platform-specific padding at the end of rows makes it unwise to
traverse the entire buffer. Instead, find the beginning of each row using
height and rowbytes.
NOTE: This value does not vary based on whether field rendering is
active.
NOTE: Input and output worlds with the same dimensions can use
different rowbytes values.
height
extent_hint The smallest rectangle encompassing all opaque (non-zero alpha) pixels
in the layer. This defines the area which needs to be output. If your
plug-in varies with extent (like a diffusion dither), ignore this and
render the full frame each time.
ROWBYTES IN PF_EFFECTWORLDS
Don't assume that you can get to the next scanline of a PF_EffectWorld using (width *
sizeof(current_pixel_type)) + 4, or whatever; use the PF_EffectWorld’s
rowbytes instead. Never write outside the indicated region of a PF_EffectWorld; this can
corrupt cached image buffers that don't belong to you.
To test whether your effects are honoring the PF_EffectWorld>rowbytes , apply the
Grow Bounds effect after your effect. The output buffer will have larger rowbytes than the
input (though it will still have the same logical size).
BYTE ALIGNMENT
DEEPER COLOR
Beyond 8-bit per channel color, After Effects supports 16 bit and 32-bit float per-channel
color. Effects will never receive input and output worlds with differing bit depths, nor will
they receive worlds with higher bit depth than they have claimed to be able to handle.
Use the following macros to access the data within (opaque) PF_PixelPtrs. It is,
emphatically, not safe to simply cast pointers of one type into another! To make it work at
all requires a cast, and there's nothing that prevents you from casting it incorrectly. We may
change its implementation at a later date (at which time you’ll thank us for forcing this level
of abstraction).
*wP,
PF_GET_PIXEL_DATA16 (
pP0,
PF_EffectWorld
PF_PixelPtr
PF_Pixel16 **outPP);
*wP,
PF_GET_PIXEL_DATA8 (
pP0,
PF_EffectWorld
PF_PixelPtr
PF_Pixel8 **outPP);
This returns deep_pixelP as NULL if the world does not have deep pixels. The second
parameter is not used very often and should be passed as NULL; pass a PF_PixelPtr that is
not contained in a PF_EffectWorld to coerce it to the depth of that PF_EffectWorld).
Always, always, always (always!) return a PF_Err from main(). Plug-ins must pass all errors
back to After Effects. It is vitally important that you pass any errors (returned to you by
callbacks and PICA suites) to After Effects, unless you’ve handled them. Be vigilant about
returning the right error code, and disposing of any memory you’ve allocated. Really. We’re
serious.
After Effects has a consistent policy for error handling; follow it.
If you encounter an error in your plug-in’s code, report it to the user immediately, before
returning from your plug-in to After Effects. After Effects considers errors from the
operating system, encountered during your plug-in’s execution, to be yours. If you get an
error code back from one of our callback functions, pass it back to After Effects; we’ve
already reported it. Out-of-memory errors are never reported by After Effects. Error
reporting is always suppressed during RAM preview, and when After Effects is running in -
noui mode.
Now you have a basic understanding of effect plug-ins, and are ready to start experimenting
with some real code. Go ahead and get started!
After getting the basics of your plug-in setup, you may have some questions about reuseable
code, advanced functionality, and how to optimize your code to make it faster. To this end,
After Effects exposes a tremendous amount of its internal functionality via function suites.
By relying on After Effects code for utility functions, you should be able to get your image
processing algorithms implemented quickly. This will discussed in the next chapter.
3: Effect Details
Now that we’ve covered the basics of effect plug-ins, we’ll cover some of the finer points to
polish off your effect. Not every section will be relevant to every plug-in, so feel free to use
the PDF document bookmarks to skip to the sections pertinent to your current project.
After Effects provides effect plug-ins with as much information and supporting code as
possible. Use our function suites and callbacks to obtain the value of parameters (including
source footage) at different times. Use our memory allocation suite to avoid competing with
the host for resources. Use our image processing suites to copy, fill, blend and convolve
images, and convert between color spaces. Obtain information about the masks applied to a
layer. ANSI emulation and math utility suites are also provided, as well as information
about the application, user, serial number, and current drawing context.
Previous versions of After Effects have provided functions for many common tasks. As we
moved to support deeper color, these were moved to function suites. Use the newer function
suites whenever possible; things will just be better.
Using our function suites keeps your plug-in compact; you write and test less code. The
functions are tested, optimized, and used by our own plug-ins. The functions are distributed
to multiple processors and take advantage of available hardware acceleration.
If you are writing C++ code, accessing functions in our PICA function suites is a breeze,
using the AEGP_SuiteHandler, which automatically acquires the suite when needed, and
disposes of it when done. Just instantiate the handler like so:
AEGP_SuiteHandler suites(in_data->pica_basicP);
If you must use C code, then acquire and release the suites manually using the
PF_Suite_Helper utility files, as demonstrated in the Checkout sample project.
Behind the scenes, these both of these methods acquire PICA function suites using
AcquireSuite, a member function of the SPBasicSuite pointed to in PF_InData .
SUITE VERSIONS
WhizBangSuite1 may provide a Foobar() function which takes two arguments, and
WhizBangSuite2>Foobar() may take three. Though each new version of a suite supercedes
the old one, feel free to acquire multiple versions of the same suite; we never remove or alter
previously shipped suites.
When unsure of the capabilities of the plug-in host (no third party host besides Premiere
supports PICA), attempt to acquire the latest version, and “fall back” to previous versions. If
functionality you require isn’t available, warn the user, and return an error (or fall back on
other behavior when running in more “primitive” plug-in hosts). Note that support for these
suites in other hosts of After Effects plug-ins is a maze of twisty caves and passages, all alike.
THREADING
Unless documented otherwise, assume that any function provided by our suites is not
thread-safe. For example, only your plug-in’s main thread should do anything that modifies
the user interface.
MEMORY ALLOCATION
Use After Effects for any memory allocations of significant size. For small allocations, you
can use new and delete, but this is the exception, not the rule. In low-memory conditions
(such as during RAM preview), it’s very important that plug-ins deal gracefully with out-of-
memory conditions, and not compete with After Effects for OS memory. By using our
memory allocation functions, After Effects can know when to free cached images, to avoid
memory swapping. Failing to use our functions for sizable allocations can cause lock-ups,
crashes, and tech support calls. Don’t do that.
Handles passed to you by After Effects are locked for you before you’re called, and unlocked
once you return.
PF_Handle pf_handle);
Unlocks a handle. Replaces PF_UNLOCK_HANDLE.
void (*host_unlock_handle)(
host_unlock_handle
PF_Handle pf_handle);
Frees a handle. Replaces PF_DISPOSE_HANDLE.
void (*host_dispose_handle)(
host_dispose_handle
PF_Handle pf_handle);
host_get_handle_size Returns the size, in bytes, of the reallocatable block whose handle is
passed in. Replaces PF_GET_HANDLE_SIZE.
A_HandleSize (*host_get_handle_size)(
PF_Handle pf_handle);
Resizes a handle. Replaces PF_RESIZE_HANDLE.
PF_Err (*host_resize_handle)(
host_resize_handle
A_HandleSize new_sizeL,
PF_Handle *handlePH);
Use these functions to create and destroy PF_EffectWorld s, and to find out their bit-
depth.
ITERATION SUITES
Effects often iterate over all pixels in an image, filtering each one. By taking advantage of
After Effects’ iteration suites, you make it possible for After Effects to sub-allocate your task
to as many processors are present, taking advantage of hardware-specific acceleration. After
Effects will also manage progress reporting and user cancellation automatically. Use these
*area,
PF_EffectWorld *src,
const PF_Rect
A_u_char *a_lut0,
A_u_char *r_lut0,
A_u_char *g_lut0,
A_u_char *b_lut0,
PF_EffectWorld *dst);
After Effects exposes its internal transform and graphic utility routines through the
following function suites.
These functions combine PF_EffectWorlds in interesting ways. When you use these, you’re
using the same code After Effects does internally.
blend Blends two images, alpha-weighted. Does not deal with different-sized
sources, though the destination may be either PF_EffectWorld.
PF_Err blend (
PF_ProgPtr effect_ref,
const PF_EffectWorld *src1,
const PF_EffectWorld *src2,
PF_Fixed ratio,
PF_EffectWorld *dst);
copy_hq A higher fidelity version of the above (using the same parameters).
KERNEL FLAGS
Functions such as convolve or gaussian kernel work with kernels, or matrices of filter weight
values. These matrices can be in any format. The kernel flags describe how the matrices
should be created and used. OR together any flags you need. The flags relevant to given
PF_KernelFlag_CLAMP CLAMP restricts values to the valid range for their data
PF_KernelFlag_NO_CLAMP type.
The FillMatteSuite can be used to fill a PF_EffectWorld, either with a specific color or
premultiplied with an alpha value.
premultiply Converts to (and from) r, g, and b color values pre-multiplied with black to
represent the alpha channel. Quality independent. forward is used as a
boolean; true means convert non-premultiplied to pre-multiplied, false
mean un-pre-multiply.
PF_Err premultiply (
A_long forward,
PF_EffectWorld *dst);
effect_ref,
PF_Err premultiply_color (
PF_ProgPtr
PF_EffectWorld *src,
PF_Pixel *color,
A_long forward,
PF_EffectWorld *dst);
Note: areas outside the bounds of the image being sampled are treated as zero alpha. For
convenience, the functions from PF_Sampling8Suite1, PF_Sampling16Suite1, and
PF_SamplingFloatSuite1 are all listed in this table.
effect_ref,
PF_Err nn_sample (
PF_ProgPtr
PF_Fixed x,
PF_Fixed y,
const PF_SampPB *params,
PF_Pixel *dst_pixel );
effect_ref,
PF_Err subpixel_sample (
PF_ProgPtr
PF_Fixed x,
PF_Fixed y,
const PF_SampPB *params,
PF_Pixel *dst_pixel);
effect_ref,
PF_Err area_sample (
PF_ProgPtr
PF_Fixed x,
PF_Fixed y,
const PF_SampPB *params,
PF_Pixel *dst_pixel);
NOTE: Areas outside the boundaries of the layer are considered the same as
zero alpha, for sampling purposes.
effect_ref,
PF_Err (*begin_sampling)(
PF_ProgPtr
PF_Quality qual,
PF_ModeFlags mf,
PF_SampPB *params);
effect_ref,
PF_Err (*end_sampling)(
PF_ProgPtr
PF_Quality qual,
PF_ModeFlags mf,
PF_SampPB *params);
effect_ref,
PF_Err (*get_batch_func)(
PF_ProgPtr
PF_Quality quality,
PF_ModeFlags mode_flags,
const PF_SampPB *params,
PF_BatchSampleFunc *batch);
effect_ref,
PF_Err (*get_batch_func16)(
PF_ProgPtr
PF_Quality quality,
PF_ModeFlags mode_flags,
const PF_SampPB *params,
PF_BatchSample16Func *batch);
Along with the variety of graphics utilities, we also provide a block of ANSI standard
routines so that plug-ins will not need to include other libraries to use standard functions.
We give function pointers to a large number of math functions (trig functions, square root,
logs, etc.).
Using our suite functions provides for some (application level) error handling, and prevents
problems with including different versions of multiple “standard” libraries.
All functions return a double. All angles are expressed in radians, use PF_RAD_PER_DEGREE
(a constant from AE_EffectCB.h) to convert from degrees to radians if necessary.
While the un-macro’d function pointers are provided in PF_InData , use the provided
macros to access them. See how stringent we are about deprecating macro usage? Let’s let
this be our little secret.
Param_Utils.h:
We provide convenience macros for specific parameter types, in Utils/
PF_ADD_COLOR,
PF_ADD_ARBITRARY,
PF_ADD_SLIDER,
PF_ADD_FIXED,
PF_ADD_FLOAT_SLIDERX,
PF_ADD_CHECKBOXX,
PF_ADD_BUTTON,
PF_ADD_ANGLE,
PF_ADD_NULL,
PF_ADD_LAYER,
PF_ADD_255_SLIDER,
PF_ADD_PERCENT,
PF_ADD_POINT,
PF_ADD_POINT_3D,
PF_ADD_TOPICX,
PF_END_TOPIC,
PF_ADD_POPUPX,
PF_ADD_FLOAT_SLIDERX_DISABLED
PF_ABORT Returns non-zero if the user has cancelled; return that value to After Effects.
Wrap your render routine in a “while abort has not been requested” while
loop.
PF_Err PF_ABORT (PF_InData *in_data);
PF_CHECKOUT_PARAM Obtains parameter values, or the source video layer, at a specified time. After
Effects makes caching decisions based on the checkout state of parameters.
Allocate a new PF_ParamDef to hold the result; those passed to the plug-
in are read-only. If you check out a layer parameter that’s set to <none>, the
layer returned will be filled with zeros. Masks are not included with checked-
out layers.
Do not check out layer parameters during UI event handling.
PF_Err PF_CHECKOUT_PARAM (
PF_InData *in_data,
PF_ParamIndex index,
A_long what_time,
A_long step,
A_long time_scale,
PF_ParamDef *param);
If checking out the source layer, a deinterlaced frame will be returned. If you
ask for the time that references the upper field, you will receive back the
upper field with a filter used to generate the extra scanlines. For example,
assuming line 0 and 2 are upper fields, and line 1 is a lower field, if you check
out the upper fields, line 0 and 2 will be passed back directly from the source
footage, and line 1 will be calculated by averaging lines 0 and 2. If you want
to reassemble a full resolution source frame with both fields present, you can
call PF_CHECKOUT_PARAM twice to get both fields, and reinterlace the
footage.
What happens when checking out a layer at a time that is not frame-aligned?
All items have essentially infinite time resolution, so when asking for a time at
any value, AE renders the item at that time. For a composition, that involves
interpolating all of the keyframes values to the subframe time. For footage,
AE returns a full image that corresponds to the time asked, which is the
nearest-to-left frame. If the user has frame-blending on that layer, an
interpolated frame is generated.
Effects are applied to an image in order from 0 to n within the Effect Control (and
Composition) panel. The output from effect[n-1] is the input ( param[0] ) of effect[n]. On
the other hand, when a normal effect checks out a layer using PF_CHECKOUT_PARAM , it
receives the raw (un-effected) source layer, regardless of its order. However, when a
SmartFX effect checks out its input parameter ( params[0]), previous effects are applied.
Regardless of whether the layer in and out point have been trimmed, you will get valid
frames from the start of the source footage to the end, and then transparent before and after
that.
Layer params with a lower frame rate than the composition in which they’re checked out are
only refreshed as often as necessitated by the lower frame rate. A 10fps layer checked out in
a 30fps composition will only need to be refreshed every third frame. if your effect wants to
change it’s output every frame despite the static input layer, you’d need to set
PF_Outflag_NON_PARAM_VARY .
Plug-ins that check out layers at different times can generate re-entrant behavior. Consider
an instance where the Checkout sample plug-in is applied to a layer in composition B, and B
is pre-composed into composition A where Checkout is applied to it as well. When
composition A is rendered, Checkout[A] will be sent PF_Cmd_RENDER, during which it
checks out a layer (composition B) from a time other than the current time. In order to
provide that checked-out layer, After Effects sends PF_Cmd_RENDER to Checkout[B].
Presto, recursion!
If you’re going to check out parameters, your effects must handle re-entrant render requests
appropriately. Don’t use globals, or read or write static variables...but you weren’t going to
anyway, right?
After Effects strives to be as responsive as possible to user interaction, even while rendering.
Do the same through appropriate use of PF_ITERATE(). For example, perhaps you’re using a
PF_ITERATE’d function three times during your response to PF_Cmd_RENDER. In this case,
you’d start off with:
lines_per_iterateL = in_data>extent_hint.top -
in_data>extent_hint.bottom;
total_linesL = 3 * lines_per_iterateL;
lines_so_farL = 0;
After each iteration, you’d add the already-completed lines to the current position.
suites.iterate8suite()>iterate( lines_so_farL,
total_linesL,
&output>extent_hint,
input_worldP,
refcon,
WhizBangPreProcessFun,
output_worldP);
lines_so_farL += lines_per_iterateL;
ERR(PF_PROGRESS(lines_so_farL, total_linesL));
&output>extent_hint,
input_worldP,
refcon,
WhizBangRenderFunc,
output_worldP);
lines_so_far += lines_per_iterateL;
ERR(PF_PROGRESS(lines_so_farL, total_linesL));
suites.iterate8suite()>iterate( lines_so_farL,
total_linesL,
&output>extent_hint,
input_worldP,
refcon,
WhizBangPostProcessFunc,
output_worldP);
ERR(PF_PROGRESS(lines_so_farL, total_linesL));
Effects must respond correctly to footage with non-square pixels, and non-uniform
downsampling factors. Even different layer parameters can have different pixel aspect ratios!
Doing so isn’t difficult once you understand the concepts involved.
Simple effects needn’t do any work to match up point parameters to the actual pixels in the
output. Point parameters are given to the effect scaled for downsample factor and pixel
aspect ratio; they are in the coordinate system of the input buffer. This provides an implicit
“pixel coordinate system.” This coordinate system is handy and easy to understand. But
effects that use absolute pixel measurements or geometry must take a deeper look at the
relationship between the input buffer and the final rendered image.
First, it is not necessarily a square coordinate system, due to both pixel aspect ratio and non-
uniform downsample factor. The final rendered image can be stretched or squashed
horizontally, relative to the pixels your effect processes. Circles will appear as ellipses,
squares as rectangles. The distance between two points varies based on their angle in this
coordinate system; anything rotated in this system is skewed, in the final output.
Sometimes these issues aren't a problem. Any effect that colors pixels based solely on a linear
function of the x and y coordinates need not bother with pixel aspect ratio and downsample
factor at all. Staying in the input coordinate space is an option, though you must account for
pixel aspect ratio and downsample factor elsewhere.
Suppose you're writing a particle system effect that sprays textured sprites from a source
position defined by an effect control point. Using pixel coordinates to represent the particle
positions seems fine (as long as the particles don't have to rotate around a point), but when
you go to actually render the particle textures, you'll have to scale them by pixel aspect ratio
and downsample factor.
SUGGESTED APPROACH
The simplest way to get all of this right is to work entirely in full resolution square
coordinates, then scale by downsample factor and pixel aspect ratio as a final output
transformation. Since point parameters are always reported in input buffer coordinates,
convert them to full-resolution square coordinates before use. With this approach you don't
need to worry about sliders which define a size in pixels; just interpret them as defining size
in full-resolution vertical pixels.
1) When getting your point parameters, go immediately to floating point and a full
resolution square pixel system, like this:
x *= in_data>pixel_aspect_ratio.num /
(float)in_data>pixel_aspect_ratio.den;
x *= in_data>downsample_x.den /
(float)in_data>downsample_x.num;
y *= in_data>downsample_y.den /
(float)in_data>downsample_y.num;
3) To go back to a coordinate system that corresponds directly to the pixels of the output
buffer, undo the transformations from step one. Do this as late as possible, so as little code
as possible needs to deal with this non-square space. If you're using matrices, this would be a
final output transformation. For an effect which renders something based on the coordinate
of each pixel, iterate over the output pixels and convert pixel coordinates to square
coordinates before doing any processing for that pixel.
This may seem like extra work, but most reasonably complex effects like this have a
coordinate transformation step anyway; and if they don't, they still need one to handle pixel
aspect ratio and downsample factor correctly.
After Effects does all of its stretching horizontally so as to not to introduce unnecessary field
interpolations; when pixels are used as a unit, we think of them as vertical pixels.
Test at 1/2, 1/4, and custom resolutions and compare the output. Use an anamorphic (2:1)
pixel aspect ratio composition to track down bugs in pixel aspect ratio handling (it really
makes them obvious), and be sure to test with different horizontal and vertical downsample
factors.
Some developers have reported problems with the downsample factors provided by some
“After Effects compatible” plug-in hosts being zero. Check for zero before dividing.
We have something to admit to you; for years, even though we’ve given you 8 bit color
values, we’ve internally used floating point representations behind your back. That’s right,
even with over-bright colors, we’d only ever tell you ‘255, 255, 255’. Yeah, right. Well, we
can’t live the lie any longer! Given a color parameter (passed to you by After Effects in your
We also provide a way to get floating point values for point parameters.
New in CS6.0.2, we now provide a way to get floating point values for angle parameters.
PARAMETER SUPERVISION
Supervision means dynamically changing the values of some parameters based on the values
of others. To supervise a parameter, set PF_ParamFlag_SUPERVISE before adding it
during PF_Cmd_PARAMS_SETUP. Whenever it is changed, you will receive
PF_Cmd_USER_CHANGED_PARAM. The index (into the plug-in’s parameter array) of
the changed parameter is sent in the PF_UserChangedParamExtra ( extra ) param. During
PF_Cmd_USER_CHANGED_PARAM, you may change the values and appearance of any
of your parameters.
If you set PF_ParamFlag_SUPERVISE on any parameter, After Effects will send you
PF_Cmd_UPDATE_PARAMS_UI, just as if you had set
PF_OutFlag_SEND_UPDATE_PARAMS_UI.
During PF_Cmd_UPDATE_PARAMS_UI, you may only change the appearance and enable
state of parameters. Use PF_UpdateParamUI () from PF_ParamUtilsSuite to update
the UI, passing it a copy of the parameter you wish to modify. Do not attempt to modify the
original. It is not necessary to set PF_OutFlag_REFRESH_UI; PF_UpdateParamUI() handles
that for you. Note also that this is the only way to update the UI of
PF_PUI_STD_CONTROL_ONLY parameters.
When changing parameter values (and not just the UI), modify the original parameter, and
set PF_Paramdef.uu.change_flags to PF_ChangeFlag_CHANGED_VALUE. This change will be
also update the UI, and will be undoable by the user. Note that
PF_ChangeFlag_CHANGED_VALUE isn’t supported for layer parameters.
This suite is provided to give effect plug-ins some access to their parameter streams, without
requiring AEGP suite usage. At least some of these functions are provided by several third-
party hosts. These functions are especially handy for effects with supervised parameters.
PF_AreStatesIdentical PF_AreStatesIdentical(
PF_ProgPtr effect_ref,
const PF_State *state1P,
const PF_State *state2P,
A_Boolean *samePB);
New in CS6. Compare two different states, retrieved using
PF_GetCurrentState, above.
PF_IsIdenticalCheckout PF_IsIdenticalCheckout(
PF_ProgPtr effect_ref,
PF_ParamIndex param_index,
A_long what_time1,
A_long time_step1,
A_u_long time_scale1,
A_long what_time2,
A_long time_step2,
A_u_long time_scale2,
PF_Boolean *identicalPB);
Returns TRUE if a parameter’s value is the same at the two passed
times. Note: the times need not be contiguous; there could be
different intervening values.
PF_GetKeyframeCount PF_GetKeyframeCount(
PF_ProgPtr effect_ref,
PF_ParamIndex param_index,
PF_KeyIndex *key_countP);
Returns the number of keyframes in the parameter’s stream.
PF_CheckoutKeyframe PF_CheckoutKeyframe(
PF_ProgPtr effect_ref,
key_index,
PF_ParamIndex param_index,
*key_timeP0,
PF_KeyIndex
*key_timescaleP0,
A_long
A_u_long
PF_ParamDef *paramP0);
Checks a keyframe for the specified parameter out of our keyframe
database. param_index is zero-based. You can request time,
timescale, or neither; useful if you’re performing your own motion
blur.
PF_CheckinKeyframe PF_CheckinKeyframe(
PF_ProgPtr effect_ref,
PF_ParamDef *paramP);
All calls to PF_CheckoutKeyframe must be balanced with this
check-in, or pain will ensue.
PF_KeyIndexToTime PF_KeyIndexToTime(
PF_ProgPtr effect_ref,
key_indexP,
PF_ParamIndex param_index,
*key_timeP,
PF_KeyIndex
A_long
A_u_long *key_timescaleP);
Returns the time (and timescale) of the specified keyframe.
After Effects allows plug-ins to store data at three scopes; global, sequence, and frame.
Consider carefully where you store information; choosing poorly can impact performance, or
make your plug-in confusing to the user.
Use global data for information common to all instances of the effect: static variables and
data, bitmaps, pointers to other DLLs or external applications.
Store anything specific to this instance of your plug-in (UI settings, text strings, and any
custom data not stored in parameters) in sequence data, Use After Effects’ memory
allocation functions.
Frame data is used for information specific to rendering a given frame. This has fallen into
disuse, as most machines are capable of loading an entire frame into memory at a time. Of
course, your IMAX-generating users will still appreciate any optimizations you can make.
PERSISTENCE
After Effects saves sequence data in the project file, but not global or frame data. Pointers
within sequence data which point to external data are, in all likelihood, invalid upon re-
opening the project, and must be re-connected. We call this process “flattening” and “un-
flattening” the sequence data.
Careful sequence data validation is important for effects that do simulation across time,
where frame N is dependent on frame N-1, and you use a cache of calculated data in your
sequence data. If a parameter is changed, certain calculated data may no longer be valid, but
it would also be wasteful to blindly recalculate everything after every change.
When asked to render frame N, assuming you have your cached data calculated up to frame
N-1, call PF_GetCurrentState() / PF_AreStatesIdentical() to see if the cache of
calculated data is still valid given the current parameter settings. The state of all parameters
(except those with PF_ParamFlag_EXCLUDE_FROM_HAVE_INPUTS_CHANGED set),
including layer parameters (including param[0] ) are checked over the passed time span.
This is done efficiently, as the change tracking is done with timestamps.
If the inputs have not changed, you can safely use your cache, AND the internal caching
system will assume that you have a temporal dependency on the passed range. So if
something changes upstream, the host’s caches will be properly invalidated automatically.
If your sequence data references external memory (in pointers or handles), you must flatten
and unflatten your data for disk-safe storage. This is analogous to creating your own
miniature file format.
Remember, your users (the ones who bought two copies of your plug-in, anyway) may want
the same project to work on Mac OS and Windows. After Effects sends
PF_Cmd_SEQUENCE_RESETUP when the data is reloaded, for either flat or unflat data.
Use a flag at a common offset within both structures to indicate the data’s state.
typedef struct {
A_char* messageZ;
PF_FpLong big_numF;
void* temp_storage;
} non_flat_data;
typedef struct {
char message[256];
PF_FpLong big_numF;
A_Boolean big_endianB;
} flat_data;
Some values are not adequately represented by After Effects existing parameter types. You
can create and register any data for interpolation by After Effects, by creating parameters of
arbitrary data type, or “arb data”. You can rely on our interpolation engine and parameter
management, without having to force your data into a pre-defined parameter type.
We’ve created a new messaging structure for custom data types, which are easily
conceptualized as member (and friend) functions of a C++ class. You must respond to all
selectors detailed here if you use arb data.
These functions deal with custom data structure management. Your arb data will be
unloaded and reloaded at the user’s whim; provide disk-safe flatten and unflatten functions.
PF_Arbitrary_FLATTEN_FUNC Flatten the instance you’re passed, and place it in the supplied
buffer. The buffer will be the size you reported in response to
PF_Arbitrary_FLAT_SIZE_FUNC.
PF_Arbitrary_UNFLATTEN_FUNC Unpack the buffer into an instance of your arbitrary data type,
and put in the handle which you’ve been passed.
PF_Arbitrary_COMPARE_FUNC You are passed two instances of your arbitrary data, and a
pointer to a comparison result. Populate the result with one of
the values for PF_ArbCompareResult (see
AE_Effect.h) to indicate whether the first was equal to,
less than, more than, or simply not equal to the second.
PF_Arbitrary_PRINT_SIZE_FUNC Indicate the buffer size you require for printing your
parameter’s current values by setting print_sizePLu
(member of print_size_func_params, part of the
PF_ArbParamsExtra structure).
PF_Arbitrary_PRINT_FUNC Format your arbitrary data for text-based export, and copy the
result to the buffer. This can be as elaborate as you would like.
Your plug-in should emulate the cut-and-paste behavior for
pasting text representations of parameter settings (into a
Microsoft Excel spreadsheet, for example) displayed by the
plug-ins shipped with After Effects. You have a great deal of
flexibility in how you format your output.
PF_Arbitrary_SCAN_FUNC Given a buffer of text data (often from the system clipboard),
parse it into your arbitrary data format.
In addition to the normal command and event selector, arb data requires another set of host
interaction. This is transparent for other parameter types, as After Effects manages their
representing data. Writing an arb data plug-in will give you insight into the vast amount of
parameter management After Effects performs, and the sequence in which those managing
actions occur. It may even cause you to rethink your implementation, and use the parameter
types After Effects manages for you.
The user may select the arb’s keyframe data in the Timeline panel, copy it, then switch to
another application. You will be sent a PF_Arbitrary_PRINT_SIZE_FUNC; set the size of
your output buffer by setting print_sizePLu in the PF_ArbParamsExtra. You’ll then receive
PF_Arbitrary_PRINT_FUNC; populate the print_bufferPC output buffer with a textual
representation of the Arb(s) in question.
Users may paste keyframe data into your Arb’s timeline. You will receive
PF_Arbitrary_SCAN_FUNC. Create an Arb based on the contents of the character buffer
handed to you (its size is indicated in print_sizeLu).
Your plug-in code must be recursively re-entrant to support custom data types, since it could
be called by After Effects for numerous reasons. Your plug-in could check out a layer that, in
turn, depends on another instance of your effect. Your plug-in’s arbitrary data handling code
will be triggered by your attempt to check out a (seemingly) unrelated layer. Watch out for
calls to C run-time libraries that rely on static values accessed through global variables. If
you’re not prepared for this eventuality, you’ll hang After Effects, and users will curse and
punch their monitors.
After Effects ignores any changes made to arbitrary data parameters during
PF_Cmd_DO_DIALOG. This is by design; changes made during the display of the options
PF_EFFECTUISUITE
Although not strictly concerned with parameters, this suite can change the name of the
options button.
PF_APPSUITE
Roughly 437 years ago, when we released After Effects 5.0, we published some useful utility
callbacks in PF_AppSuite. They’re as useful today as they were then. After Effects has user-
controllable UI brightness. In addition to the PF_EffectCustomUIOverlayThemeSuite for
custom UI in effects, use these calls to integrate seamlessly into the After Effects UI.
PF_GetFontStyleSheet Retrieves font style sheet information for the fonts used in After
Effects’ UI. Trivia: The fonts used in After Effects’ UI are Tahoma on
Windows and Lucida Grande on Mac OS X.
sheet,
PF_GetFontStyleSheet(
*font_nameP0,
PF_FontStyleSheet
*font_numPS0,
PF_FontName
*sizePS0,
A_short
A_short
A_short *stylePS0);
PF_SetCursor Sets the cursor to any of After Effects’ cursors. See AE_EffectUI.h for
a complete enumeration. Set to PF_Cursor_NONE to allow After
Effects to set the cursor. Set to PF_Cursor_CUSTOM if you’ve used
OS-specific calls to change the cursor (After Effects will honor your
changes).
PF_SetCursor(
PF_CursorType cursor);
PF_AppColorPickerDialog Displays the After Effects color picker dialog (which may be the
system color picker, depending on the user’s preferences). Will return
PF_Interrupt_CANCEL if user cancels dialog. Returned color is
in the project’s working color space.
PF_AppColorPickerDialog(
PF_PixelFloat *result_colorP);
PF_InvalidateRect Queue up a redraw of a specific area of the custom UI for an effect. Only
valid while handling a non-drawing event in the effect. Specify rectP0 as
NULL to invalidate the entire window. The redraw will happen at the next
available idle moment after returning from the event. Set the
PF_EO_UPDATE_NOW event outflag to update the window immediately
after the event returns.
PF_InvalidateRect(
const PF_ContextH contextH,
const PF_Rect* rectP0);
*localP,
PF_ConvertLocalToGlobal(
const PF_Point
PF_Point *globalP);
PF_AdvAppSuite was originally designed for some pretty nefarious purposes; an external
application was pretending to be an After Effects plug-in, and required ways to notify After
Effects of the changes it had made to the project. Our API impurity is your gain.
PF_SaveProject Saves the project to the current path. To save the project elsewhere, use
AEGP_SaveProjectToPath().
PF_SaveProject(void);
PF_RefreshAllWindows Forces all After Effects windows to update. Note that although
the Composition panel will be refreshed, this does not guarantee
a new frame will be sent to External Monitor Preview plug-ins.
PF_RefreshAllWindows(void);
PF_InfoDrawColor Draws the specified color in the After Effects info palette (alpha
is ignored).
PF_InfoDrawColor(
PF_Pixel color);
PF_InfoDrawText3 Writes three lines of text into the After Effects info palette.
PF_InfoDrawText3(
const A_char *line1Z0,
const A_char *line2Z0,
const A_char *line3Z0);
PF_InfoDrawText3Plus Writes three lines of text into the After Effects info palette, with
portions of the second and third lines left and right justified.
PF_InfoDrawText3Plus(
const A_char *line1Z0,
const A_char *line2_jrZ0,
const A_char *line2_jlZ0,
const A_char *line3_jrZ0,
const A_char *line3_jlZ0);
PF_AdvTimeSuite provides several functions to match how After Effects displays time. In
fact, these are the same functions we use internally.
PF_FormatTime Contextualizes the formatted time string for the given PF_InData
and PF_EffectWorld (i.e., layer time).
PF_FormatTime(
PF_InData *in_data,
PF_EffectWorld *world,
A_long time_valueUL,
A_u_long time_scaleL,
PF_Boolean durationB,
A_char *time_buf);
Long ago, we helped a developer integrate their stand-alone tracker with After Effects by
exposing a set of functions to give them some way to notify us of, and be notified of, changes
PF_MoveTimeStep Moves num_stepsL in the specified direction, for the active item.
ActiveItem
PF_MoveTimeStepActiveItem(
PF_Step time_dir,
A_long num_stepsL);
PF_TouchActiveItem Tells After Effects that the active item must be updated.
PF_TouchActiveItem (void);
Some file types contain more than just pixel data; use PF_ChannelSuite to determine
whether such information is present, and the macros in AE_ChannelSuites.h to retrieve it in
the format you need.
effect_ref,
PF_GetLayerChannelCount(
param_index,
PF_ProgPtr
PF_ParamIndex
A_long *num_channelsPL);
PF_GetLayerChannel Retrieves (by index) a reference to, and description of, the specified channel.
IndexedRefAndDesc
PF_GetLayerChannelIndexedRefAndDesc(
PF_ProgPtr effect_ref
PF_ParamIndex param_index
*foundPB,
PF_ChannelIndex channel_index,
*channel_refP,
PF_Boolean
PF_ChannelRef
PF_ChannelDesc *channel_descP);
effect_ref,
PF_GetLayerChannelTypedRefAndDesc(
param_index,
PF_ProgPtr
channel_type,
PF_ParamIndex
*foundPB,
PF_ChannelType
*channel_refP,
PF_Boolean
PF_ChannelRef
PF_ChannelDesc *channel_descP);
PF_DataType will be one of the following:
PF_DataType_FLOAT 34 bytes
PF_DataType_DOUBLE 38 bytes
PF_DataType_LONG 34 bytes
PF_DataType_SHORT 32 bytes
PF_DataType_FIXED_16_16 34 bytes
PF_DataType_CHAR 31 byte
PF_DataType_U_BYTE 31 byte
PF_DataType_U_SHORT 32 bytes
PF_DataType_U_FIXED_16_16 34 bytes
PF_DataType_RGB 3 bytes
PF_ChannelType will be one of the following:
PF_ChannelType_DEPTH
PF_ChannelType_NORMALS
PF_ChannelType_OBJECTID
PF_ChannelType_MOTIONVECTOR
PF_ChannelType_BK_COLOR
PF_ChannelType_TEXTURE
PF_ChannelType_COVERAGE
PF_ChannelType_NODE
PF_ChannelType_MATERIAL
PF_ChannelType_UNCLAMPED
PF_ChannelType_UNKNOWN
effect_ref,
PF_CheckoutLayerChannel(
channel_refP,
PF_ProgPtr
what_time,
PF_ChannelRefPtr
duration,
long
time_scale,
long
data_type,
unsigned long
PF_DataType
PF_ChannelChunk *channel_chunkP);
MOTION BLUR
Effects handle their own motion blur, using PF_InData> shutter_angle along with
PF_InData> shutter_phase . The plug-in must set
PF_OutFlag_I_USE_SHUTTER_ANGLE so After Effects knows it needs this information.
They must check out their own parameters at other times to examine their change over the
shutter interval. If the plug-in checks out parameters outside this interval, set
PF_OutFlag_WIDE_TIME_INPUT . Doing so allows After Effects to compare the
parameters within the sampling interval, and determine if they’ve changed.
Paths differ from other parameter types, in that their values are not directly accessible. In
addition to checking them out and in (like layer parameters), you must use our path data
function suites to obtain the details of the path at a given time. See PF_PathQuerySuite
and PF_PathDataSuite . Never use the values present in a path parameter when it’s
passed to you, without first checking it out; while deleted paths will not be available, further
updating is done “lazily” (later); your effect won’t see these changes unless it checks out the
path.
You can also use the AEGP_MaskOutlineSuite to manipulate paths. See “cheating”.Path
parameters are treated as opaque blobs of data; get and set functions must be used to access
VERTICES
Path vertices are more complex than simple points. All member variables are PF_FpLongs
( doubles), and are in the layer’s coordinate space.
tan_in_y
tan_out_y
PF_PATHDATASUITE
PF_PathNumSegments Retrieves the number of segments in the path. N segments means there
are segments [0.N-1]; segment J is defined by vertex J and J+1.
PF_PathNumSegments(
PF_ProgPtr effect_ref0,
PF_PathOutlinePtr pathP,
A_long *num_segmentsPL);
PF_PathPrepare This fairly counter-intuitive function informs After Effects that you’re
SegLength going to ask for the length of a segment (using
PF_PathGetSegLength below), and it’d better get ready.
frequencyL indicates how many times you’d like us to sample the
length; our internal effects use 100.
PF_PathPrepareSegLength(
PF_ProgPtr effect_ref0,
PF_PathOutlinePtr pathP,
A_long which_segL,
A_long frequencyL,
PF_PathSegPrepPtr *lengthPrepPP);
PF_PathEvalSegLength Retrieves the location of a point lengthF along the given path segment.
PF_PathEvalSegLength(
PF_ProgPtr effect_ref0,
PF_PathOutlinePtr pathP,
PF_PathSegPrepPtr *lengthPrepPP0,
A_long which_segL,
PF_FpLong lengthF,
PF_FpLong *x,
PF_FpLong *y);
PF_PathCleanup Call this when you’re finished evaluating that segment length, so After
SegLength Effects can properly clean up the PF_PathSegPrepPtr.
PF_PathCleanupSegLength(
PF_ProgPtr effect_ref0,
PF_PathOutlinePtr pathP,
A_long which_segL,
PF_PathSegPrepPtr *lengthPrepPP);
PF_PATHQUERYSUITE
This suite is used to identify and access the paths associated with the effect’s source layer.
PF_CheckinPath Releases the path back to After Effects. Always do this, regardless of any
error conditions encountered. Every checkout must be balanced by a
checkin, or pain will ensue.
PF_CheckinPath(
PF_ProgPtr effect_ref,
PF_PathID unique_id,
PF_Boolean changedB,
PF_PathOutlinePtr pathP);
Using functions provided in the AEGP_PFInterfaceSuite , effects can access camera and
lighting information for the layer to which they’re applied; see the Resizer sample. You can
also use many of the other functions from AE_GeneralPlug.h; the possibilities are vast.
Different pixel formats are useful for different operations. After Effects exposes its internal
functions through PF_ColorCallbacksSuite. Here are the supported formats.
Plug-ins can draw on image processing algorithms written for nearly any color space by using
the following callback functions.
Hue Given an RGB pixel, eturns its hue angle mapped from 0 to 255, where 0 is 0
degrees and 255 is 360 degrees.
Replaces PF_HUE.
It is possible to add or remove parameters from a plug-in, without forcing users to re-apply
all instances of that plug-in to use the updated version. However, some advance planning on
your part is necessary to allow for such changes. Your users (and technical support staff) will
appreciate the effort.
You must first create a parameter array index. During PF_Cmd_PARAM_SETUP, assign
index values to each parameter as you add them, using a simple enumeration. The order of
enumeration corresponds to the order in which the parameters are registered during
PF_Cmd_PARAM_SETUP, which in turn determines the order in which they appear in the
Effect Control and Timeline panels.
Create another enumeration for disk IDs. The order of this enumeration must not be
changed, though you may add to the end of this list. Note that the order of this list need not
correspond with that of the parameter array index. Parameter disk IDs should range from 1
to 9999. Why not zero? Long story...
In the early “wild west” days of After Effects plug-in programming, it was fairly common for
developers not to bother with setting IDs. After Effects, realizing this, checked the ID of the first
parameter added by that effect; if it was zero, it was assumed that the programmer hadn’t
bothered to ID params; After Effects then assigned each its own ID. This assumption works fine if
you never set param IDs, but not so well if you start numbering your IDs from NULL. That’s
why.
To delete a parameter without forcing re-application, remove the code which creates it and
its entry in the parameter array index list. However, do not remove its entry in the disk ID
list. To add a new parameter, add an entry in the appropriate location in the parameter array
indices list, add the parameter creation code, and append the disk ID to the end of the disk
ID enumeration. To re-order, change the parameter array index list and reorder the
parameter creation code appropriately.
If you don’t, if someone saves a project with the old default and then reads it in with the new
effect installed, that parameter will change to the new default value. Presto! Instant support
call. This is another prime use case for
PF_ParamFlag_USE_VALUE_FOR_OLD_PROJECTS .
BEST PRACTICES
If your prototypes are anything like ours, the first version of your plug-in that runs without
crashing differs radically from the version that actually ships. How your plug-in responds to
things like downsampling, errors and exceptions, pixel aspect ratio, out-of-memory
situations, and being interrupted while processing determines how usable it is (and how
many support requests you’ll have to handle).
RESPONSIVENESS
It’s possible to have your effect show up in the “Effects & Presets” palette when users search
for something other than the plug-in’s name. Apply your effect (leaving the settings at
default, unless you’re very certain the user will want something different when they search
for the given term), and select “Save selection as animation preset” from the effect controls
palette. Save it to the name by which you want users to find the plug-in. Have your plug-in’s
installer put the resultant .ffx file into the \Presets directory, next to the After Effects
executable. Your preset will show up when users search for the name to which it was saved.
Sometimes, instead of just processing every pixel, you’ll want to get to a specific offset within
the input frame. Below is one way to sample the pixel at a given (x,y) location; similar code
could be used to write to the given location.
return (PF_Pixel*)((char*)def.data +
PF_Pixel *sampleIntegral32(PF_EffectWorld &def, int x, int y){
(y * def.rowbytes) +
(x * sizeof(PF_Pixel)));
}
return (PF_Pixel16*)((char*)def.data +
assert(PF_WORLD_IS_DEEP(&def));
(y * def.rowbytes) +
(x * sizeof(PF_Pixel16)));
}
Special thanks to Paul Miller of Profound Effects, who answered that question on the
ae_api mailing list.
Deeeeeep, man. After Effects rotates around the upper left corner of the upper left pixel
when the anchor point (see User Documentation) is (0,0). However, the subpixel sample
and area sample callbacks actually treat (.0, .0) as a direct hit. To compensate for this,
subtract 0.5 from x and y values before calling those functions. The matrix functions
( transform_world ) don't have this problem.
When translating an image by a subpixel amount, make the output layer one pixel wider
than its input, and leave the origin at (0,0).
You don’t necessarily begin effect processing with a clean output slate. Our Gaussian blur
filter, in an effort to do so, performs the following before rendering:
src_rect.left = in_data>output_origin_x;
src_rect.right = src_rect.left + input>width;
src_rect.top = in_data>output_origin_y;
src_rect.bottom = src_rect.top + input>height;
err = PF_FILL(NULL, NULL, output);
if (!err) {
err = PF_COPY(¶ms[0]>u.ld, output, NULL, &src_rect);
}
CACHING BEHAVIOR
Supporting dynamic outflags can greatly improve performance, preventing After Effects
from invalidating your effect's cache as aggressively as it otherwise would.
Confirm that your plug-in performs well with different After Effects cache settings. Does
your plug-in get called to update as often as expected, or does After Effects think it has valid
pixels when you think it doesn’t?
With the new caching in CS6, you may need to clear cached frames after changing your
effect’s rendering, so that frames rendered and stored in the cache prior to the change will not
be reused. To do so manually during development:
1) In Preferences > Media & Disk Cache, disable the Disk Cache
2) Click "Empty Disk Cache" just to be sure (disabling the Disk Cache in step 1 only disables
the *writing* of disk cache, not necessarily the usage)
3) Relaunch
If you ever encounter a glitch, it likely a legitimate bug in your effect, such as improper
rectangle handling in SmartFX.
Stoney Ballard put together the following summary of how time works with effects; you may
find it helpful.
current_time
time_step
local_time_step
total_time
time_scale
The frame being rendered affects current_time. It is expressed in the local (layer) time
system. If the PFR switch is off, current_time may be any non-negative value. If on, it will
be restricted to a multiple of time_step and local_time_step. Layer duration affects only
total_time. Comp duration is a factor only when Time Remapping (TR) is on. In that case,
total_time is the larger of layer duration and composition duration. Composition frame rate
affects only the time_scale. Time Stretch affects only time_step and local_time_step. If
the time stretch is negative, these values are negative. Even if the layer's duration (as seen in
the comp) changes, total_time remains unaffected. This works as if Time Stretch was above
a filter, but below an outer comp. PFR does not alter the effect of Time Stretch. Time
Stretch is different than an outer comp, since it affects both step params equally, while an
outer comp affects only time_step.
Time Remapping happens below the filter, so that it does not affect the time params other
than the total_time. When TR is on, the layer is lengthened to the same as the comp (but
never shortened), regardless of how much time it actually takes, or where in the comp the
The biggest variation comes from being nested in an outer comp, unless PFR is on. When
PFR is on, a filter is completely isolated from time variations in an outer comp. Of course,
current_time will not necessarily move in increments of time_step in that case. It may skip
frames or go backwards.
When PFR is off, local_time_step, total_time, and time_scale remain set to what they
were for the inner comp, but time_step contains the time to the next frame in the outer
comp, expressed in the local time system. This may be any value, including 0. This can be
interpreted as an instantaneous time rate, rather than a duration. A 0 value can last for an
arbitrary number of rendered frames, but the current_time won't change on the local layer.
current_time is quantized to time_step intervals unless rendering an outer comp with PFR
off for the inner comp. This is the current time in the layer, not in any comp.
The value of local_time_step is affected only by Time Stretch. It can never be zero, but it
can be negative.
time_step and local_time_step are always the same value unless rendering an outer comp
with PFR off. time_step is also affected by the time behavior of an outer comp (with PFR
off). It can have any value, positive, negative, or zero, and can be different for every frame (of
the outer comp). time_step can be used to determine the duration of the current frame
(with PFR off).
total_time is the duration of the layer, unless Time Remapping is on, which makes it the
larger of the layer duration and the duration of the comp.
time_scale is the scale such that total_time / time_scale is the layer duration in seconds
in its comp. It is affected only by the comp frame rate, although presumably all the time
values could be scaled proportionately for any reason.
A layer's intrinsic frame rate (if it has one) is not visible anywhere, although it's usually the
same as the comp frame rate. If a filter needs to access the actual frames of a clip, it can do so
only by being in a comp of the same frame rate, and with no Time Stretch or Time
Remapping applied to its layer. It should use local_time_step to determine where the
frames are.
Be careful if one of your parameters is a speed or velocity parameter. Consider the ripple
effect. It assumes a constant and uses the current time to determine how far along the ripple
has gone ( d = v * t). If the user interpolates the speed over time, you should integrate the
velocity function from time zero to the current time. Ripple does not do this, but provides a
“phase” parameter that the user can interpolate as they wish, providing correct results as long
as the speed is set to zero. If you want to provide the correct behavior, you can sample (and
integrate) the speed parameter from the beginning of time until the current time using
PF_CHECKOUT_PARAM(), or you can provide a “phase” or “distance” parameter and warn the
user about interpolating the speed. The cost of checking out many parameter values is
negligible compared to rendering, and is the recommended approach.
If you check out parameter values at other times, or use layer parameters at all, you must
check in those parameters when finished, even if an error has occurred. Remember, checked-
out parameters are read-only.
TESTING
Try using your plug-in in RAM previews to ensure you handle out-of-memory conditions
gracefully. Does your plug-in handle running out of memory gracefully? If you receive
PF_Err_OUT_OF_MEMORY when requesting memory, do you pass it back to After Effects?
4: SmartFX
The SmartFX API provides bidirectional communication between effects and After Effects,
enabling many performance optimizations and providing previously unavailable dependency
information. This extension of the effect API is the way to implement 32-bit per channel
support in After Effects.
Normal effect plug-ins are given a full-sized input buffer, and asked to render a full-sized
output buffer. While output extent_hint specifies the portion of the output buffer that
must actually be filled, this scheme is still very inefficient if the effect does not need its entire
input. Also, many effects don’t use extent hints.
Consider a blur effect applied to a huge layer which is mostly off-screen, or viewed through a
small region of interest, or masked down to a small size. Only a small section of the output
needs to be rendered, indicated to the effect using the output extent_hint. Only a small
section of the input to be blurred is needed as well - the output extent_hint expanded by
the blur radius. However, using the legacy effects API, there is no way for After Effects to
know this, so the entire layer is passed to the plug-in. These extra pixels can be extremely
expensive and wasteful to compute, especially in the case of prior effects or nested comps.
SmartFX solves this problem by reversing the calling sequence. The effect is told how much
of its output is required, and must explicitly ask the host for the inputs it needs. The render
process is split into two parts: pre-render and render.
During pre-render, the effect describes the input pixel data it needs; this necessary input can
vary based on anything you like (non-input layer parameters, non-layer parameters,
information from in_data, settings in sequence data...). The effect must also return the
extent of the resulting output, which may be smaller than the requested size if there are
empty pixels in the requested portion of the layer.
During the render stage, the effect can only retrieve pixels that it has previously requested.
This two-pass approach facilitates many important optimizations. For example, an effect
which multiplies or mattes one input against another might discover that its first input is not
CONTENT BOUNDS
The content bounds of a node are the largest possible result rectangle that can be returned
from a call to PreRender. It absolutely cannot vary depending on current render request or
anything else. It should be calculated carefully, not loosely.
This calculation is very important. It is an intrinsic property of the node (and its inputs) and
is fixed once the graph is built. Violation of it can and probably will cause all sorts of
problems in various pieces of code.
HOW TO SMARTIFY
PF_CMD_SMART_PRE_RENDER
After Effects requests output from the effect. The effect tells After Effects what input it
needs to generate that output, through the use of callback functions, and by manipulating
the structures in the extra parameter. An effect cannot access the pixels of any layer inputs
it has not checked out during PF_Cmd_SMART_PRE_RENDER. So all layer inputs that
an effect might possibly need must be checked out in advance using checkout_layer. If an
effect might need certain layer inputs, they must be checked out now, even if later during
rendering the effect may decide that the layer isn’t needed. Also, since no parameter array is
passed to SmartFX during PF_Cmd_SMART_PRE_RENDER or
func;
void* pre_render_data;
PF_DeletePreRenderDataFunc
} PF_PreRenderOutput;
pre_render_data will be passed back to the effect during
PF_Cmd_SMART_RENDER.
typedef struct {
PF_LRect result_rect;
PF_LRect max_result_rect;
PF_RationalScale par;
long solid;
PF_Boolean reservedB[3];
A_long ref_width;
A_long ref_height;
} PF_CheckoutResult;
result_rect can be empty. max_result_rect is the largest the
output could possibly be, if the host asked for all of it. If solid is TRUE,
the entire result_rect has opaque alpha.
ref_width and ref_height are the original dimensions of the layer,
before any effects are applied, disregarding any downsample factors. This will
be the size of the composition for collapsed layers.
There is a bug in 11.0 with the Global Performance Cache, when a SmartFX
effect uses both
PF_OutFlag2_AUTOMATIC_WIDE_TIME_INPUT &
PF_OutFlag_NON_PARAM_VARY. Calling checkout_layer
during PF_Cmd_SMART_PRE_RENDER returns empty rects in
PF_CheckoutResult. The workaround is to simply make the call
again. This workaround is no longer needed in 11.0.1.
max_result_rect The maximum size the output could possibly be, if After Effects
requested all of it. This must not vary depending on requested output
size.
solid Set this TRUE if every pixel in the output will be fully opaque. Set if
possible; it enables certain optimizations.
reserved Ignore.
pre_render_data Point this at any data that the effect would like to access during
rendering. Effects can also allocate handles and store them in
out_data>frame_data, as with regular (non-smart) effects.
Since PF_Cmd_SMART_PRE_RENDER can be called with no
corresponding PF_Cmd_SMART_RENDER, effects must never
delete this data themselves; once the effect returns from
PF_Cmd_SMART_PRE_RENDER, After Effects owns this data
and will dispose of it (using either the following function or a standard
free call).
delete_pre_render_data_func Point this to a function that will eventually be called to delete the
pre_render_data.
PRESERVE_RGB_OF_ZERO_ALPHA
RECTANGLES
Effects must set both result rectangles accurately. After Effects' caching system relies upon
them, incorrect values can cause many problems. If the plug-in returns a result_rect
Mis-sized output rectangles can cause problems as well. If these rectangles are too big, a loss
of performance results. Not only will many empty pixels be cached (robbing the application
of valuable memory), the effect may be unnecessarily asked to render large regions of
nothing. For this reason, the max_result_rect must be computed correctly, rather than
set to some arbitrarily large size.
Both result_rect and max_result_rect may vary depending on the effect's parameters,
the current time, et cetera; they are valid only for the given invocation of the effect.
However, max_result_rect cannot depend on the specific render request. It must be the
same no matter what portion of the output is requested by After Effects.
As with non-smart effects, each smart effect can arbitrarily shrink or expand its requested
input. They cannot depend on a fixed frame size, and the size of the input may change over
time. For example, the user could apply an animated drop shadow to a layer, which would
add pixels to different edges of the layer at different times, depending on the direction in
which the shadow is cast.
Some effects (for example, those which need to align one layer against another) need some
notion of “size.” This could be defined two ways, each with advantages and disadvantages.
The size of the original layer, before any effects and downsampling are applied, is given
in_data>width/ height. As this value is unaffected by subsequent effects, it can act an
absolute reference for things like center points. However, this is not fool-proof, as the user
could have applied a distortion or translation effect. Also, this value is available only for the
layer to which the effect is applied, not other layer parameters.
...or...
Note that the ref_width/height and max_result_rect for an input may be obtained
without rendering, by calling checkout_layer with an empty request_rect. This is
fairly efficient, and can be useful if the layer “size” is needed first to determine exactly which
pixels are required for rendering. This is an example of requesting a layer in pre-render and
then never calling checkout_layer (in this case, there are none).
PF_CMD_SMART_RENDER
The effect will receive at most one PF_Cmd_SMART_RENDER call for each pre-render.
Note that render may never be called at all. After Effects may have only wanted to to
perform some bounds computations, or it may have subsequently discovered that an effect's
output is not needed at all (which can happen, for example, if the pre-render phase for a
track matte returns a rectangle that does not intersect the effect's output.) All effects must
be able to handle Pre-Render without Render without leaking resources or otherwise
entering an unstable state. During PF_Cmd_SMART_RENDER, the extra parameter points
to a PF_SmartRenderExtra.
Parameters other than layer inputs may be freely checked out at any point. Layer inputs
must be accessed during PF_Cmd_SMART_PRE_RENDER. However, you aren't required to
actually use every input. If you check out a frame (or portion thereof) in
PF_Cmd_SMART_PRE_RENDER and do not subsequently check it out in
PF_Cmd_SMART_RENDER , it need never be rendered, greatly improving performance.
checkout_layer_pixels can only be called once with the checkout_id used earlier in
PreRender. There has to be a one-to-one mapping on the number of checkouts made in
PreRender and SmartRender. If you need to check out the pixels of a layer more than once,
perhaps because of the structure of your code, just use more than one checkout_id. In
PreRender, call checkout_layer on the same layer with different unique checkout_ids.
Then in SmartRender, use a different one of those checkout_ids each time
checkout_layer_pixels is called in SmartRender.
Custom ECW UI allows an effect to provide a parameter with a customized control, which
can be used either with standard parameter types or arbitrary data parameters. Parameters
that have a custom UI should set PF_PUI_CONTROL when adding the parameter.
Custom Comp UI allows an effect to provide direct manipulation of the video in the
Composition or Layer Windows. When the effect is selected, the Window can overlay
custom controls directly on the video, and can handle user interaction with those controls, to
adjust parameters more quickly and naturally. Effects should register themselves to receive
events by calling PF_REGISTER_UI .
After Effects can send events to effects for user interface handling and parameter
management, integrating effects into its central message queue. While many events are sent
in response to user input, After Effects also sends events to effects which manage arbitrary
data parameters. The type of event is specified in PF_EventExtra->e_type and the
various events are described below.
PF_Event_DO_CLICK The user clicked within the effect’s UI. PF_EventUnion contains
a PF_DoClickEventInfo. Handle the mouse click and
respond, passing along drag info; see sample code), within a context.
NOTE: As of 7.0, do not block until mouse-up; instead, rely on
PF_Event_DRAG.
PF_Event_ADJUST_CURSOR The mouse is over the plug-in’s UI. Set the cursor by changing the
PF_CursorType in the PF_AdjustCursorEventInfo. Use
OS-specific calls to implement a custom cursor; tell After Effects
you’ve done so by setting PF_CursorType to
PF_Cursor_CUSTOM. Use an After Effects cursor whenever
possible to preserve interface continuity.
PF_Event_MOUSE_EXITED New in CS6. Notification that the mouse is no longer over a specific
view (layer or comp only).
PF_EVENTEXTRA
This structure provide context information for the current event. After Effects passes a
pointer to this structure in the extra parameter of the entry point function. The
PF_EventUnion (sent in the PF_EventExtra) varies with the event type, and contains
information specific to that event.
evt_in_flags Event Input Flags. This currently contains only one value,
PF_EI_DONT_DRAW, which you should check before drawing!
w_type The window type. If you have Custom Comp and ECW UIs in the
same plug-in, this is the way to differentiate between them (what kind
of masochist are you, anyway?).
PF_Window_COMP,
PF_Window_LAYER,
PF_Window_EFFECT
plugin_state[4] An array of 4 A_longs which the plug-in can use to store state
information for a given context.
current_frame A PF_Rect indicating the full frame of the area occupied by the
control.
horiz_offset A horizontal offset from the left side of the title area in which to draw
into the title.
CLICK
screen_point Where, in screen coordinates, the click occurred. For Custom Comp
UI, these coordinates can be converted to composition coordinates
using the UI Callbacks. See the CCU sample project for an example.
modifiers Which modifier keys (if any) were held down during click.
send_drag Set this flag to TRUE to indicate continued dragging. The next click
event will then effectively be a drag event.
last_time Set when the drag event ends (the user has released the mouse button).
DRAW
After Effects needs your custom UI to refresh. Note: when handling draw requests, use the
image dimensions provided in PF_InData (rather that the dimensions of your input layer,
as you would during PF_Cmd_RENDER).
The user pressed a key, and the effect’s UI is active. Use the macros in AE_EffectUI.h to
access and manipulate the key codes received.
screen_point Screen coordinate of the mouse pointer when the key was pressed. For
Custom Comp UI, these coordinates can be converted to composition
coordinates using the UI Callbacks. See the CCU sample project for an
example.
key_code Either a character code (for printable characters, we use the unshifted
upper case version; A not a, 7 not &), or a control code:
PF_ControlCode_Space
PF_ControlCode_Unknown
PF_ControlCode_Backspace
PF_ControlCode_Tab
PF_ControlCode_Return
PF_ControlCode_Enter
PF_ControlCode_Escape
PF_ControlCode_F1
...
PF_ControlCode_F24
PF_ControlCode_PrintScreen
PF_ControlCode_ScrollLock
PF_ControlCode_Pause
PF_ControlCode_Insert
PF_ControlCode_Delete
PF_ControlCode_Home
PF_ControlCode_End
PF_ControlCode_PageUp
PF_ControlCode_PageDown
PF_ControlCode_Help
PF_ControlCode_Clear
PF_ControlCode_Left
PF_ControlCode_Right
PF_ControlCode_Up
PF_ControlCode_Down
PF_ControlCode_NumLock
PF_ControlCode_Command
PF_ControlCode_Option
PF_ControlCode_Alt = PF_ControlCode_Option
PF_ControlCode_Control
PF_ControlCode_Shift
PF_ControlCode_CapsLock
PF_ControlCode_ContextMenu
PF_Mod_CAPS_LOCK_KEY
PF_Mod_SHIFT_KEY
ADJUSTCURSOR
The cursor has moved onto (but not off of) the effect’s custom UI, to allow the effect to
change the cursor.
modifiers What, if any, modifier keys were held down when the message was sent.
After Effects needs your plug-in to manage it’s arbitrary data parameter(s). Though
arbitrary data types are not required for custom UI support, PF_ArbParamsExtra follows
the EventInfo model.
u {
Custom UI uses a composited drawing model using Drawbot. The Drawbot suites can be
used for:
1. Basic 2D path drawing: Lines, Rect, Arc, Bezier
2. Stroking/Filling/Shading paths
3. Image drawing: Compositing an ARGB/BGRA buffer onto the surface
4. Pushing/popping surface state
5. Text drawing, if supplier supports it (clients should first check if text drawing is
supported before actual drawing)
Drawing may only occur during PF_Event_DRAW (and not during PF_Event_DRAG or
PF_Event_DO_CLICK). To use Drawbot, first get the drawing reference by passing in
PF_Context to a new suite call PF_GetDrawingReference . If a non-NULL drawing
reference is returned, use it to get the supplier and surface references from
DRAWBOT_DrawbotSuite .
REDRAWING
If an effect needs to update more than one window at a time, it should set
PF_OutFlag_REFRESH_UI , which will cause a redraw of the entire ECW, comp, and layer
windows.
To support HiDPI and Retina Displays, you can use offscreen images that are twice the size,
and then use the Transform function to scale the image down in half before drawing it.
PF_EFFECTCUSTOMUISUITE
Enables an effect to get the drawing reference. This is the first call needed to use Drawbot.
Using the Drawbot reference, get the supplier and surface references.
DRAWBOT_SUPPLIERSUITE
Calls to create and release drawing tools, get default settings, and query drawing capabilities.
NewDefaultFont Create a new font with default settings. You can pass the default font
size from GetDefaultFontSize. Release this using
ReleaseObject.
NewDefaultFont(
DRAWBOT_SupplierRef in_supplier_ref,
float in_font_sizeF,
DRAWBOT_FontRef *out_fontP);
NewImageFromBuffer Create a new image from buffer passed to in_dataP. Release this
using ReleaseObject.
NewImageFromBuffer(
DRAWBOT_SupplierRef in_supplier_ref,
int in_width,
int in_height,
int in_row_bytes,
DRAWBOT_PixelLayout in_pl,
const void *in_dataP,
DRAWBOT_ImageRef *out_imageP);
DRAWBOT_PixelLayout can be one of the following:
kDRAWBOT_PixelLayout_24RGB,
kDRAWBOT_PixelLayout_24BGR,
kDRAWBOT_PixelLayout_32RGB, ARGB (A is ignored)
kDRAWBOT_PixelLayout_32BGR, BGRA (A is ignored).
kDRAWBOT_PixelLayout_32ARGB_Straight,
kDRAWBOT_PixelLayout_32ARGB_Premul,
kDRAWBOT_PixelLayout_32BGRA_Straight,
kDRAWBOT_PixelLayout_32BGRA_Premul
SupportsPixelLayoutARGB SupportsPixelLayoutARGB(
DRAWBOT_SupplierRef in_supplier_ref,
DRAWBOT_Boolean *out_supports_argbPB);
PrefersPixelLayoutARGB PrefersPixelLayoutARGB(
DRAWBOT_SupplierRef in_supplier_ref,
DRAWBOT_Boolean *out_prefers_argbPB);
RetainObject Retain (increase reference count on) any object (pen, brush, path,
etc). For example, it should be used when any object is copied and the
copied object should be retained.
RetainObject(
DRAWBOT_ObjectRef in_obj_ref);
ReleaseObject Release (decrease reference count on) any object (pen, brush, path,
etc). This function MUST be called for any object created using
NewXYZ() from this suite. Do not call this function on a
DRAWBOT_SupplierRef and DRAWBOT_SupplierRef, since
these are not created by the plug-in.
ReleaseObject(
DRAWBOT_ObjectRef in_obj_ref);
DRAWBOT_SURFACESUITE
Calls to draw on the surface, and to query and set drawing settings.
PopStateStack Pop the last pushed surface state off the stack.
PopStateStack(
DRAWBOT_SurfaceRef in_surface_ref);
in_alignment_style,
const DRAWBOT_PointF32 *in_originP,
DRAWBOT_TextAlignment
DRAWBOT_TextTruncation in_truncation_style,
float in_truncation_width);
DRAWBOT_TextAlignment is one of the following:
kDRAWBOT_TextAlignment_Left,
kDRAWBOT_TextAlignment_Center,
kDRAWBOT_TextAlignment_Right
DRAWBOT_TextTruncation is one of the following:
kDRAWBOT_TextTruncation_None,
kDRAWBOT_TextTruncation_End,
kDRAWBOT_TextTruncation_EndEllipsis,
kDRAWBOT_TextTruncation_PathEllipsis
SetInterpolationPolicy SetInterpolationPolicy(
DRAWBOT_SurfaceRef in_surface_ref,
DRAWBOT_InterpolationPolicy in_interp);
DRAWBOT_InterpolationPolicy is one of the following:
kDRAWBOT_InterpolationPolicy_None,
kDRAWBOT_InterpolationPolicy_Med,
kDRAWBOT_InterpolationPolicy_High
GetInterpolationPolicy GetInterpolationPolicy(
DRAWBOT_SurfaceRef in_surface_ref,
DRAWBOT_InterpolationPolicy *out_interpP);
GetAntiAliasPolicy GetAntiAliasPolicy(
DRAWBOT_SurfaceRef in_surface_ref,
DRAWBOT_AntiAliasPolicy *out_policyP);
Flush Flush drawing. This is not always needed, and if overused, may cause
excessive redrawing and flashing.
Flush(
DRAWBOT_SurfaceRef in_surface_ref);
DRAWBOT_PATHSUITE
AddArc Add a arc to the path. Zero start degrees == 3 o'clock. Sweep is
clockwise. Units for angle are in degrees.
AddArc(
DRAWBOT_PathRef in_path_ref,
const DRAWBOT_PointF32 *in_centerP,
float in_radius,
float in_start_angle,
float in_sweep);
PF_EFFECTCUSTOMUIOVERLAYTHEMESUITE
This suite should be used for stroking and filling paths and vertices on the Composition and
Layer Windows. After Effects is using this suite internally, and we have made it available to
make custom UI look consistent across effects. The foreground/shadow colors are computed
based on the app brightness level so that custom UI is always visible regardless of the
application’s Brightness setting in the Preferences.
PF_StrokePath Stroke the path with the overlay theme foreground color.
Optionally draw the shadow using the overlay theme shadow
color. Uses overlay theme stroke width for stroking foreground
and shadow strokes.
PF_StrokePath(
const DRAWBOT_DrawRef drawbot_ref,
const DRAWBOT_PathRef path_ref
PF_Boolean draw_shadowB);
PF_FillPath Fills the path with overlay theme foreground color. Optionally
draw the shadow using the overlay theme shadow color.
PF_FillPath(
const DRAWBOT_DrawRef drawbot_ref,
const DRAWBOT_PathRef path_ref
PF_Boolean draw_shadowB);
PF_FillVertex Fills a square vertex around the center point using the overlay
theme foreground color and vertex size.
PF_FillVertex(
const DRAWBOT_DrawRef drawbot_ref,
const A_FloatPoint *center_pointP
PF_Boolean draw_shadowB);
UI CALLBACKS
After Effects provides callbacks for transposing between coordinate systems, and obtaining
OS-specific information about drawing contexts, without guesswork or asking the OS
directly. Use these callbacks! Pointers to these callbacks are provided in
PF_EventCallbacks. Use the macros in AE_EffectUI.h and AE_EffectCB.h to access
these routines.
These macros default the refcon and context handle for simplicity. The refcon assumes you
have a local variable named “ extra”. The default context is the current context. These
default parameters are defined in the PF_EventCallbacks structure (in AE_EffectUI.h).
You can override the defaults by accessing the callbacks through the PF_EventExtra
structure. We don’t recommend (or support) modification of the macros in the header file.
Don’t do it!
PF_Err PF_GET_PLATFORM_DATA (
PF_PlatDataID which,
void *ppData);
PF_PlatDataID can have the following values:
PF_PlatData_MAIN_WND
PF_PlatData_EXE_FILE_PATH_DEPRECATED
PF_PlatData_RES_FILE_PATH_DEPRECATED
PF_PlatData_RES_REFNUM //Mac OS
PF_PlatData_RES_DLLINSTANCE // Win
PF_PlatData_BUNDLE_REF
PF_PlatData_EXE_FILE_PATH_W // new CS6
PF_PlatData_RES_FILE_PATH_W // new CS6
UI PERFORMANCE
On Mac OS, the foreground and background colors are not set to white and black when
custom UI draw events are sent. This is by design; you don’t have to change the background
color when you’re drawing directly into our context.
There is no way to determine the bit depth of the layer(s) being processed during events.
However, you can cache the last-known pixel depth in your sequence data. Better still, you
can have your fixed and float slider parameters rely on the PF_ValueDisplayFlags in their
parameter definitions; if you use this, it will have your parameters’ UI respond to the user’s
preferences for pixel display values. You can also check the depth of your input world during
PF_Cmd_RENDER.
ARBITRARY DATA
An arbitrary data parameter is an excellent way to manage your custom UI. Store state,
preference, and last-item-used information in an arb, and you’ll always be able to recover it.
After Effects manages parameters with a much richer message stream than custom UIs.
A plug-in may want to get a color from a layer within a composition. The user would use the
eyedropper associated with a color parameter, or the plug-in’s custom composition panel UI,
to select the point. During the click event, the plug-in converts the coordinates of the click
into layer space, and stores that information in sequence data. It then forces a re-render,
during which it has access to the color of the layer point corresponding to the stored
coordinates. The plug-in stores the color value in sequence data, and cancels the render,
requesting a redraw of the affected parameter(s). Finally, during the draw, the plug-in adds
appropriate keyframes to its color parameter stream using the KeyframeSuite. Yes, this
means the effect needs to cheat and use the AEGP API.
6: Audio
After Effects can process audio encoded at up to 96Khz, floating point (24-bit) resolution,
mono or stereo. We provide high quality resampling. PF_InData and PF_OutData both
contain information specific to audio handling.
While audio isn’t the focus of After Effects’ feature set, it is an important component of
compositing and pre-visualization workflows. Also, several engineers on our team are audio
fanatics, and ensure that our audio effects (and the whole audio pipeline) are of the highest
quality.
GLOBAL OUTFLAGS
The following data types are used by After Effects to describe audio data.
FLAGS
PHASE
CURVE TOLERANCE
Curve tolerance is used by After Effects to subdivide the audio effects’ time-variant
parameters. Set this to zero for default behavior (or for non-audio FLOAT_SLIDER
parameters).
If your effect requires as input a time span different from the output time span, update the
startsampL and endsampL field in PF_OutData during PF_Cmd_AUDIO_SETUP.
You cannot extend the length of an audio clip through the API. However, it is a relatively
simple matter for the user to extend the length of the clip before applying your effect. Apply
time remapping to the layer and simply extend the out point. If you’re adding a delay effect
to a sounds clip, you’d want to allow it time to fade away instead of truncating the sound at
the original end point. Document the steps users should take when applying your effect.
AUDIO CONSIDERATIONS
The After Effects audio API supports sampling rates up to 96Khz, in as many formats as
possible. In the same way that plug-ins’ pixel manipulation functions should remain
“resolution independent”, audio plug-ins should be sample rate- and bit depth-independent.
Your plug-in can’t know anything about the final output format of the audio in question; it
might get stretched, normalized, truncated, or phase-inverted between the application of
your plug-in and the final output.
Audio filters encounter different issues than do image filters. Investigate the SDK sample
for one possible implementation of audio rendering.
7: AEGPs
The After Effects General Plug-in (AEGP) API is powerful and broad, offering
functionality beyond what is available to effect plug-ins. To users, AEGPs appear to be part
of After Effects. They can add, intercept, and trigger menu commands, access the keyframe
database, and register functions as part of After Effects’ internal messaging. AEGPs can add
and remove items to projects and compositions, add and remove filters and keyframes. Once
its command is triggered, AEGPs use the numerous PICA function suites (described in this
chapter) to work with every After Effects item.
AEGPs can publish function suites for plug-ins, manipulate all project elements, change
interpretations, replace files and determine which external files are used to render a project.
There are several specialized types of AEGP; Keyframers, Artisans, and I/O modules
(AEIOs). They are all still AEGPs, but have access to specialized messaging streams, for
which they register with After Effects.
WHAT’S NEW?
For what’s new in CC releases, see the heading in the Intro chapter.
AEGP Render Suite is now at version 3, adding a new function to get the GUID for a render
receipt.
OVERVIEW
AEGPs use Plug-In Component Architecture (PICA) function suites to access all
functionality. They may also publish their own function suites, for use by effect plug-ins
(since plug-in load order varies, AEGPs can’t depend on suites not provided by After
Effects). AEGPs can also request a suite and, if it’s not present, provide replacement
functionality themselves.
For effect plug-ins, all communication with After Effects occurs through a single entry point
function. This is not the case with AEGPs. While After Effects does call the entry point
function designated in the AEGP’s PiPL (which is still required), all subsequent
communication between After Effects and AEGPs is handled by the hook functions the
AEGP registers. This registration must be performed from within the plug-in’s entry
function, using the AEGP_RegisterSuite.
AEGPs work in the same manner, regardless of specialization. They can be simple, just
adding one menu item to trigger an external application, or complex like Artisans. While any
plug-in can access any function suite, only plug-ins of the appropriate type will have access
to all the required parameters. Only Artisans will have render contexts, and only AEIO
plug-ins will receive input and output specifications; messaging is dependent upon which
hook functions are registered.
Whenever possible, After Effects presents plug-ins with opaque data types, and provides
accessor functions for manipulating them. For example, video frames are represented using
the opaque AEGP_WorldH. While in some cases it might be more efficient to simply modify
the underlying structure, by maintaining the opaqueness of the data types we allow for
changes to our implementation without making you recompile (and redistribute) your plug-
ins.
AEGP_ProjectH The current After Effects project. Projects are a set of elements AEGP Proj Suite
arranged hierarchically in a tree to preserve semantic
relationships. Interior nodes of the tree are folders. As of CS6,
there will only ever be one open project.
AEGP_FootageH An item that can be rendered. Folders and compositions are AEGP Footage
the only items that are not footage. Suite
AEGP_LayerH An element of a composition. Layers are rendered in sequence, AEGP Layer Suite
which allows for occlusions. Solids, text, paint, cameras, lights,
images, and image sequences are all represented as layers.
Layers may be defined over sub-intervals of the composition's
time interval.
AEGP_MaskOutline The specific points which constitute the mask.The points AEGP Mask
ValH in a mask outline are ordered, and the mask need not be Outline Suite
closed.
AEGP_Text Represents the actual text associated with a text layer. AEGP Text
DocumentH Document Suite
AEGP_Text A reference to all the paths that make up the outlines of a AEGP Text Layer
OutlinesH given text layer. Suite
AEGP_MarkerVal The data associated with a given timeline marker. AEGP Marker
Suite
AEGP_LayerRender The settings associated with a layer render request. AEGP Layer
OptionsH Render Options
Suite
AEGP_SoundDataH The audio settings used for a given layer. AEGP Sound Data
Suite
Information about layers, streams, and many other items doesn’t survive long; it’s often
invalidated by user activity. Anything that modifies the quantity (not quality) of items will
invalidate references to those items; adding a keyframe to a stream invalidates references to
that stream, but forcing a layer to be rendered doesn’t invalidate references to it. Do not
cache layer pixels.
Caching references between calls to a specific hook function within your plug-in is not
recommended; acquire information when you need it, and forget (release) it as soon as
possible.
When you ask After Effects to populate and return handles to data structures, it’s important
that you clean up after yourself. For the following data types, you must call the appropriate
disposal routines.
AEGP_FootageH AEGP_DisposeFootage
AEGP_EffectRefH AEGP_DisposeEffect
AEGP_MaskRefH AEGP_DisposeMask
AEGP_RenderReceiptH AEGP_DisposeRenderReceipt
IMPLEMENTATION
Because the functionality available through the AEGP API is so vast, and the integration
with After Effects so complete, a good deal of design work is necessary to ensure that your
plug-in behaves appropriately in all situations.
AEGPs interact with After Effects through PICA function suites. AEGPs are not loaded in
a specific order. Check the version of the AEGP API (from within your AEGP’s entry point
function) to confirm whether a given suite will be available. AEGPs may also use any effect
API suite function which doesn’t require a PF_ProgPtr (obtained by effects from
PF_InData ).
ENTRY POINT
A_Err AEGP_PluginInitFuncPrototype(
struct SPBasicSuite *pica_basicP,
A_long major_versionL,
A_long minor_versionL,
AEGP_PluginID aegp_plugin_id,
AEGP_GlobalRefcon *global_refconP)
The plug-in’s entry point, exported in the PiPL resource, is called just once during launch;
all other calls to the AEGP go to the functions it’s registered. This is very different from the
effect plug-in model, where all communication comes through the same entry point. Because
plug-in load order may vary, it’s never a good idea to acquire suites not provided by After
Effects during your entry point function. Rather, wait until the appropriate hook
function(s).
The AEGP API version numbers can help distinguish between different versions of After
Effects, in case the AEGP needs to behave differently or handle different behavior.
Those other functions are registered as callback hooks. An AEGP that adds menu items
must register an UpdateMenuHook function (with a function signature as described in
AE_GeneralPlug.h) which After Effects can call to determine whether or not to enable
those items. Similarly, plug-ins which process commands register a CommandHook (one for
all commands).
SPECIALIZATION
AEIOs and Artisans must register with After Effects in order to receive the messaging
streams on which they depend. Like everything else in the AEGP API, this is done through a
function suite; in this case, the aptly-named AEGP_RegisterSuite .
No matter how many menu items you add, you register only one CommandHook. When
called, determine which menu item was chosen (based on the command ID), use AEGP
PICA suite functions to determine the current state of the project, and act accordingly. For
example, keyframing plug-ins may want to disable their menu items unless a (keyframe-able)
parameter stream is part of the current selection.
PRIVATE DATA
Unlike effects, AEGPs are never unloaded during an After Effects session. Still, that doesn’t
mean that relying on static and global variables is a good idea.
All hook functions are passed a plugin_refconPV for storage information specific to that
function. Many AEGP Suite functions take the aegp_plugin_id as a parameter; store it in
the global_refconPV you are passed, either in a structure you allocate or just the ID itself.
Use global_refconPV for your globals (like your aegp_plugin_id) and refcon for
hook-function-specific storage.
THREADING
AEGP supports no threading at all. Everything must be done from the main thread, either in
response to a callback, or from the idle hook.
AEGP SUITES
As mentioned earlier, AEGPs do everything through suites. The following suites are used by
all types of AEGPs, and may be called from within any hook function (except for the
RegisterSuite, which must be used from within the AEGP’s entry point). Following is a
description of each function in every suite, and, where appropriate details on using those
functions.
Suite Description
Memory Suite Manage memory resources. Use this suite! Whenever memory-related
errors are encountered, After Effects can report errors for you.
Command Suite Manage your AEGP’s menu items. Used in conjunction with the
Register Suite.
Register Suite Used in conjunction with the Command Suite to add functions to menu
commands. AEIOs and Artisans must use this suite’s functions to indicate to
After Effects that they want to receive the appropriate message streams. You can
replace some After Effects’ commands using this suite.
Suite Description
Project Suite Reads and modifies project data.
Collection Suite Query which items are currently selected, and create your own selection
sets. It’s often a good UI move to select all the items your AEGP has
modified, just to give the user some idea what you’ve done.
Layer Suite Provides information about the layers within a composition, and the
relationship(s) between the source and layer times. Solids, text, paint,
cameras, lights, images, and image sequences can all become layers.
Effect Suite Provides access to the effects applied to a layer. Use Stream suites to
obtain effect keyframe information. Use
AEGP_EffectCallGeneric() to communicate with effects that you
setup ahead of time to respond to your AEGP.
Dynamic Stream Suite Used to access the characteristics of dynamic streams associated with a
layer.
Mask Outline Suite Used in conjunction with Stream Suite, this suite provides detailed
information about the path rendered to make a layer’s mask.
Text Document Suite Used to access the actual text on a text layer.
Text Layer Suite Used to access the paths that make up the outlines of a text layer.
Utility Suite Supplies error message handling, AEGP version checking and access to
After Effects’ undo stack.
Persistent Data Query and manage all persistent data (i.e., the preferences file). AEGPs
Suite can also add their own data to the prefs.
Color Settings Suite Obtain information on After Effects’ current color management settings.
Render Suite Get rendered frames (and audio samples) from within an AEGP.
Suite Description
World Suite Allocate, dispose of, and query AEGP_Worlds. Also provides a way to
convert a PF_EffectWorld into an AEGP_World, for working with
effect plug-ins.
Composite Suite Exposes After Effects’ compositing functionality, including transfer modes,
track matting, and good old fashioned bit copying.
Sound Data Suite Functions for managing and accessing sound data.
Render Queue Suite Add and remove items from the render queue.
Render Queue Item Query and modify items in the render queue.
Suite
Render Options Suite Query and manage all items exposed in a render queue item’s options
dialog.
Output Module Suite Query and modify the output modules attached to items in the render
queue.
PF Interface Suite The functions in this suite, while technically part of the AEGP API, are
for use by effects.
AEGP Iterate Suite Gives AEGPs a way to have a function (which has the required signature)
to be run on any or all available processors.
File Import Manager Registers AEGP file and project importers as part of After Effects’ file
Suite handling.
FAIL GRACEFULLY
If a suite isn’t present, make every attempt to fail gracefully. Show the user a message
indicating the nature of the problem. Attempt to acquire and use an earlier version of the
same suite.
Since AEGPs are so deeply integrated with After Effects, make sure that users know who or
what is encountering a given problem. Identify yourself! Provide support and/or help
information to the user whenever possible.
HANDLING HANDLES
Use the AEGP Memory Suite to manage memory used by the AEGP. Whenever memory
related errors are encountered, After Effects can report errors for you to find early on.
AEGP_MemHandle is a structure that contains more than just the referenced memory. So it
Function Purpose
AEGP_NewMemHandle Create a new memory handle. This memory is guaranteed to be 16-
byte aligned. plugin_id is the ID passed in through the main
entry point, or alternatively what you obtained from
AEGP_RegisterWithAEGP(). Use whatZ to identify the
memory you are asking for. After Effects uses the string to display
any related error messages.
AEGP_NewMemHandle(
AEGP_PluginID *plugin_id,
const A_char *whatZ,
AEGP_MemSize size,
AEGP_MemFlag flags,
AEGP_MemHandle *memPH);
AEGP_LockMemHandle Locks the handle into memory (cannot be moved by OS). Use this
function prior to using memory allocated by
AEGP_NewMemHandle. Can be nested.
AEGP_LockMemHandle(
AEGP_MemHandle memH,
void **ptr_to_ptr);
Function Purpose
AEGP_SetMemReportingOn If After Effects runs into problems with the memory handling, the
error should be reported to the user. Make use of this during
development!
Only memory allocated and then leaked using this suite is reported
using this call, so for example memory allocated using
PF_HandleSuite1 will not be reported.
AEGP_SetMemReportingOn(
A_Boolean turn_OnB);
Command Suites allow you to create and handle any menu events. To add your own menu
commands, you must also use AEGP_RegisterSuite to assign handlers to menu events.
Function Purpose
AEGP_GetUniqueCommand Obtain a unique command identifier. Use the Register Suite
to register a handler for the command.
AEGP_GetUniqueCommand(
AEGP_Command *unique_commandP);
Note: On occasion After Effects will send command 0 (zero),
so don’t use that as part of your command handling logic.
Function Purpose
AEGP_InsertMenuCommand Add a new menu command. Using nameZ = “-” will insert
a separator. menu_ID can be:
AEGP_Menu_NONE
AEGP_Menu_APPLE
AEGP_Menu_FILE
AEGP_Menu_EDIT
AEGP_Menu_COMPOSITION
AEGP_Menu_LAYER
AEGP_Menu_EFFECT
AEGP_Menu_WINDOW
AEGP_Menu_FLOATERS
AEGP_Menu_KF_ASSIST
AEGP_Menu_IMPORT
AEGP_Menu_SAVE_FRAME_AS
AEGP_Menu_PREFS
AEGP_Menu_EXPORT
AEGP_Menu_ANIMATION
AEGP_Menu_PURGE
AEGP_Menu_NEW - Supported in CC and later
Locations can be set to a specific location in the menu or can
be one assigned by After Effects:
AEGP_MENU_INSERT_SORTED
AEGP_MENU_INSERT_AT_BOTTOM
AEGP_MENU_INSERT_AT_TOP
For AEGP_Menu_WINDOW, the BOTTOM and TOP options
haven’t been supported since CS4 and will return an error. We
recommend SORTED.
command,
AEGP_InsertMenuCommand(
AEGP_Command
const A_char *nameZ,
AEGP_MenuID menu_id,
A_long after_itemL);
command,
AEGP_SetCommandName(
AEGP_Command
const A_char *nameZ);
Function Purpose
AEGP_EnableCommand Enable a menu command.
AEGP_EnableCommand(
AEGP_Command command);
AEGP_CheckMarkMenuCommand After Effects will draw a check mark next to the menu
command.
command,
AEGP_CheckMarkMenuCommand(
AEGP_Command
A_Boolean checkB);
AEGP_DoCommand Call the handler for a specified menu command. Every After
Effects menu item has an associated command; if your AEGP
needs to call an After Effects menu item, you can use the
scripting command:
cmd = app.findMenuCommandId(text);
or contact API Engineering for the command number.
Note that we make no guarantees that command IDs will be
consistent from version to version.
AEGP_DoCommand(AEGP_Command command);
Here are a few command numbers that have been supplied to
other developers, and may be of interest:
3061 Open selection, ignoring any modifier keys.
2285 RAM Preview.
2415 Play (spacebar).
2997 Crop composition to region of interest.
2372 Edit > Purge > Image Caches
Function Purpose
AEGP_RegisterCommandHook Register a hook (command handler) function with After Effects. If
you are replacing a function which After Effects also handles,
AEGP_HookPriority determines whether your plug-in gets it
first.
AEGP_HP_BeforeAE
AEGP_HP_AfterAE
For each menu item you add, obtain your own AEGP_Command
using AEGP_GetUniqueCommand() prior registering a single
command_hook_func. Determine which command was sent
within this hook function, and act accordingly.
Currently, AEGP_HookPriority is ignored.
AEGP_RegisterCommandHook(
AEGP_PluginID aegp_plugin_id,
AEGP_HookPriority hook_priority,
AEGP_Command command,
AEGP_CommandHook command_hook_func
void *refconPV);
aegp_plugin_id,
AEGP_RegisterDeathHook(
AEGP_PluginID
AEGP_DeathHook death_hook_func,
void *refconPV);
Function Purpose
AEGP_RegisterArtisan Register your Artisan. See the Artisan chapter for more details.
api_version,
AEGP_RegisterArtisan(
A_Version
A_Version Artisan_version,
*aegp_refconPV,
long aegp_plugin_id,
void
const A_char *match_nameZ,
const A_char *Artisan_nameZ,
PR_ArtisanEntryPoints *entry_funcsP);
AEGP_RegisterIO Register your AEIO plug-in. See the AEIO section for more
details.
AEGP_RegisterIO (
AEGP_PluginID aegp_plugin_id,
AEGP_IORefcon aegp_refconP,
const AEIO_ModuleInfo *io_infoP,
const AEIO_FunctionBlock4 *aeio_fcn_blockP);
AEGP_RegisterIdleHook Register your IdleHook function. After Effects will call the
function sporadically, while the user makes difficult artistic
decisions (or while they’re getting more coffee).
AEGP_RegisterIdleHook(
AEGP_PluginID aegp_plugin_id,
AEGP_IdleHook idle_hook_func,
AEGP_IdleRefcon refconP);
aegp_plugin_id,
A_Version
AEGP_PluginID
*match_nameZ,
void *aegp_refconPV,
const A_char
const A_char *artisan_nameZ,
PR_ArtisanEntryPoints *entry_funcsP);
AEGP_RegisterPreset Call this to register as many strings as you like for name-
LocalizationString replacement when presets are loaded. Any time a Property name is
found, or referred to in an expression, and it starts with an ASCII
tab character ('\t'), followed by one of the English names, it will be
replaced with the localized name. (In English the tab character
will simply be removed).
AEGP_RegisterPresetLocalizationString(
const A_char *english_nameZ,
const A_char *localized_nameZ);
These functions access and modify project data. Support for multiple projects is included to
prepare for future expansion; After Effects currently adheres to the single project model. To
save project-specific data in After Effects’ preferences (and thus, outside the projects
themselves), use the Persistent Data Suite . Use caution: the functions for opening
and creating projects do not save changes to the project currently open when they are called!
Function Purpose
AEGP_NumProjects Currently will never return more than 1. After Effects can have
only one project open at a time.
AEGP_GetNumProjects)
A_long *num_projPL)
proj_indexL,
AEGP_GetProjectProjectByIndex(
A_long
AEGP_ProjectH *projPH);
projH,
AEGP_GetProjectName(
AEGP_ProjectH
A_char *nameZ);
AEGP_GetProjectPath Get the path of the project (empty string the project hasn’t been
saved yet). The path is a handle to a NULL-terminated
A_UTF16Char string, and must be disposed with
AEGP_FreeMemHandle.
projH,
AEGP_GetProjectPath(
AEGP_ProjectH
AEGP_MemHandle *unicode_pathPH)
AEGP_GetProjectRootFolder Get the root of the project, which After Effects also treats as a
folder.
projH,
AEGP_GetProjectRootFolder(
AEGP_ProjectH
AEGP_ItemH *root_folderPH)
AEGP_SaveProjectToPath Saves the entire project to the specified full path. The file path is
a NULL-terminated UTF-16 string with platform separators.
AEGP_SaveProjectToPath(
AEGP_ProjectH projH,
const A_UTF16Char *pathZ);
Function Purpose
AEGP_GetProjectTimeDisplay Retrieves the current time display settings.
AEGP_GetProjectTimeDisplay(
AEGP_ProjectH projH,
AEGP_TimeDisplay3 *time_displayP);
typedef struct {
AEGP_TimeDisplayMode
display_mode;
AEGP_SourceTimecodeDisplayMode
footage_display_mode;
A_Boolean display_dropframeB;
A_Boolean use_feet_framesB;
A_char timebaseC;
A_char frames_per_footC;
AEGP_FramesDisplayMode
frames_display_mode;
} AEGP_TimeDisplay3;
enum {
AEGP_TimeDisplay_TIMECODE = 0,
AEGP_TimeDisplay_FRAMES
};
typedef char AEGP_TimeDisplayMode;
enum {
AEGP_SourceTimecode_ZERO= 0,
AEGP_SourceTimecode_SOURCE_TIMECODE
};
typedef char AEGP_SourceTimecodeDisplayMode;
enum {
AEGP_Frames_ZERO_BASED= 0,
AEGP_Frames_ONE_BASED,
AEGP_Frames_TIMECODE_CONVERSION
};
typedef char AEGP_FramesDisplayMode;
AEGP_ProjectIsDirty Returns TRUE if the project has been modified since it was
opened.
AEGP_ProjectIsDirty(
AEGP_ProjectH projH,
A_Boolean *is_dirtyPB);
Function Purpose
AEGP_SaveProjectAs Saves the project to the specified path. The file path is a NULL-
terminated UTF-16 string with platform separators. NOTE:
This will overwrite an existing file.
AEGP_SaveProjectAs(
AEGP_ProjectH projH,
const A_UTF16Char *pathZ);
AEGP_NewProject Creates a new project. NOTE: Will close the current project
without saving it first!
AEGP_NewProject(
AEGP_ProjectH*new_projectPH);
AEGP_OpenProjectFromPath Opens a project from the supplied path, and returns its
AEGP_ProjectH. The file path is a NULL-terminated UTF-
16 string with platform separators. NOTE: Will close the current
project without saving it first!
AEGP_OpenProjectFromPath(
const A_UTF16Char *pathZ,
AEGP_ProjectH *projectPH);
Member Description
Note: values in unused fields persist when After Effects is using a different display type.
Member Description
A_char timebaseC; 0 - 100. Only used for
AEGP_TimeDisplayType_TIMECODE.
Accesses and modifies items within a project or composition. Anything in the project bin is
an AEGP_Item. Note that cameras have no source, and thus have no AEGP_ItemH. Unless
more specificity is required for the function(s) you’re using, remain as abstract as possible;
AEGP_Comps are passed into and returned from most functions as AEGP_Items.
projectH,
AEGP_GetFirstProjItem(
AEGP_ProjectH
AEGP_ItemH *itemPH);
projectH,
AEGP_GetNextProjItem(
AEGP_ProjectH
AEGP_ItemH itemH,
AEGP_ItemH *next_itemPH);
Function Purpose
AEGP_IsItemSelected Returns true if the Project window is active and the item is
selected.
itemH,
AEGP_IsItemSelected(
AEGP_ItemH
A_Boolean *selectedPB)
Function Purpose
AEGP_SetItemName Specifies the name of the AEGP_ItemH. (name length has
no limit). Undoable.
AEGP_SetItemName(
AEGP_ItemH itemH,
const A_UTF16Char *nameZ);
AEGP_GetItemID Returns the item’s unique ID, which persists across saves
and loads of the project.
AEGP_GetItemID(
AEGP_ItemH itemH,
A_long *item_idPL);
itemH,
AEGP_SetItemParentFolder(
AEGP_ItemH
AEGP_ItemH parent_folderH);
Function Purpose
AEGP_GetItemDuration Get duration of item, in seconds.
AEGP_GetItemDuration(
AEGP_ItemH itemH,
A_Time *durationPT);
AEGP_GetItemCurrentTime Get current time within item. Not updated while rendering.
itemH,
AEGP_GetItemCurrentTime(
AEGP_ItemH
A_long *curr_timePT);
itemH,
AEGP_GetItemDimensions(
*widthPL)
AEGP_ItemH
A_long
A_long *heightPL);
itemH,
AEGP_GetItemPixelAspectRatio(
AEGP_ItemH
A_Ratio *ratioPRt);
itemH,
AEGP_GetItemSolidColor(
AEGP_ItemH
PF_Pixel *PF_Pixel);
Function Purpose
AEGP_SetSolidDimensions Removed in AEGP_ItemSuite4. See
AEGP_SetSolidFootageDimensions.
Sets the dimensions of an existing solid (error if itemH is
not a solid).
AEGP_SetSolidDimensions(
widthS,
AEGP_ItemH itemH,
A_short
A_short heightS);
*nameZ,
AEGP_CreateNewFolder(
projH),
const A_UTF16Char
parentH0),
AEGP_ProjectH
AEGP_ItemH
AEGP_ItemH *new_folderPH);
itemH,
AEGP_SetItemCurrentTime(
AEGP_ItemH
const A_Time *new_timePT);
itemH,
AEGP_GetItemCommentLength(
AEGP_ItemH
A_u_long *buf_sizePLu);
itemH,
AEGP_SetItemComment(
AEGP_ItemH
const char *commentZ);
Function Purpose
AEGP_GetItemLabel Retrieves an item’s label.
AEGP_GetItemLabel(
AEGP_ItemH itemH,
AEGP_LabelID *labelP);
AEGP_GetItemMRUView Gets an item’s most recently used view. The view can be
used with two calls in the AEGP_ColorSettingsSuite, to
perform a color transform on a pixel buffer from working to
view color space.
AEGP_SetItemLabel(
AEGP_ItemH itemH,
AEGP_ItemViewP *mru_viewP);
MANAGING SELECTIONS
This suite manages selection states, mirroring the functionality supplied by vectors in the
C++ Standard Template Library. Many types of items may be simultaneously selected in
After Effects; AEGP_CollectionItems are unions of layer, mask, effect, stream, mask
vertex, and keyframe items. First acquire the current collection, then iterate across its
members to ensure that whatever your AEGP does is applicable to each.
Function Purpose
AEGP_NewCollection Creates and returns a new, empty collection. To obtain the
current composition’s selection as a collection, use
AEGP_GetNewCollection
FromCompSelection.
plugin_id,
AEGP_NewCollection(
AEGP_PluginID
AEGP_Collection2H *collectionPH);
When AEGP_StreamRefHs are inserted into a collection, they are adopted by the collection;
do not free them. AEGP_EffectRefHs, on the other hand, are not adopted, and must be
freed by the calling AEGP.
MANIPULATE COMPOSITIONS
Provide information about the compositions in a project, and create cameras, lights, and
solids.
Function Purpose
AEGP_GetCompFromItem Retrieves the handle to the composition, given an item
handle. Returns NULL if itemH is not an AEGP_CompH.
AEGP_GetCompFromItem(
AEGP_ItemH itemH,
AEGP_CompH *compPH);
compH,
AEGP_SetCompDownsampleFactor(
AEGP_CompH
AEGP_DownsampleFactor *dsfP);
compH,
AEGP_GetCompBGColor(
AEGP_CompH
AEGP_ColorVal *bg_colorP);
Function Purpose
AEGP_GetCompFlags Returns composition flags, or’d together.
AEGP_GetCompFlags(
AEGP_CompH compH,
AEGP_CompFlags *AEGP_CompFlags);
AEGP_CompFlag_SHOW_ALL_SHY
AEGP_CompFlag_ENABLE_MOTION_BLUR
AEGP_CompFlag_ENABLE_TIME_FILTER
AEGP_CompFlag_GRID_TO_FRAME
AEGP_CompFlag_GRID_TO_FIELDS
AEGP_CompFlag_USE_LOCAL_DSF
AEGP_CompFlag_DRAFT_3D
AEGP_CompFlag_SHOW_GRAPH
AEGP_GetShowLayerNameOr New in CC. Passes back true if the Comp’s timeline shows
-SourceName layer names, false if source names. This will open the comp
as a side effect.
AEGP_GetShowLayerNameOrSourceName(
AEGP_CompH compH,
A_Boolean *layer_names_shownPB);
AEGP_SetShowLayerNameOr New in CC. Pass in true to have the Comp’s timeline show
-SourceName layer names, false for source names. This will open the comp
as a side effect.
AEGP_SetShowLayerNameOrSourceName(
AEGP_CompH compH,
A_Boolean *layer_names_shownPB);
AEGP_GetShowBlendModes New in CC. Passes back true if the Comp’s timeline shows
blend modes column, false if hidden. This will open the
comp as a side effect.
AEGP_GetShowBlendModes(
AEGP_CompH compH,
A_Boolean *blend_modes_shownPB);
AEGP_SetShowBlendModes New in CC. Pass in true to have the Comp’s timeline show
the blend modes column, false to hide it. This will open the
comp as a side effect.
AEGP_GetCompFlags(
AEGP_CompH compH,
A_Boolean show_blend_modesB);
compH,
AEGP_GetCompFramerate(
AEGP_CompH
A_FpLong *fpsPF);
Function Purpose
AEGP_SetCompFramerate Sets the composition’s frames per second.
compH,
AEGP_SetCompFramerate(
AEGP_CompH
A_FpLong *fpsPF);
compH,
AEGP_GetCompShutterAnglePhase(
*angle,
AEGP_CompH
A_Ratio
A_Ratio *phase);
compH,
AEGP_GetCompShutterFrameRange(
AEGP_CompH
const A_Time *comp_timeP);
AEGP_GetCompMotionBlur- New in CC. Retrieves the motion blur adaptive sample limit
AdaptiveSampleLimit for the given composition. As of CC, a new comp defaults to
128.
AEGP_GetCompMotionBlurAdaptiveSampleLimit (
AEGP_CompH compH,
A_long *samplesPL)
AEGP_SetCompMotionBlur- New in CC. Specifies the motion blur adaptive sample limit
AdaptiveSampleLimit for the given composition. As of CC, both the limit and the
suggested values are clamped to [2,256] range and the limit
value will not be allowed less than the suggested value.
Undoable.
AEGP_SetCompMotionBlurAdaptiveSampleLimit (
AEGP_CompH compH,
A_long samplesL);
Function Purpose
AEGP_GetCompWorkAreaStart Get the time where the current work area starts.
AEGP_GetCompWorkAreaStart(
AEGP_CompH compH,
A_Time *startPT);
compH,
AEGP_GetCompWorkAreaDuration(
AEGP_CompH
A_Time *durationPT);
AEGP_SetCompWorkArea Set the work area start and duration, in seconds. Undo-able.
StartAndDuration One call to this function is sufficient to set the layer’s in
point and duration; it’s not necessary to call it twice, once for
each timespace.
AEGP_SetCompWorkAreaStartAndDuration)
AEGP_CompH compH,
const A_Time *startPT)
const A_Time *durationPT);
AEGP_CreateSolidInComp Creates a new solid with a specified width, height, color, and
duration in the composition. Undo-able.
If you pass NULL for the duration, After Effects uses its
preference for the duration of a new still. If you pass NULL,
or an invalid time scale, duration is set to the length of the
composition.
A_Long widthL,
A_Long heightL,
const PF_Pixel *color,
AEGP_CompH parent_compH,
const A_Time *durationPT0,
AEGP_LayerH *new_solidPH);
Function Purpose
AEGP_CreateLightInComp Creates and adds a light to the specified composition. Once
created, you can manipulate the light’s parameter streams
using the AEGP_StreamSuite.
AEGP_CreateLightInComp(
const A_UTF16Char *utf_nameZ,
A_FloatPoint center_point,
AEGP_CompH parent_compH,
AEGP_LayerH *new_lightPH);
AEGP_CreateComp Creates a new composition for the project. If you don’t provide a
parent folder, the composition will be at the root level of the
project. Undo-able.
parent_folderHO,
AEGP_CreateComp(
const A_UTF16Char
AEGP_ItemH
*utf_nameZ,
A_Long widthL,
A_Long heightL,
const A_Ratio
*pixel_aspect_ratioPRt,
const A_Time *durationPT,
const A_Ratio
*frameratePRt,
AEGP_CompH *new_compPH);
AEGP_SetSelection Sets the selection within the given composition to the given
AEGP_Collection2H. Will return an error if members
of the AEGP_Collection2H are not available. Don’t
assume that a composition hasn’t changed between
operations; always use a fresh AEGP_Collection2H.
AEGP_SetSelection(
AEGP_CompH compH,
AEGP_Collection2H collectionH);
Function Purpose
AEGP_GetCompDisplayStartTime Gets the displayed start time of a composition.
AEGP_GetCompDisplayStartTime(
AEGP_CompH compH,
const A_Time *start_timePT);
compH,
AEGP_SetCompDuration(
AEGP_CompH
const A_Time *durationPT);
Function Purpose
AEGP_CreateBoxTextLayerInComp Updated in CS6. Creates a new box text layer, and returns its
AEGP_LayerH.
AEGP_CreateBoxTextLayerInComp)(
AEGP_CompH parent_compH,
A_Boolean select_new_layerB,
A_FloatPoint box_dimensions,
AEGP_LayerH *new_text_layerPH);
Function Purpose
AEGP_SetCompDisplayDropFrame Sets the dropness of the timecode in the specified
composition.
AEGP_SetCompDisplayDropFrame(
AEGP_CompH compH,
A_Boolean dropFrameB);
Provides information about footage, or items in a project or composition. When getting and
setting footage’s interpretation, it is possible to specify incompatible options. If you
encounter warnings and errors during development, be sure to make all related changes
atomically, and reassess the logic of the operation you’re performing. For example, changing
the pull-down interpretation of footage won’t work unless there’s a difference between it’s
native and conformed frame rate.Depending on what you’re trying to accomplish, it may
make sense to abort all of your operations at that point, inform the user of the problem
encountered.
Function Purpose
AEGP_GetMainFootageFromItem Returns an error if item isn’t a footage item Used to
convert an item handle to a footage handle.
itemH,
AEGP_GetMainFootageFromItem(
AEGP_ItemH
AEGP_FootageH *footagePH);
itemH,
AEGP_GetProxyFootageFromItem(
AEGP_ItemH
AEGP_FootageH *proxy_ftgPH);
AEGP_FootageH footageH,
AEGP_GetFootageNumFiles(
A_long *num_filesPL0,
A_long *files_per_frmPL0);
Function Purpose
AEGP_GetFootagePath Get fully realized path to footage source file. Retrieves
the footage path for a piece of footage (or for the
specified frame of a footage sequence). frame_numL
ranges from 0 to num_main_files, as obtained using
AEGP_GetFootageNumFiles.
AEGP_FOOTAGE_MAIN_FILE_INDEX is the main
file. The path is a handle to a NULL-terminated
A_UTF16Char string, and must be disposed with
AEGP_FreeMemHandle.
footageH,
AEGP_GetFootagePath(
AEGP_FootageH
A_long frame_numL,
A_long file_indexL,
AEGP_MemHandle *unicode_pathPH);
footageH,
AEGP_GetFootageSignature(
AEGP_FootageH
AEGP_FootageSignature *sigP);
The signature will be one of the following:
AEGP_FootageSignature_NONE
AEGP_FootageSignature_MISSING
AEGP_FootageSignature_SOLID
Function Purpose
AEGP_NewFootage Creates a new footage item. The file path is a NULL-
terminated UTF-16 string with platform separators.
Note that footage filenames with colons are not allowed,
since colons are used as path separators in the HFS+ file
system.
AEGP_NewFootage(
AEGP_PluginID aegp_plugin_id,
const A_UTF16Char
*pathZ,
const AEGP_FootageLayerKey
*layer_infoP0,
const AEGP_FileSequenceImportOptions
*sequence_optionsP0,
AEGP_InterpretationStyle
interp_style,
void *reserved,
AEGP_FootageH *footagePH);
Note the optional params. If
allow_interpretation_dialogB is FALSE,
After Effects will guess the alpha interpretation.
typedef struct {
A_long layer_idL;
A_long layer_indexL
char *nameAC;
AEGP_LayerDrawStyle draw_style;
} AEGP_FootageLayerKey;
AEGP_LayerDrawStyle can be:
AEGP_LayerDrawStyle_LAYER_BOUNDS
AEGP_LayerDrawStyle_DOCUMENT_BOUNDS
AEGP_InterpretationStyle can be:
AEGP_InterpretationStyle_NO_DIALOG_GUESS
Will guess alpha interpretation even if file contains unknown
alpha interpretation and user pref says to ask user.
AEGP_InterpretationStyle_DIALOG_OK
Optionally can show a dialog.
AEGP_InterpretationStyle_NO_DIALOG_NO_GUESS
Used for replace footage implementation.
Function Purpose
AEGP_AddFootageToProject Adds a footage item to a project. Footage will be adopted
by the project, and may be added only once. This is
Undo-able; do not dispose of the returned added item if
it’s undone.
footageH,
AEGP_AddFootageToProject(
AEGP_FootageH
AEGP_ItemH folderH,
AEGP_ItemH *add_itemPH0);
footageH,
AEGP_SetItemProxyFootage(
AEGP_FootageH
AEGP_ItemH itemH);
AEGP_ReplaceItemMainFootage Replaces footage for an item. The item will replace the
main footage for this item. This is Undo-able; do not
dispose of the returned added item if it’s undone.
footageH,
AEGP_ReplaceItemMainFootage(
AEGP_FootageH
AEGP_ItemH itemH);
proxyB,
const AEGP_ItemH itemH,
A_Boolean
AEGP_FootageInterp *interpP);
If proxyB is TRUE, the proxy footage’s settings are
retrieved.
Function Purpose
AEGP_SetFootageInterpretation Apply the settings in the AEGP_FootageInterp to
the AEGP_FootageH. Undo-able.
AEGP_SetFootageInterpretation(
proxyB,
const AEGP_ItemH itemH,
A_Boolean
const AEGP_FootageInterp
*interpP);
If proxyB is TRUE, the proxy footage’s settings are
modified.
plugin_id,
AEGP_NewPlaceholderFootage(
*nameZ,
AEGP_PluginID
width,
const A_char
height,
A_long
A_long
const A_Time *durationPT,
AEGP_FootageH *footagePH);
Function Purpose
AEGP_NewPlaceholderFootage This is the hip new way to add references to footage that
WithPath can’t be found right this moment. The file path is a
NULL-terminated UTF-16 string with platform
separators.
In CS6 and earlier, file_type was ignored and we
previously recommendedsetting it to
AEIO_FileType_NONE. Starting in CC,
AEIO_FileType_NONE is now a warning condition.
If you pass AEIO_FileType_ANY, then path MUST
exist. If the path may not exist, pass
AEIO_FileType_DIR for folder, or
AEIO_FileType_GENERIC for a file.
plugin_id,
AEGP_NewPlaceholderFootageWithPath(
path_platform,
file_type,
AEGP_Platform
widthL,
AEIO_FileType
heightL,
A_long
*durationPT,
A_long
const A_Time
AEGP_FootageH *footagePH);
AEGP_NewSolidFootage This is the way to add a solid. Until the footage is added
to the project, the caller owns the AEGP_FootageH
(and must dispose of it if, and only if, it isn’t added to the
project).
AEGP_NewSolidFootage(
width,
const A_char *nameZ,
height,
A_long
*colorP,
A_long
const AEGP_ColorVal
AEGP_FootageH *footagePH);
itemH,
AEGP_GetSolidFootageColor(
proxyB,
AEGP_ItemH
A_Boolean
AEGP_ColorVal *colorP);
If proxyB is TRUE, the proxy solid’s color is retrieved.
Function Purpose
AEGP_SetSolidFootageColor Sets the color of a solid. Undo-able.
AEGP_SetSolidFootageColor(
itemH,
proxyB,
AEGP_ItemH
A_Boolean
AEGP_ColorVal *colorP);
If proxyB is TRUE, the proxy solid’s color is set.
itemH,
AEGP_SetSolidFootageDimensions(
proxyB,
AEGP_ItemH
widthL,
A_Boolean
A_long
A_long heightL);
If proxyB is TRUE, the proxy solid’s dimensions are
modified. Returns an error if the item isn’t a solid.
footageH,
AEGP_GetFootageSoundDataFormat(
AEGP_FootageH
AEGP_SoundDataFormat *formatP);
AEGP_FileSequenceImportOptions
AEGP_FootageH footageH,
*optionsP);
Member Purpose
AEGP_InterlaceLabel il; The interlace settings for the footage item.
A_u_long signature; // ‘FIEL’
A_short version;
FIEL_Type type;
FIEL_Order order;
A_u_long reserved;
FIEL_Type is one of the following:
FIEL_Type_FRAME_RENDERED
FIEL_Type_INTERLACED
FIEL_Type_HALF_HEIGHT
FIEL_Type_FIELD_DOUBLED
FIEL_Type_FIELD_DOUBLED means 60 full-sized field
doubled frames per second.
FIEL_Order is either FIEL_Order_UPPER_FIRST or
FIEL_Order_LOWER_FIRST.
redCu;
AEGP_AlphaLabel al; AEGP_AlphaFlag flags;
A_u_char
A_u_char greenCu;
A_u_char blueCu;
AEGP_PulldownPhase pd; Indicates the phase for use in 3:2 pulldown. One of the
following:
AEGP_PulldownPhase_NO_PULLDOWN,
AEGP_PulldownPhase_WSSWW,
AEGP_PulldownPhase_SSWWW,
AEGP_PulldownPhase_SWWWS,
AEGP_PulldownPhase_WWWSS,
AEGP_PulldownPhase_WWSSW,
AEGP_PulldownPhase_WWWSW,
AEGP_PulldownPhase_WWSWW,
AEGP_PulldownPhase_WSWWW,
AEGP_PulldownPhase_SWWWW,
AEGP_PulldownPhase_WWWWS
Member Purpose
AEGP_LoopBehavior loop; Indicates the number of times the footage should loop.
A_long loops;
A_long reserved;
A_Ratio pix_aspect_ratio; Expresses the pixel aspect ratio of the footage (x over y).
A_FpLong native_fpsF; The original framerate (in frames per second) of the
footage item.
A_FpLong conform_fpsF; The framerate being used for the footage item.
A_long depthL; The pixel depth of the footage. One of the following:
AEGP_Footage_Depth_2
AEGP_Footage_Depth_1
AEGP_Footage_Depth_4
AEGP_Footage_Depth_16
AEGP_Footage_Depth_8
AEGP_Footage_Depth_24
AEGP_Footage_Depth_30
AEGP_Footage_Depth_32
AEGP_Footage_Depth_GRAY_2
AEGP_Footage_Depth_GRAY_4
AEGP_Footage_Depth_48
AEGP_Footage_Depth_GRAY_8
AEGP_Footage_Depth_64
AEGP_Footage_Depth_GRAY_16
MANAGE LAYERS
compH,
AEGP_GetCompNumLayers(
AEGP_CompH
A_long *num_layersPL);
Function Purpose
AEGP_GetCompLayerByIndex Get a AEGP_LayerH from a composition. Zero is the
foremost layer.
AEGP_GetCompLayerByIndex(
AEGP_CompH compH,
A_long layer_indexL,
AEGP_LayerH *layerPH);
AEGP_GetLayerIndex Get the index of the layer (0 is the topmost layer in the
composition).
AEGP_GetLayerIndex(
AEGP_LayerH layerH,
A_long *layer_indexPL);
layerH,
AEGP_GetLayerSourceItemID(
AEGP_LayerH
A_long *source_idPL);
Function Purpose
AEGP_GetLayerName Get the name of a layer. Both utf_layer_namePH0 and
utf_source_namePH0 point to null terminated UTF-
16 strings. They must be disposed with
AEGP_FreeMemHandle.
AEGP_GetLayerName(
AEGP_PluginID pluginID,
AEGP_LayerH layerH,
AEGP_MemHandle *utf_layer_namePH0,
AEGP_MemHandle *utf_source_namePH0);
AEGP_SetLayerQuality Sets the quality of a layer (see flag values above). Undoable.
AEGP_SetLayerQuality(
AEGP_LayerH layerH,
AEGP_LayerQuality quality);
Function Purpose
AEGP_GetLayerFlags Get flags for a layer.
layerH,
AEGP_GetLayerFlags(
AEGP_LayerH
AEGP_LayerFlags *layer_flagsP);
AEGP_LayerFlag_NONE
AEGP_LayerFlag_VIDEO_ACTIVE
AEGP_LayerFlag_AUDIO_ACTIVE
AEGP_LayerFlag_EFFECTS_ACTIVE
AEGP_LayerFlag_MOTION_BLUR
AEGP_LayerFlag_FRAME_BLENDING
AEGP_LayerFlag_LOCKED
AEGP_LayerFlag_SHY
AEGP_LayerFlag_COLLAPSE
AEGP_LayerFlag_AUTO_ORIENT_ROTATION
AEGP_LayerFlag_ADJUSTMENT_LAYER
AEGP_LayerFlag_TIME_REMAPPING
AEGP_LayerFlag_LAYER_IS_3D
AEGP_LayerFlag_LOOK_AT_CAMERA
AEGP_LayerFlag_LOOK_AT_POI
AEGP_LayerFlag_SOLO
AEGP_LayerFlag_MARKERS_LOCKED,
AEGP_LayerFlag_NULL_LAYER,
AEGP_LayerFlag_HIDE_LOCKED_MASKS,
AEGP_LayerFlag_GUIDE_LAYER,
AEGP_LayerFlag_ENVIRONMENT_LAYER,
AEGP_LayerFlag_ADVANCED_FRAME_BLENDING,
True only if pixel motion frame blending is on for the layer.
AEGP_LayerFlag_SUBLAYERS_RENDER_SEPARATELY,
Used to get/set the state of per-character 3D enablement on
a text layer.
AEGP_LayerFlag_ENVIRONMENT_LAYER
New in CS6.
layerH,
AEGP_SetLayerFlag(
AEGP_LayerH
AEGP_LayerFlags single_flag,
A_Boolean valueB);
Function Purpose
AEGP_IsLayerAudioReallyOn Accounts for solo status of other layers in the composition.
AEGP_IsLayerAudioReallyOn(
AEGP_LayerH layerH,
A_Boolean *onPB);
layerH,
AEGP_SetLayerInPointAndDuration(
AEGP_LayerH
AEGP_LTimeMode time_mode,
const A_Time *in_pointPT,
const A_Time *durationPT);
AEGP_GetLayerOffset Get the offset from the start of the composition to layer time 0, in
composition time.
AEGP_GetLayerOffset(
AEGP_LayerH layerH,
A_Time *offsetPT);
Function Purpose
AEGP_SetLayerOffset Set the offset from the start of the composition to the first
frame of the layer, in composition time. Undoable.
AEGP_SetLayerOffset(
AEGP_LayerH layerH,
A_Time *offsetPT);
Function Purpose
AEGP_AddLayer Add an item to the composition, above all other layers.
Undo-able. Use AEGP_IsAddLayerValid() first, to
confirm that it’s possible.
AEGP_AddLayer(
AEGP_ItemH item_to_addH,
AEGP_CompH into_compH,
A_Boolean *added_layerPH0);
AEGP_GetLayerMaskedBounds Given a layer’s handle and a time, returns the bounds of area
visible with masks applied.
AEGP_GetLayerMaskedBounds(
AEGP_LayerH layerH,
const A_Time *comp_timePT,
A_FloatRect *boundsPR);
Function Purpose
AEGP_IsVideoActive Given composition time and a layer, see if the layer will
render. Time mode is either
AEGP_LTimeMode_LayerTime or
AEGP_LTimeMode_CompTime.
AEGP_IsVideoActive(
AEGP_LayerH layerH,
AEGP_LTimeMode time_mode,
A_Time *comp_timePT,
A_Boolean *is_activePB);
layerH,
AEGP_GetLayerDancingRandValue(
AEGP_LayerH
const A_Time *comp_timePT,
A_long *rand_valuePL);
AEGP_GetLayerID Supplies the layer’s unique ID. This ID never changes during
the lifetime of the project.
AEGP_GetLayerID(
AEGP_LayerH layerH,
AEGP_LayerIDVal *id_valP);
Function Purpose
AEGP_GetLayerToWorldXform Given a layer handle and time, returns the layer-to-world
transformation matrix.
AEGP_GetLayerToWorldXform(
AEGP_LayerH aegp_layerH,
const A_Time *comp_timeP,
A_Matrix4 *transform);
Function Purpose
AEGP_GetLayerFromLayerID Retrieves the AEGP_LayerH associated with a given
AEGP_LayerIDVal (which is what you get when
accessing an effect’s layer parameter stream).
AEGP_GetLayerFromLayerID(
AEGP_CompH parent_compH,
AEGP_LayerIDVal id,
AEGP_LayerH *layerPH);
AEGP_SetLayerSamplingQuality New in CC. Sets the sampling quality of a layer (see flag
values above). Option is explicitly set on the layer
independent of layer quality. If you want to force it on you
must also set the layer quality to AEGP_LayerQual_BEST
with AEGP_SetLayerQuality. Otherwise it will only
be using the specified layer sampling quality whenever the
layer quality is set to AEGP_LayerQual_BEST.
Undoable.
AEGP_SetLayerSamplingQuality(
AEGP_LayerH layerH,
AEGP_LayerSamplingQuality label);
All layers created using AEGP calls will start at composition time 0, and have the duration
of the composition. Use AEGP_SetLayerOffset () and
AEGP_SetLayerInPointAndDuration () to properly set the layer’s time information.
When the layer stretch factor (obtained using AEGP_GetLayerStretch , naturally) is not
100%, the following computation will be needed to yield the correct layer offset:
Access the effects applied to a layer. This suite provides access to all parameter data streams.
Use the AEGP_StreamSuite to work with those streams.
Function Purpose
AEGP_GetLayerNumEffects Get number of effects applied to a layer.
AEGP_GetLayerNumEffects(
AEGP_LayerH layerH,
A_long *num_effectsPL);
Function Purpose
AEGP_GetEffectParamUnionByInde Returns description of effect parameter. Do not use the
x value(s) in the ParamDef returned by this function (Use
AEGP_GetNewStreamValue() instead); it’s provided
so AEGPs can access parameter defaults, checkbox names,
and pop-up strings.
Use AEGP_GetEffectNumParamStreams() from
the StreamSuite to get the stream count, useful for
determining the maximum param_index. The last
parameter is optional;
AEGP_GetEffectParamUnionByIndex(
AEGP_PluginID aegp_plugin_id,
AEGP_EffectRefH effectH,
PF_ParamIndex param_index,
PF_ParamType *param_typeP
PF_ParamDefUnion *uP0);
Function Purpose
AEGP_EffectCallGeneric Call an effect plug-in, and pass it a pointer to any data you
like; the effect can modify it. This is how AEGPs
communicate with effects. Pass
PF_Cmd_COMPLETELY_GENERAL for effect_cmd.
AEGP_EffectCallGeneric(
AEGP_PluginID aegp_plugin_id,
AEGP_EffectRefH effectH,
const A_Time *timePT,
PF_Cmd effect_cmd,
void *extraPV);
AEGP_InstalledEffectKey
AEGP_LayerH layerH,
installed_key,
AEGP_EffectRefH *effect_refPH);
Function Purpose
AEGP_GetEffectName Get name of the effect. nameZ can be up to
AEGP_MAX_EFFECT_NAME_SIZE + 1 long.
AEGP_GetEffectName(
AEGP_InstalledEffectKey
installed_key,
A_char *nameZ);
Note: use AEGP_SetStreamName to change the
display name of an effect.
Function Purpose
AEGP_GetEffectMaskID New in CC 2014. For a given mask_indexL, returns the
corresponding AEGP_MaskIDVal for use in uniquely
identifying the mask.
AEGP_GetEffectMaskID(
AEGP_EffectRefH effect_refH,
A_u_long mask_indexL,
AEGP_MaskIDVal *id_valP);
Even if you manipulate a layer’s effects, its effect controls won’t necessarily become visible.
However, if you apply then immediately remove an effect, the layer’s effect controls will be
made visible. Tricky, eh?
How do you get an AEGP_StreamRef for an effect? Start by getting the effect’s
AEGP_EffectRef, by calling AEGP_GetNewEffectForEffect(). Then call
To get an effect’s instance name (as renamed by the user), get the AEGP_StreamRef for the
effect itself and call AEGP_GetStreamName .
Just about everything in After Effects is a stream. Effect parameters, layers, masks, and
shapes are all internally represented by streams. The AEGP API can access nearly every
aspect of every stream.
The After Effects timeline can contain numerous object types; each object supports a set of
parameters called streams. All streams, regardless of which type of object to which they’re
attached, are conceptually similar (and handled similarly by After Effects. But the way you
access each type of stream varies because of their containment.
A stream, once acquired, represents a value which may change over time. Not all streams can
vary over time, and a particular stream may not be time-variant at the time of access.
There are two ways to access the value of a stream. If the stream has keyframes, you can use
the keyframe suite. The values provided won’t reflect the influence of expressions. Note: In
any expression, the current keyframed value is always available as the variable value.
You can also use AEGP_GetNewStreamValue , which samples the value of the stream at a
particular time. For streams without expressions or keyframes, the time parameter is
meaningless, and the function returns what essentially is the constant value of the stream.
Use AEGP_SetStreamValue (which doesn't take a time as a parameter) to set these
streams.
Many StreamSuite functions populate a StreamH, which your AEGP must dispose. when
done. After Effects allocates and passes you a copy of the values, not a direct handle to the
original value. AEGP_GetNewLayerStream() is restricted to streams for which no
memory allocation is required to access their values.
A stream value is a large union, only one structure of which (depending on the stream type)
is populated. Note the similarity to the PF_ParamDef .
typedef union {
AEGP_FourDVal four_d;
AEGP_ThreeDVal three_d;
AEGP_TwoDVal two_d;
AEGP_OneDVal one_d;
AEGP_ColorVal color;
AEGP_ArbBlockVal arbH;
AEGP_MarkerValP markerP;
AEGP_LayerIDVal layer_id;
AEGP_MaskIDVal mask_id;
AEGP_MaskOutlineValH mask;
AEGP_TextDocumentH text_documentH;
} AEGP_StreamVal2;
LAYERS
MASKS
Since a layer can have multiple masks, access the masks using
AEGP_GetLayerMaskByIndex . Masks don’t have streams like layers do; they get their
own enumeration. Access their streams using AEGP_GetNewMaskStream .
EFFECTS
They can have a variable number of streams/parameters, and the order and definition of
them is not known when the AEGP is written. Therefore we cannot offer an enum for
selecting them, and instead you must get them by index, hence GetNewEffectStream-
ByIndex .
Access and manipulate the values of a layer’s streams. For paint and text streams, use
AEGP_DynamicStreamSuite instead.
Function Purpose
AEGP_IsStreamLegal Determines if the given stream is appropriate for the given
layer.
AEGP_IsStreamLegal(
AEGP_LayerH layerH,
AEGP_LayerStream which_stream,
A_Boolean* is_legalP);
Function Purpose
AEGP_GetNewLayerStream Get a layer’s data stream. Plug-in must dispose of
streamPH. Note that this will not provide keyframe
access; Use the AEGP_KeyframeSuite instead.
AEGP_GetNewLayerStream(
AEGP_PluginID id,
AEGP_LayerH layerH,
AEGP_LayerStream which_stream,
AEGP_StreamRefH *streamPH);
AEGP_LayerStream_ANCHORPOINT
AEGP_LayerStream_POSITION
AEGP_LayerStream_SCALE
AEGP_LayerStream_ROTATION
AEGP_LayerStream_ROTATE_Z
AEGP_LayerStream_OPACITY
AEGP_LayerStream_AUDIO
AEGP_LayerStream_MARKER
AEGP_LayerStream_TIME_REMAP
AEGP_LayerStream_ROTATE_X,
AEGP_LayerStream_ROTATE_Y,
AEGP_LayerStream_ORIENTATION,
Only valid for AEGP_ObjectType_CAMERA:
AEGP_ObjectType_CAMERA
AEGP_LayerStream_ZOOM,
AEGP_LayerStream_DEPTH_OF_FIELD,
AEGP_LayerStream_FOCUS_DISTANCE,
AEGP_LayerStream_APERTURE,
AEGP_LayerStream_BLUR_LEVEL,
AEGP_LayerStream_IRIS_SHAPE,
AEGP_LayerStream_IRIS_ROTATION,
AEGP_LayerStream_IRIS_ROUNDNESS,
AEGP_LayerStream_IRIS_ASPECT_RATIO,
AEGP_LayerStream_IRIS_DIFFRACTION_FRINGE,
AEGP_LayerStream_IRIS_HIGHLIGHT_GAIN,
AEGP_LayerStream_IRIS_HIGHLIGHT_THRESHOLD,
AEGP_LayerStream_IRIS_HIGHLIGHT_SATURATION,
Only valid for AEGP_ObjectType_LIGHT:
AEGP_LayerStream_INTENSITY,
AEGP_LayerStream_COLOR,
AEGP_LayerStream_CONE_ANGLE,
AEGP_LayerStream_CONE_FEATHER,
AEGP_LayerStream_SHADOW_DARKNESS,
AEGP_LayerStream_SHADOW_DIFFUSION,
AEGP_LayerStream_LIGHT_FALLOFF_TYPE,
AEGP_LayerStream_LIGHT_FALLOFF_START,
AEGP_LayerStream_LIGHT_FALLOFF_DISTANCE,
Function Purpose
AEGP_GetNewLayerStream Only valid for AEGP_ObjectType_AV:
(continued) AEGP_LayerStream_ACCEPTS_SHADOWS,
AEGP_LayerStream_ACCEPTS_LIGHTS,
AEGP_LayerStream_AMBIENT_COEFF,
AEGP_LayerStream_DIFFUSE_COEFF,
AEGP_LayerStream_SPECULAR_INTENSITY,
AEGP_LayerStream_SPECULAR_SHININESS,
AEGP_LayerStream_METAL,
AEGP_LayerStream_LIGHT_TRANSMISSION,
Only valid for AEGP_ObjectType_AV, new in CS6:
AEGP_LayerStream_REFLECTION_INTENSITY,
AEGP_LayerStream_REFLECTION_SHARPNESS,
AEGP_LayerStream_REFLECTION_ROLLOFF,
AEGP_LayerStream_TRANSPARENCY_COEFF,
AEGP_LayerStream_TRANSPARENCY_ROLLOFF,
AEGP_LayerStream_INDEX_OF_REFRACTION,
AEGP_LayerStream_EXTRUSION_BEVEL_STYLE,
AEGP_LayerStream_EXTRUSION_BEVEL_DIRECTION,
AEGP_LayerStream_EXTRUSION_BEVEL_DEPTH,
AEGP_LayerStream_EXTRUSION_HOLE_BEVEL_DEPTH,
AEGP_LayerStream_EXTRUSION_DEPTH,
AEGP_LayerStream_PLANE_CURVATURE,
AEGP_LayerStream_PLANE_SUBDIVISION,
Only valid for LIGHT and AV only:
AEGP_LayerStream_CASTS_SHADOWS,
AEGP_LayerStream_SOURCE_TEXT
AEGP_LayerStream_BEGIN =
AEGP_LayerStream_ANCHORPOINT,
AEGP_LayerStream_END =
AEGP_LayerStream_LIGHT_FALLOFF_DISTANCE+1
enum {
AEGP_LightFalloff_NONE = 0,
AEGP_LightFalloff_SMOOTH,
AEGP_LightFalloff_INVERSE_SQUARE_CLAMPED
};
typedef A_u_long AEGP_LightFalloffType;
effect_refH,
AEGP_GetEffectNumParamStreams(
AEGP_EffectRefH
A_long *num_parmsPL);
Function Purpose
AEGP_GetNewEffectStream Get an effect’s parameter stream. Plug-in must dispose of
ByIndex streamPH.
id,
AEGP_GetNewEffectStreamByIndex(
effect_refH,
AEGP_PluginID
AEGP_EffectRefH
PF_ParamIndex param_index,
AEGP_StreamRefH *streamPH);
AEGP_GetNewMaskStream Get a mask’s stream. The stream must be disposed. Also see
the AEGP_MaskSuite and
AEGP_MaskOutlineSuite for additional Mask
functions.
AEGP_MaskStream_OUTLINE,
AEGP_MaskStream_OPACITY,
AEGP_MaskStream_FEATHER,
AEGP_MaskStream_EXPANSION,
Useful for iteration:
AEGP_MaskStream_BEGIN =
AEGP_MaskStream_OUTLINE,
AEGP_MaskStream_END =
AEGP_MaskStream_EXPANSION+1
AEGP_GetNewMaskStream(
mask_refH,
AEGP_PluginID aegp_plugin_id,
which_stream,
AEGP_MaskRefH
AEGP_MaskStream
AEGP_StreamRefH *mask_strmPH);
AEGP_DisposeStream Dispose of a stream (do this with all streams passed to the
plug-in by these functions).
AEGP_DisposeStream(
AEGP_StreamRefH streamH);
aegp_plugin_id,
AEGP_GetNewMaskOpacity(
AEGP_PluginID
AEGP_MaskH maskH,
AEGP_StreamRefH
PF_ParamIndex param_index,
*mask_opacity_streamPH);
Function Purpose
AEGP_GetStreamName Get name of the stream (localized or forced English). is
handle of A_UTF16Char (contains null terminated
UTF16 string); must be disposed with
AEGP_FreeMemHandle.
AEGP_GetStreamName(
AEGP_PluginID pluginID,
streamH,
AEGP_StreamRefH
A_Boolean force_englishB,
AEGP_MemHandle
*utf_stream_namePH);
NOTE: if force_englishB is TRUE, the default name
will override any stream renaming which has been done
(either programatically, or by the user).
streamH,
AEGP_GetStreamUnitsText(
AEGP_StreamRefH
A_Boolean force_englishB,
A_char *unitsZ);
streamH,
AEGP_GetStreamProperties(
AEGP_StreamRefH
AEGP_StreamFlags *flagsP,
A_FpLong *minP0,
A_FpLong *maxP0);
AEGP_StreamRefH streamH,
AEGP_IsStreamTimevarying(
A_Boolean *is_timevaryPB);
Function Purpose
AEGP_GetStreamType Get type (dimension) of a stream.
streamH,
AEGP_GetStreamType(
AEGP_StreamRefH
AEGP_StreamType *stream_typeP);
AEGP_StreamType_NO_DATA,
AEGP_StreamType_TwoD_SPATIAL,
AEGP_StreamType_TwoD,
AEGP_StreamType_ThreeD,
AEGP_StreamType_ThreeD_SPATIAL,
AEGP_StreamType_OneD,
AEGP_StreamType_COLOR,
AEGP_StreamType_ARB,
AEGP_StreamType_MARKER,
AEGP_StreamType_LAYER_ID,
AEGP_StreamType_MASK_ID,
AEGP_StreamType_MASK,
AEGP_StreamType_TEXT_DOCUMENT
NOTE: always returns ThreeD_Spatial for position,
regardless of whether or not the layer is 3D.
aegp_plugin_id,
AEGP_GetNewStreamValue(
AEGP_PluginID
AEGP_StreamRefH streamH,
AEGP_LTimeMode time_mode,
pre_exprB,
const A_Time *timePT,
A_Boolean
AEGP_StreamValue2 *valueP);
aegp_plugin_id,
AEGP_SetStreamValue(
streamH,
AEGP_PluginID
AEGP_StreamRefH
AEGP_StreamValue2 *valueP);
Function Purpose
AEGP_GetLayerStreamValue NOTE: This convenience function is only valid for streams
with primitive data types, and not for
AEGP_ArbBlockVal, AEGP_MarkerValH or
AEGP_MaskOutlineValH. For these and other
complex types, use
AEGP_GetNewStreamValue,described above.
layerH,
AEGP_GetLayerStreamValue(
which_stream,
AEGP_LayerH
time_mode,
AEGP_LayerStream
*timePT,
AEGP_LTimeMode
pre_expB,
const A_Time
*stream_valP,
A_Boolean
AEGP_StreamVal
AEGP_StreamType *strm_typeP0);
aegp_plugin_id,
AEGP_GetExpression(
streamH,
AEGP_PluginID
AEGP_StreamRefH
AEGP_MemHandle *expressionHZ);
aegp_plugin_id,
AEGP_SetExpression(
streamH,
AEGP_PluginID
AEGP_StreamRefH
const char* expressionP);
Function Purpose
AEGP_DuplicateStreamRef Duplicates a given AEGP_StreamRefH. Dispose of the
duplicate.
AEGP_DuplicateStreamRef(
AEGP_PluginID aegp_plugin_id,
AEGP_StreamRefH streamH,
AEGP_StreamRefH *dup_streamPH);
DYNAMIC STREAMS
Function Purpose
AEGP_GetNewStreamRefForLayer Retrieves the AEGP_StreamRefH corresponding to
the layer. This function is used to initiate a recursive
walk of the layer’s streams.
AEGP_GetNewStreamRefForLayer(
AEGP_PluginID aegp_plugin_id,
AEGP_LayerH layerH,
AEGP_StreamRefH *streamPH);
Function Purpose
AEGP_GetStreamGroupingType Retrieves the grouping type for the given
AEGP_StreamRefH.
AEGP_GetStreamGroupingType(
AEGP_StreamRefH streamH,
AEGP_StreamGroupingType
*group_typeP);
AEGP_StreamGroupingType will be one of the
following:
AEGP_StreamGroupingType_NONE
AEGP_StreamGroupingType_LEAF
AEGP_StreamGroupingType_NAMED_GROUP
AEGP_StreamGroupingType_INDEXED_GROUP
Function Purpose
AEGP_GetDynamicStreamFlags Retrieves the flags for a given AEGP_StreamRefH.
AEGP_GetDynamicStreamFlags(
AEGP_StreamRefH streamH,
AEGP_DynStreamFlags *flagsP);
AEGP_DynStreamFlags will be one of the
following:
AEGP_DynStreamFlag_ACTIVE_EYEBALL
AEGP_DynStreamFlag_HIDDEN
AEGP_DynStreamFlag_DISABLED
AEGP_DynStreamFlag_ELIDED
AEGP_DynStreamFlag_SHOWN_WHEN_EMPTY
AEGP_DynStreamFlag_SKIP_REVEAL_WHEN
_UNHIDDEN
AEGP_DynStreamFlag_ACTIVE_EYEBALL means
that the stream is available for reading and writing.
AEGP_DynStreamFlag_HIDDEN means that, while
the stream is still readable/writable, it may not currently
be visible in the UI.
AEGP_DynStreamFlag_DISABLED A read-only
flag. Indicates whether the AEGP_StreamRefH is
grayed out in the UI. Note that as of CS5, this flag will
not be returned if a parameter is disabled. Instead, check
PF_PUI_DISABLED in ui_flags.
AEGP_DynStreamFlag_ELIDED A read-only flag.
Indicates that the AEGP_StreamRefH is read-only,
the user never sees it. However, the children are still seen
and not indented in the Timeline panel.
AEGP_DynStreamFlag_SHOWN_WHEN_EMPTY
New in CS6. A read-only flag. Indicates that this stream
group should be shown when empty.
AEGP_DynStreamFlag_SKIP_REVEAL_WHEN
_UNHIDDEN New in CS6. A read-only flag. Indicates
that this stream property will not be automatically
revealed when un-hidden.
Function Purpose
AEGP_SetDynamicStreamFlag Sets the specified flag for the AEGP_StreamRefH.
Note; flags must be set individually. Undoable if
undoableB is TRUE.
AEGP_SetDynamicStreamFlag(
AEGP_StreamRefH streamH,
AEGP_DynStreamFlags one_flag,
A_Boolean undoableB,
A_Boolean setB);
This call may be used to dynamically show or hide
parameters, by setting and clearing
AEGP_DynStreamFlag_HIDDEN. However,
AEGP_DynStreamFlag_DISABLED may not be
set.
Function Purpose
AEGP_GetNewStreamRefByMatchname Retrieves a sub-stream by match name from a given
AEGP_StreamRefH. Only legal for
AEGP_StreamGroupingType_NAMED_GROUP.
AEGP_GetNewStreamRefByMatchname(
AEGP_PluginID aegp_plugin_id,
AEGP_StreamRefH parent_groupH,
const A_char *match_nameZ,
AEGP_StreamRefH *streamPH);
Here are some handy stream names, for which references may
be retrieved:
AEGP_StreamGroupName_MASK_PARADE
AEGP_StreamGroupName_MASK_ATOM
AEGP_StreamName_MASK_FEATHER
AEGP_StreamName_MASK_OPACITY
AEGP_StreamName_MASK_OFFSET
AEGP_StreamGroupName_EFFECT_PARADE
AEGP_StreamGroupName_LAYER
AEGP_StreamGroupName_AV_LAYER
AEGP_StreamGroupName_TEXT_LAYER
AEGP_StreamGroupName_CAMERA_LAYER
AEGP_StreamGroupName_LIGHT_LAYER
AEGP_StreamGroupName_AUDIO
AEGP_StreamGroupName_MATERIAL_OPTIONS
AEGP_StreamGroupName_TRANSFORM
AEGP_StreamGroupName_LIGHT_OPTIONS
AEGP_StreamGroupName_CAMERA_OPTIONS
Function Purpose
AEGP_ReorderStream Sets the new index of the specified
AEGP_StreamRefH. Undoable. Only valid for
children of
AEGP_StreamGroupingType_INDEXED_GROUP.
The AEGP_StreamRefH is updated to refer to the
newly-ordered stream.
AEGP_ReorderStream(
AEGP_StreamRefH streamH
A_long new_indexL);
Function Purpose
AEGP_GetMatchName Retrieves the match name for the specified
AEGP_StreamRefH. Note that this may differ from
the display name, which can be retrieves using
AEGP_GetStreamName, in AEGP_StreamSuite.
nameZ can be up to
AEGP_MAX_STREAM_MATCH_NAME_SIZE in
length.
AEGP_GetMatchName(
AEGP_StreamRefH streamH,
A_char *nameZ);
Function Purpose
AEGP_IsSeparationLeader Valid on leaf streams only. Returns true if this stream is a
multidimensional stream that can have its dimensions
separated, though they may not be currently separated.
Terminology: A Leader is the stream that can be separated, a
Follower is one of N automatic streams that correspond to the
N dimensions of the Leader.
A Leader isn't always separated, call
AEGP_AreDimensionsSeparated to find out if it
is. As of CS4, the only stream that is ever separarated is the
layer's Position property. Please *do not* write code assuming
that, we anticipate allowing separation of more streams in the
future.
AEGP_IsSeparationLeader(
AEGP_StreamRefH streamH,
A_Boolean *leaderPB);
AEGP_IsSeparationFollower Valid on leaf streams only. Returns true if this stream is a one
dimensional property that represents one of the dimensions of
a Leader. You can retrieve stream from the Leader using
AEGP_GetSeparationFollower().
AEGP_IsSeparationFollower(
AEGP_StreamRefH streamH
A_Boolean *followerPB);
Function Purpose
AEGP_GetSeparationLeader Valid on separation Followers only, returns the Leader it is part
of.
AEGP_GetSeparationLeader(
AEGP_StreamRefH follower_streamH,
AEGP_StreamRefH *leader_streamPH);
Keyframes make After Effects what it is. AEGPs (and...ssshh, don’t tell anyone...effects) can
use this suite to add, manipulate and remove keyframes from any keyframe-able stream.
Function Purpose
AEGP_GetStreamNumKFs Retrieves the number of keyframes on the given stream.
Returns AEGP_NumKF_NO_DATA if the stream is
not keyframe-able. Also, note that a stream without
keyframes isn’t necessarily constant; it can be altered by
expressions.
streamH,
AEGP_GetStreamNumKFs(
AEGP_StreamRefH
A_long *num_kfsPL);
streamH,
AEGP_GetKeyframeTime(
AEGP_StreamRefH
time_mode,
AEGP_KeyframeIndex index,
AEGP_LTimeMode
A_Time *timePT);
Function Purpose
AEGP_InsertKeyframe Adds a keyframe to the specified stream (at the specified
composition or layer time). Returns the new keyframe’s
index. All indexes greater than the new index are now
invalid (but you knew that). If there is already a keyframe
at that time, the values will be updated.
streamH,
AEGP_InsertKeyframe(
time_mode,
AEGP_StreamRefH
*timePT,
AEGP_LTimeMode
const A_Time
AEGP_KeyframeIndex *key_indexP);
index,
AEGP_StreamRefH streamH,
AEGP_KeyframeIndex
const AEGP_StreamValue2*valP);
A_short *t_dimPS);
Function Purpose
AEGP_GetNewKeyframe Returns the AEGP_StreamValue2s representing the
SpatialTangents stream’s tangential values at the time of the keyframe.
The returned AEGP_StreamValue2s must be
disposed of using AEGP_DisposeStreamValue.
plugin_id,
AEGP_GetNewKeyframeSpatialTangents(
streamH,
AEGP_PluginID
AEGP_KeyframeIndex key_index,
AEGP_StreamRefH
AEGP_StreamValue2 *in_tanP0,
AEGP_StreamValue2 *out_tanP0);
streamH,
AEGP_GetKeyframeTemporalEase(
AEGP_KeyframeIndex key_index,
AEGP_StreamRefH
dimensionL,
AEGP_KeyframeEase *in_easeP0,
A_long
AEGP_KeyframeEase *out_easeP0);
NOTE: the returned ease values must be multiplied by
layer height to match the values displayed in the After
Effects UI.
Function Purpose
AEGP_SetKeyframeTemporalEase Specifies the AEGP_KeyframeEases to be used for
the stream’s value at the time of the keyframe.
dimensionL ranges from 0 to
(temporal_dimensionality -1). The
AEGP_KeyframeEases passed are not adopted by
After Effects.
AEGP_SetKeyframeTemporalEase(
streamH,
key_index,
AEGP_StreamRefH
dimL,
AEGP_KeyframeIndex
streamH,
AEGP_GetKeyframeFlags(
key_index,
AEGP_StreamRefH
AEGP_KeyframeIndex
AEGP_KeyframeFlags *flagsP);
*flagsP will be a combination of the following:
AEGP_KeyframeFlag_NONE
AEGP_KeyframeFlag_TEMPORAL_CONTINUOUS
AEGP_KeyframeFlag_TEMPORAL_AUTOBEZIER
AEGP_KeyframeFlag_SPATIAL_CONTINUOUS
AEGP_KeyframeFlag_SPATIAL_AUTOBEZIER
AEGP_KeyframeFlag_ROVING
AEGP_SetKeyframeFlag Sets the specified flag for the keyframe. Flags must be set
individually.
streamH,
AEGP_SetKeyframeFlag(
key_index,
AEGP_StreamRefH
AEGP_KeyframeIndex
AEGP_KeyframeFlags flag,
A_Boolean valueB);
Function Purpose
AEGP_GetKeyframeInterpolation Retrieves the in and out
AEGP_KeyframeInterpolationTypes for the
specified keyframe.
streamH,
AEGP_GetKeyframeInterpolation(
AEGP_KeyframeIndex key_index,
AEGP_StreamRefH
*inP0,
AEGP_KeyframeInterpolationType
AEGP_KeyframeInterpolationType
*outP0);
AEGP_KeyframeInterpolationType is one of
the following:
AEGP_KeyInterp_NONE
AEGP_KeyInterp_LINEAR
AEGP_KeyInterp_BEZIER
AEGP_KeyInterp_HOLD
in_interp,
AEGP_KeyframeInterpolationType
AEGP_KeyframeInterpolationType
out_interp);
time_mode,
AEGP_AddKeyframesInfoH
*timePT,
AEGP_LTimeMode
const A_Time
A_long *indexPL);
Function Purpose
AEGP_SetAddKeyframe Sets the value of the specified keyframe.
AEGP_AddKeyframesInfoH akH,
AEGP_SetAddKeyframe(
A_long indexL,
const AEGP_StreamValue2*valueP);
Each time you call AEGP_InsertKeyframe(), the entire stream is added to the undo
stack. If you’re adding one or two keyframes, this isn’t a problem. However, if you’re writing
a keyframer, you’ll want to do things the right way.
MARKER STREAMS
Function Purpose
AEGP_NewMarker Creates a new marker.
AEGP_NewMarker(
AEGP_MarkerValP *markerPP);
Function Purpose
AEGP_DuplicateMarker Duplicates a marker (didn’t see that one coming, eh?).
AEGP_DuplicateMarker(
AEGP_MarkerValP markerP,
AEGP_MarkerValP *new_markerP);
Function Purpose
AEGP_GetIndCuePointParam Returns the cue point param at the specified index (which
must be between 0 and (cue point params -1). Returned
handles are UTF-16, NULL-terminated strings, and must be
disposed of by caller using AEGP_FreeMemHandle.
AEGP_GetIndCuePointParam(
AEGP_PluginID id,
AEGP_ConstMarkerValP markerP,
A_long param_indexL,
AEGP_MemHandle *unicodeKeyPH,
AEGP_MemHandle *uni_ValuePH);
AEGP_SetMarkerDuration AEGP_SetMarkerDuration(
AEGP_MarkerValP markerP,
const A_Time *durationPT);
AEGP_GetMarkerDuration AEGP_GetMarkerDuration(
AEGP_ConstMarkerValP markerP,
A_Time *durationPT);
Function Purpose
AEGP_GetLayerNumMasks Counts the masks applied to a layer,
AEGP_GetLayerNumMasks(
AEGP_LayerH aegp_layerH,
A_long *num_masksPL);
AEGP_GetLayerMaskBy Given a layer handle and mask index, returns a pointer to the
Index mask handle. You must destroy the mask handle by using
AEGP_DisposeMask().
aegp_layerH,
AEGP_GetLayerMaskByIndex(
AEGP_LayerH
A_long mask_indexL,
AEGP_MaskRefH *maskPH);
AEGP_GetMaskMode Given a mask handle, returns the current mode of the mask.
PF_MaskMode_NONE does nothing, PF_MaskMode_ADD is
the default behavior.
PF_MaskMode_ADD,
PF_MaskMode_NONE
PF_MaskMode_SUBTRACT,
PF_MaskMode_INTERSECT,
PF_MaskMode_LIGHTEN,
PF_MaskMode_DARKEN,
PF_MaskMode_DIFFERENCE,
AEGP_GetMaskMode(
AEGP_MaskRefH maskH,
PF_MaskMode *modeP);
Function Purpose
AEGP_SetMaskMode Sets the mode of the given mask.
AEGP_SetMaskMode(
AEGP_MaskRefH maskH,
PF_MaskMode mode);
AEGP_GetMaskMotionBlurState Retrieves the motion blur setting for the given mask.
mask_refH,
AEGP_GetMaskMotionBlurState(
AEGP_MaskRefH
AEGP_MaskMBlur *blur_stateP);
AEGP_MaskMBlur will be one of the following:
AEGP_MaskMBlur_SAME_AS_LAYER
AEGP_MaskMBlur_OFF
AEGP_MaskMBlur_ON
AEGP_SetMaskMotionBlurState New in CS6. Sets the motion blur setting for the given mask.
mask_refH,
AEGP_SetMaskMotionBlurState(
AEGP_MaskRefH
AEGP_MaskMBlur blur_state);
AEGP_GetMaskFeatherFalloff New in CS6. Gets the type of feather falloff for the given mask,
either AEGP_MaskFeatherFalloff_SMOOTH or
AEGP_MaskFeatherFalloff_LINEAR.
mask_refH,
AEGP_SetMaskMotionBlurState(
AEGP_MaskRefH
AEGP_MaskFeatherFalloff
*feather_falloffP);
AEGP_SetMaskFeatherFalloff Sets the type of feather falloff for the given mask.
mask_refH,
AEGP_SetMaskMotionBlurState(
AEGP_MaskRefH
AEGP_MaskFeatherFalloff
feather_falloff);
mask_refH,
AEGP_GetMaskID(
AEGP_MaskRefH
AEGP_MaskIDVal *id_valP);
Function Purpose
AEGP_CreateNewMask Creates a new mask on the referenced AEGP_LayerH, with zero
nodes. The new mask’s index is returned.
AEGP_CreateNewMask(
AEGP_LayerH layerH,
AEGP_MaskRefH *mask_refPH,
A_long *mask_indexPL0);
AEGP_DeleteMaskFromLayer AEGP_DeleteMaskFromLayer(
AEGP_MaskRefH mask_refH);
NOTE: As of 6.5, if you delete a mask and it or a child stream is
selected, the current selection within the composition will become
NULL.
mask_refH,
AEGP_SetMaskColor(
AEGP_MaskRefH
const AEGP_ColorVal *colorP);
mask_refH,
AEGP_GetMaskLockState(
AEGP_MaskRefH
A_Boolean *is_lockedPB);
mask_refH,
AEGP_SetMaskLockState(
AEGP_MaskRefH
A_Boolean lockB);
mask_refH,
AEGP_GetMaskIsRotoBezier(
AEGP_MaskRefH
A_Boolean *is_roto_bezierPB);
Function Purpose
AEGP_SetMaskIsRotoBezier Sets whether a given mask is to be used as a rotobezier.
mask_refH,
AEGP_SetMaskIsRotoBezier(
AEGP_MaskRefH
A_Boolean *is_roto_bezierPB);
orig_mask_refH,
AEGP_DuplicateMask(
AEGP_MaskRefH
AEGP_MaskRefH *dupe_mask_refPH);
MASK OUTLINES
The Mask Suite above tells plug-ins about the masks on a layer, but not about the details of
those masks. This is because processing is required on After Effects’ part to access the
information; the information isn’t just lying around. Plug-ins access that information using
this Mask Outline Suite.
AEGP_MaskOutlineVal *mask_outlineP,
AEGP_GetMaskOutlineNumSegments(
A_long *num_segmentsPL);
Function Purpose
AEGP_GetMaskOutline Given a mask outline pointer and a point between 0 and the total
VertexInfo number of segments. For closed mask paths, vertex[0] is the
same as vertex[num_segments].
AEGP_MaskOutlineVal *mask_outlineP,
AEGP_GetMaskOutlineVertexInfo(
A_long which_pointL,
AEGP_MaskVertex *vertexP);
AEGP_SetMaskOutlineVertex Sets the vertex information for a given index. Setting vertex 0 is
Info special; its in tangent will actually set the out tangent of the last
vertex in the outline. Of course, which_pointL must be valid
for the mask outline, or the function will return an error.
mask_outlineH,
AEGP_SetMaskOutlineVertexInfo(
which_pointL,
AEGP_MaskOutlineValH
AEGP_VertexIndex
AEGP_MaskVertex *vertexP);
AEGP_CreateVertex Creates a vertex at index position. All vertices which formerly had
an AEGP_VertexIndex of position or greater will have their
indices incremented by one.
mask_outlineH,
AEGP_CreateVertex(
AEGP_MaskOutlineValH
AEGP_VertexIndex position);.
NOTE: All masks must have at least one vertex.
Function Purpose
AEGP_SetMaskOutline New in CS6. Feather must already exist; use
FeatherInfo AEGP_CreateMaskOutlineFeather first, if needed.
AEGP_SetMaskOutlineFeatherInfo(
AEGP_MaskOutlineValH mask_outlineH,
AEGP_VertexIndex which_featherL,
const AEGP_MaskFeather *featherP);
MASK FEATHERING
typedef struct {
A_long segment; // mask segment where feather is
PF_FpLong segment_sF; // 0-1: feather location on segment
PF_FpLong radiusF; // negative value allowed if type ==
AEGP_MaskFeatherType_INNER
PF_FpShort ui_corner_angleF; // 0-1: angle of UI handle on
corners
PF_FpShort tensionF; // 0-1: tension of boundary at feather
pt
AEGP_MaskFeatherInterp interp;
AEGP_MaskFeatherType type;
} AEGP_MaskFeather;
This suite enables AEGPs to get and set the text associated with text layers. Note: to get
started, retrieve an AEGP_TextDocumentH by calling AEGP_GetLayerStreamValue ,
above, and passing AEGP_StreamType_TEXT_DOCUMENT as the AEGP_StreamType.
Function Purpose
AEGP_GetNewText Retrieves the UTF-16, NULL-terminated string used in
the AEGP_TextDocumentH. Note: After Effects will
allocate the AEGP_MemHandle; your plug-in must
dispose of it when done using
AEGP_FreeMemHandle.
id,
AEGP_GetNewText(
text_docH,
AEGP_PluginID
AEGP_TextDocumentH
AEGP_MemHandle *unicodePH);
text_docH,
AEGP_SetText(
AEGP_TextDocumentH
const A_u_short *unicodePS,
long lengthL);
The AEGP_TextLayerSuite provides access to the actual outlines of the text used by text
layers. One you have a path, you can manipulate it with PF_PathQuerySuite and
PF_PathDataSuite .
Function Purpose
AEGP_GetNewTextOutlines Allocates and returns a handle to the
AEGP_TextOutlinesHs associated with the
specified layer. outlinesPH will be NULL if there are
no AEGP_TextOutlinesHs associated with
layerH (in other words, if it’s not a text layer).
AEGP_GetNewTextOutlines(
AEGP_LayerH layerH, /
const A_Time *layer_timePT,
AEGP_TextOutlinesH *outlinesPH);
outlinesH,
AEGP_GetNumTextOutlines(
AEGP_TextOutlinesH
A_long *num_otlnsPL);
outlinesH,
AEGP_GetIndexedTextOutline(
path_indexL,
AEGP_TextOutlinesH
A_long
PF_PathOutlinePtr *pathPP);
The Utility suite supplies error message handling, AEGP version checking and access to the
undo stack. Everything you need to keep After Effects and your plug-in tidy.
Function Purpose
AEGP_ReportInfo Displays dialog with name of the AEGP followed by the string
passed.
aegp_plugin_id,
AEGP_ReportInfo(
AEGP_PluginID
const A_char *info_stringZ);
AEGP_ReportInfoUnicode New in CC. Displays dialog with name of the AEGP followed by
the unicode string passed.
aegp_plugin_id,
AEGP_ReportInfoUnicode(
AEGP_PluginID
const A_UTF16Char *info_stringP);
*major_versionPS,
AEGP_GetDriverSpecVersion(
A_short
A_short *minor_versionPS);
AEGP_StartUndoGroup Add action(s) to the undo queue. The user may undo any actions
between this and AEGP_EndUndoGroup(). The
undo_nameZ will appear in the edit menu.
AEGP_StartUndoGroup(
const A_char *undo_nameZ);
Function Purpose
AEGP_RegisterWithAEGP Returns an AEGP_PluginID, which effect plug-ins can then
use in calls to many functions throughout the AEGP API. Effects
should only call this function once, during
PF_Cmd_GLOBAL_SETUP, and save the AEGP_PluginID
for later use. The first parameter can be any value, and the second
parameter should be the plug-in’s match name.
AEGP_RegisterWithAEGP(
AEGP_GlobalRefcon global_refcon,
const A_char *plugin_nameZ,
AEGP_PluginID *plugin_id);
AEGP_GetMainHWND Retrieves After Effects’ HWND; useful when displaying your own
dialog on Windows. If you don’t use After Effects’ HWND, your
modal dialog will not prevent interaction with the windows
behind, and pain will ensue.
AEGP_GetMainHWND(
void *main_hwnd);
AEGP_ShowHideAllFloaters Toggles whether or not floating palettes are displayed. Use this
with care; users get twitchy when you unexpectedly change the UI
on them.
AEGP_ShowHideAllFloaters(
A_Boolean include_tool_palB);
Function Purpose
AEGP_CharPalGetStrokeColor Retrieves the stroke color from the character palette.
AEGP_CharPalGetStrokeColor(
A_Boolean *is_scolor_definedPB,
AEGP_ColorVal *stroke_colorP);
AEGP_CharPalIsFillColorUI Returns whether or not the fill color is frontmost. If it isn’t, the
Frontmost stroke color is frontmost.
AEGP_CharPalIsFillColorUIFrontmost(
A_Boolean *is_fcolor_selectedPB);
AEGP_CauseIdleRoutines This routine is safe to call from threads other than the main
ToBeCalled thread. It is asynchronous and will return before the idle handler
is called. The suite functions to get this function pointer are not
thread safe; save it off in the main thread for use by the child
thread.
AEGP_CauseIdleRoutinesToBeCalled(void);
Function Purpose
AEGP_WriteToDebugLog Writes a message to the debug log, or to the OS command line if
After Effects was launched with the “-debug” option.
AEGP_WriteToDebugLog(
const A_char *subsystemZ,
const A_char *event_typeZ,
const A_char *infoZ);
AEGP_GetLastErrorMessage Retrieves the last error message displayed to the user, and its
associated error number. Pass in the size of the character buffer to
be returned.
AEGP_GetLastErrorMessage(
A_long buffer_size,
A_char *error_string,
A_Err *error_num);
AEGP_ExecuteScript Have After Effects execute a script. The script passed in can be in
either UTF-8 or the current application encoding (if
platform_encodingB is passed in as TRUE).
The two out arguments are optional. The value of the last line of
the script is what is passed back in outResultPH0.
AEGP_ExecuteScript(
AEGP_PluginID inPlugin_id,
const A_char *inScriptZ,
*outResultPH0,
const A_Boolean platform_encodingB ,
AEGP_MemHandle
AEGP_MemHandle *outErrStringPH0);
AEGP_HostIsActivated Returns TRUE if the user has successfully activated After Effects.
AEGP_HostIsActivated(
A_Boolean *is_activatedPB);
Function Purpose
AEGP_GetPluginPaths New in CC. Returns a particular path associated with the plug-in:
AEGP_GetPathTypes_PLUGIN - (Not Implemented) The
path to the location of the plug-in itself.
AEGP_GetPathTypes_USER_PLUGIN -The suite specific
location of user specific plug-ins.
AEGP_GetPathTypes_ALLUSER_PLUGIN - The suite
specific location of plug-ins shared by all users.
AEGP_GetPathTypes_APP - The After Effects .exe or .app
location. Not plug-in specific.
AEGP_GetPluginPaths(
AEGP_PluginID aegp_plugin_id,
AEGP_GetPathTypes path_type
AEGP_MemHandle *unicode_pathPH);
Plug-ins have read and write access to persistent data in After Effects’ preferences. AEGPs
may add and manage their own persistent data using the following suite. The data entries are
accessed by (section key, value key) pairs. It is recommended that plug-ins use their
matchname as their section key, or as a prefix if using multiple section keys.
The available data types are A_long, A_FpLong, strings, and void*. A_FpLongs are stored
with 6 decimal places of precision. There is no provision for specifying a different precision.
String data supports the full 8-bit space. Only 0x00 is reserved for string ending. This makes
them ideal for storing UTF-8 encoded strings, ISO 8859-1, and plain ASCII. Both section
keys and value keys are of this type. For data types not represented by the simple data types
provided, use data handles containing your custom data. void* unstructured data allows you
to store any kind of data. You must pass in a size in bytes along with the data.
When calling any of the functions to retrieve the value of a key, if a given key is not found,
the default value is both written to the blob and returned as the value; if no default is
provided, a blank value will be written and returned.
Note that this data is stored in the application’s preferences, not in the project. As of 6.5,
there is no way to store opaque AEGP-generated data in an After Effects project.
Function Purpose
AEGP_GetApplicationBlob Obtains the handle to all persistent application data.
Modifying this will modify the application.
The AEGP_PersistentType parameter is new in
CC, and should be set to one of the following:
AEGP_PersistentType_MACHINE_SPECIFIC,
AEGP_PersistentType_MACHINE_INDEPENDENT,
AEGP_PersistentType_MACHINE_INDEPENDENT_RENDER,
AEGP_PersistentType_MACHINE_INDEPENDENT_OUTPUT,
AEGP_PersistentType_MACHINE_INDEPENDENT_
-COMPOSITION,
AEGP_PersistentType_MACHINE_SPECIFIC_TEXT,
AEGP_PersistentType_MACHINE_SPECIFIC_PAINT
AEGP_GetApplicationBlob(
AEGP_PersistentType blob_type,
AEGP_PersistentBlobH *blobPH);
Function Purpose
AEGP_GetValueKeyByIndex Retrieves the value of the indexed key.
AEGP_GetValueKeyByIndex(
AEGP_PersistentBlobH blobH,
const A_char *section_keyZ,
A_long key_index,
A_long max_key_size,
A_char *value_keyZ);
For the functions below, if a given key is not found, the default value is both written to the blob and
returned as the value; if no default is provided, a blank value will be written and returned.
AEGP_GetDataHandle Obtains the value associated with the given section’s key.
If using in-memory data structures, watch for endian
issues.
AEGP_GetDataHandle(
AEGP_PluginID plugin_id,
AEGP_PersistentBlobH blobH,
const A_char *section_keyZ,
const A_char *value_keyZ,
AEGP_MemHandle defaultH0,
AEGP_MemHandle *valuePH);
AEGP_GetString Obtains the string for a given section key’s value (and
indicates its length in actual_szLu0).
AEGP_GetString(
AEGP_PersistentBlobH blobH,
const A_char *section_keyZ,
const A_char *value_keyZ,
const A_char *defaultZ0,
A_u_long buf_sizeLu,
char *bufZ,
A_u_long *actual_szLu0);
Function Purpose
AEGP_GetLong Obtains the A_long associated with a given section
key’s value.
AEGP_GetLong(
AEGP_PersistentBlobH blobH,
const A_char *section_keyZ,
const A_char *value_keyZ,
A_long defaultL,
A_long *valuePL);
AEGP_SetDataHandle Sets the given section key’s value to the handle passed in.
AEGP_SetDataHandle(
AEGP_PersistentBlobH blobH,
const A_char *section_keyZ,
const A_char *value_keyZ,
const AEGP_MemHandle valueH);
Function Purpose
AEGP_SetData Sets the given section key’s value to the data contained in
dataPV.
AEGP_SetData(
AEGP_PersistentBlobH blobH,
const A_char *section_keyZ,
const A_char *value_keyZ,
A_u_long data_sizeLu,
const void *dataPV);
Function Purpose
AEGP_DeleteEntry Removes the given section’s value from the blob.
AEGP_DeleteEntry(
AEGP_PersistentBlobH blobH,
const A_char *section_keyZ,
const A_char *value_keyZ);
COLOR MANAGEMENT
We’ve provided a function so AEGPs can obtain information on After Effects’ current color
management settings.
Function Purpose
AEGP_GetBlendingTables Retrieves the current opaque
PF_EffectBlendingTables, for use with
AEGP_TransferRect.
AEGP_GetBlendingTables(
PR_RenderContextH
render_contextH,
PF_EffectBlendingTables
*blending_tables);
Function Purpose
AEGP_GetNewWorkingSpace Retrieves the opaque current working space ICC profile.
ColorProfile Must be disposed. The “New” in the name does not indicate
that you’re making up a new profile; rather, it’s part of our
function naming standard; anything with “New” in the name
allocates something which the caller must dispose.
AEGP_GetNewWorkingSpaceColorProfile(
AEGP_PluginID aegp_plugin_id,
AEGP_MemHandle *icc_profPH);
Function Purpose
AEGP_GetColorProfileApproxi- Returns a floating point number approximating the gamma
mateGamma setting used by the specified color profile.
AEGP_GetColorProfileApproximateGamma(
AEGP_ConstColorProfileP
profileP,
A_FpShort *approx_gammaP);
RENDER SUITES
Since we introduced the AEGP API, we’ve been asked to provide functions for retrieving
rendered frames. These function suites allows you to do just that. First, specify what you
want rendered in the AEGP_RenderOptionsSuite or AEGP_LayerRenderOptionsSuite.
Then do the rendering with AEGP_RenderSuite.
Function Purpose
AEGP_NewFromItem Returns the AEGP_RenderOptionsH associated with a given
AEGP_ItemH. If there are no options yet specified, After Effects
passes back an AEGP_RenderOptionsH with render time set to 0,
time step set to the current frame duration, field render set to
PF_Field_FRAME, and the depth set to the highest resolution
specified within the item.
AEGP_NewFromItem(
AEGP_PluginID plugin_id,
AEGP_ItemH itemH,
AEGP_RenderOptionsH *optionsPH);
Function Purpose
AEGP_Dispose Deletes an AEGP_RenderOptionsH.
AEGP_Dispose(
AEGP_RenderOptionsH optionsH);
AEGP_SetTimeStep Specifies the time step (duration of a frame) for the referenced
AEGP_RenderOptionsH.
AEGP_SetTimeStep(
AEGP_RenderOptionsH optionsH,
A_Time time_step);
AEGP_GetTimeStep Retrieves the time step (duration of a frame) for the given
AEGP_RenderOptionsH.
AEGP_GetTimeStep(
AEGP_RenderOptionsH optionsH,
A_Time *timePT);
Function Purpose
AEGP_GetWorldType Retrieves the AEGP_WorldType of the given
AEGP_RenderOptionsH.
AEGP_GetWorldType(
AEGP_RenderOptionsH optionsH,
AEGP_WorldType *typeP);
Function Purpose
AEGP_GetMatteMode Retrieves the AEGP_MatteMode for the given
AEGP_RenderOptionsH.
AEGP_GetMatteMode(
AEGP_RenderOptionsH optionsH,
AEGP_MatteMode *modeP);
AEGP_GetRenderGuide Passes back a boolean that is true if the render guide layers setting is on.
Layers
AEGP_GetRenderGuideLayers)(
AEGP_RenderOptionsH optionsH,
A_Boolean *will_renderPB);
AEGP_GetRenderQuality Get the render quality of the render queue item. Quality can be either
AEGP_ItemQuality_DRAFT or AEGP_ItemQuality_BEST.
AEGP_GetRenderQuality)(
AEGP_RenderOptionsH optionsH,
AEGP_ItemQuality *qualityP);
Function Purpose
AEGP_NewFromLayer Returns the AEGP_LayerRenderOptionsH associated with a
given AEGP_LayerH. Render time is set to the layer's current time,
time step is set to layer's frame duration, ROI to the layer's nominal
bounds, and EffectsToRender to "all". optionsPH must be disposed
by calling code.
AEGP_NewFromLayer(
AEGP_PluginID plugin_id,
AEGP_LayerH layerH,
AEGP_LayerRenderOptionsH *optionsPH);
Function Purpose
AEGP_SetTimeStep Specifies the time step (duration of a frame) for the referenced
AEGP_LayerRenderOptionsH.
AEGP_SetTimeStep(
AEGP_LayerRenderOptionsH optionsH,
A_Time time_step);
AEGP_GetTimeStep Retrieves the time step (duration of a frame) for the given
AEGP_LayerRenderOptionsH.
AEGP_GetTimeStep(
AEGP_LayerRenderOptionsH optionsH,
A_Time *timePT);
Function Purpose
AEGP_SetMatteMode Specifies the AEGP_MatteMode for the given
AEGP_LayerRenderOptionsH.
AEGP_SetMatteMode(
AEGP_LayerRenderOptionsH optionsH,
AEGP_MatteMode mode);
AEGP_MatteMode will be one of the following:
AEGP_MatteMode_STRAIGHT
AEGP_MatteMode_PREMUL_BLACK
AEGP_MatteMode_PREMUL_BG_COLOR
Function Purpose
AEGP_RenderAndCheck- Retrieves an AEGP_FrameReceiptH (not the actual pixels)
outFrame for the frame requested. Check in this receipt using
AEGP_CheckinFrame to release memory.
Create the AEGP_RenderOptionsH using the
AEGP_RenderOptionsSuite .
Optionally, the AEGP can pass a function to be called by After
Effects if the user cancels the current render, as well as a refcon
(constant reference to opaque data) for use during that
function.
AEGP_RenderAndCheckoutFrame(
AEGP_RenderOptionsH
optionsH,
AEGP_RenderSuiteCheckForCancel
cancel_functionP0,
AEGP_CancelRefcon
cancel_function_refconP0,
AEGP_FrameReceiptH
*receiptPH);
Function Purpose
AEGP_RenderAndCheck- New in CC 2014. This allows frame checkout of a layer with
outLayerFrame effects applied at non-render time. This is useful for an
operation that requires the frame, for example, when a button is
clicked and it is acceptable to wait for a moment while it is
rendering. Note: Since it is not asynchronous, it will not solve
the general problem where custom UI needs to draw based on
the frame.
Retrieves an AEGP_FrameReceiptH (not the actual pixels)
for the layer frame requested. Check in this receipt using
AEGP_CheckinFrame to release memory.
Create the AEGP_LayerRenderOptionsH using
AEGP_NewFromUpstreamOfEffect(), in the
AEGP_LayerRenderOptionsSuite .
You can actually use AEGP_NewFromLayer() to get other
layer param's layers with their effects applied. However, be
careful. If you do it in your effect A, and there's an effect B on
the other layer that does the same thing during rendering, you'd
create an infinite loop. If you're not doing it for render
purposes then it could be okay.
Optionally, the AEGP can pass a function to be called by After
Effects if the user cancels the current render, as well as a refcon
(constant reference to opaque data) for use during that
function.
AEGP_RenderAndCheckoutLayerFrame(
AEGP_LayerRenderOptionsH
optionsH,
A_Boolean render_plain_layer_frameB,
AEGP_RenderSuiteCheckForCancel
cancel_functionP0,
AEGP_CancelRefcon
cancel_function_refconP0,
AEGP_FrameReceiptH
*receiptPH);
AEGP_CheckinFrame Call this function as soon as your AEGP is done accessing the
frame. After Effects makes caching decisions based on which
frames are checked out, so don’t hog them!
AEGP_CheckinFrame(
AEGP_FrameReceiptH receiptH);
Function Purpose
AEGP_GetReceiptWorld Retrieves the pixels (AEGP_WorldH) associated with the
referenced AEGP_FrameReceiptH.
AEGP_GetReceiptWorld(
AEGP_FrameReceiptH receiptH,
AEGP_WorldH *worldPH);
Function Purpose
AEGP_HasItemChanged Returns whether the video of an AEGP_ItemH has changed
SinceTimestamp since the given AEGP_TimeStamp. Note: this does not track
changes in audio.
AEGP_HasItemChangedSinceTimestamp(
AEGP_ItemH itemH,
const A_Time *start_timeP,
const A_Time *durationP,
const AEGP_TimeStamp *time_stampP,
A_Boolean *changedPB);
AEGP_Worlds are the common format used throughout the AEGP APIs to describe frames
of pixels.
Function Purpose
AEGP_New Returns an allocated, initialized AEGP_WorldH.
plugin_id,
AEGP_New(
AEGP_PluginID
widthL,
AEGP_WorldType type,
heightL,
A_long
A_long
AEGP_WorldH *worldPH);
worldH,
AEGP_GetType(
AEGP_WorldH
AEGP_WorldType **typeP);
AEGP_WorldType will be one of the following:
AEGP_WorldType_8,
AEGP_WorldType_16,
AEGP_WorldType_32
worldH,
AEGP_GetSize(
*widthPL,
AEGP_WorldH
A_long
A_long *heightPL);
worldH,
AEGP_GetRowBytes(
AEGP_WorldH
A_u_long *row_bytesPL);
Function Purpose
AEGP_GetBaseAddr8 Returns the base address of the AEGP_WorldH for use
in pixel iteration functions. Will return an error if used
on a non-8bpc world.
worldH,
AEGP_GetBaseAddr8(
AEGP_WorldH
PF_Pixel8 **base_addrP);
worldH,
AEGP_GetBaseAddr16(
AEGP_WorldH
PF_Pixel16 **base_addrP);
worldH,
AEGP_FillOutPFEffectWorld(
AEGP_WorldH
PF_EffectWorld *pf_worldP);
radiusF,
AEGP_FastBlur(
mode,
A_FpLong
quality,
PF_ModeFlags
PF_Quality
AEGP_WorldH worldH);
Function Purpose
AEGP_NewPlatformWorld Creates a new AEGP_PlatformWorldH (a pixel
world native to the execution platform).
plugin_id,
AEGP_NewPlatformWorld(
type,
AEGP_PluginID
widthL,
AEGP_WorldType
heightL,
A_long
A_long
AEGP_PlatformWorldH *worldPH);
Use the AEGP_CompositeSuite to copy pixel worlds, operate on track mattes, and apply
transfer functions.
Function Purpose
AEGP_ClearAlphaExceptRect For the given PF_EffectWorld, sets the alpha to fully
transparent except for the specified rectangle.
AEGP_ClearAlphaExceptRect(
A_Rect *clipped_dst_rectPR,
PF_EffectWorld *dstP);
num_pix,
AEGP_PrepTrackMatte(
deepB,
A_long
*src_mask,
A_Boolean
mask_flags,
const PF_Pixel
PF_MaskFlags
PF_Pixel *dst_mask);
Function Purpose
AEGP_CopyBits_LQ Copies a rectangle of pixels (pass a NULL rectangle to get all
pixels) from one PF_EffectWorld to another, at low quality.
*src_worldP,
AEGP_CopyBits_LQ(
*src_r,
PF_EffectWorld
*dst_r,
A_Rect
A_Rect
PF_EffectWorld *dst_worldP);
*src,
AEGP_CopyBits_HQ_Straight(
*src_r,
PF_EffectWorld
*dst_r,
A_Rect
A_Rect
PF_EffectWorld *dst);
*src,
AEGP_CopyBits_HQ_Premul(
*src_r,
PF_EffectWorld
*dst_r,
A_Rect
A_Rect
PF_EffectWorld *dst);
AEGP_SoundDataSuite allows AEGPs to obtain and manipulate the audio associated with
compositions and footage items. Audio-only items may be added to the render queue using
AEGP_RenderNewItemSoundData() .
Function Purpose
AEGP_NewSoundData Creates a new AEGP_SoundDataH, of which the plug-in
must dispose.
AEGP_NewSoundData(
const AEGP_SoundDataFormat
*formatP,
AEGP_SoundDataH *new_dataPH);
AUDIO SETTINGS
This suite allows AEGPs to add items the to render queue (using default options), and
control the basic state of the render queue.
Function Purpose
AEGP_AddCompToRenderQueue Adds a composition to the render queue, using default
options.
AEGP_AddCompToRenderQueue(
AEGP_CompH compH,
const A_char* pathZ);
Function Purpose
AEGP_GetNumRQItems Returns the number of items currently in the render queue.
AEGP_GetNumRQItems(
A_long *num_itemsPL);
rq_item_index,
AEGP_GetRQItemByIndex(
A_long
AEGP_RQItemRefH *rq_item_refPH);
rq_itemH,
AEGP_SetRenderState(
AEGP_RQItemRefH
A_Boolean renderB);
Function Purpose
AEGP_GetStartedTime Returns the time (in seconds, since 1904) that rendering began.
rq_itemH,
AEGP_GetStartedTime(
AEGP_RQItemRefH
A_Time *started_timePT);
rq_itemH,
AEGP_GetElapsedTime(
AEGP_RQItemRefH
A_Time *render_timePT);
rq_itemH,
AEGP_GetLogType(
AEGP_RQItemRefH
AEGP_LogType *logtypeP);
AEGP_LogtType will have one of the following values:
AEGP_LogType_NONE
AEGP_LogType_ERRORS_ONLY
AEGP_LogType_PLUS_SETTINGS
AEGP_LogType_PER_FRAME_INFO
rq_itemH,
AEGP_SetLogType(
AEGP_RQItemRefH
AEGP_LogType logtype);
rq_itemH,
AEGP_RemoveOutputModule(
AEGP_RQItemRefH
AEGP_OutputModuleRefH outmodH);
rq_itemH,
AEGP_GetComment(
AEGP_RQItemRefH
A_char *commentZ);
rq_itemH,
AEGP_SetComment(
AEGP_RQItemRefH
const A_char *commentZ);
Function Purpose
AEGP_GetCompFromRQItem Retrieves the AEGP_CompH associated with the
AEGP_RQItemRefH.
rq_itemH,
AEGP_GetCompFromRQItem(
AEGP_RQItemRefH
AEGP_CompH *compPH);
New in CS6. This suite provides all the info a render queue manager needs to figure out
what is happening at any point in a render.
Function Purpose
AEGP_RegisterListener Register a set of plug-in-defined functions to be called by
the render queue. Use the refcon to pass in data that you
want to use later on when your plug-in-defined functions
in AEGP_RQM_FunctionBlock1 are called later. It
may be set it to NULL if you don’t need it.
AEGP_RegisterListener(
AEGP_PluginID aegp_plugin_id,
AEGP_RQM_Refcon aegp_refconP,
const AEGP_RQM_FunctionBlock1
*fcn_blockP );
The AEGP_RQM_FunctionBlock1 is defined as
follows:
struct _AEGP_RQM_FunctionBlock1 {
A_Err (*AEGP_RQM_RenderJobStarted)(
AEGP_RQM_BasicData *basic_dataP,
AEGP_RQM_SessionId jobid);
A_Err (*AEGP_RQM_RenderJobEnded)(
AEGP_RQM_BasicData *basic_dataP,
AEGP_RQM_SessionId jobid);
(AEGP_RQM_FunctionBlock1 definition continued
on next page)
Function Purpose
AEGP_RegisterListener (cont’d) A_Err (*AEGP_RQM_RenderJobItemStarted)(
AEGP_RQM_BasicData *basic_dataP,
AEGP_RQM_SessionId jobid,
AEGP_RQM_ItemId itemid);
A_Err (*AEGP_RQM_RenderJobItemUpdated)(
AEGP_RQM_BasicData *basic_dataP,
AEGP_RQM_SessionId jobid,
AEGP_RQM_ItemId itemid,
AEGP_RQM_FrameId frameid);
A_Err (*AEGP_RQM_RenderJobItemEnded)(
AEGP_RQM_BasicData *basic_dataP,
AEGP_RQM_SessionId jobid,
AEGP_RQM_ItemId itemid,
AEGP_RQM_FinishedStatus fstatus);
AEGP_RQM_FinishedStatus_UNKNOWN,
AEGP_RQM_FinishedStatus_SUCCEEDED,
AEGP_RQM_FinishedStatus_ABORTED,
AEGP_RQM_FinishedStatus_ERRED
A_Err (*AEGP_RQM_RenderJobItemReportLog)(
AEGP_RQM_BasicData *basic_dataP,
AEGP_RQM_SessionId jobid,
AEGP_RQM_ItemId itemid,
A_Boolean isError,
AEGP_MemHandle logbuf);
} AEGP_RQM_FunctionBlock1;
The AEGP_RQM_BasicData is defined below.
struct _AEGP_RQM_BasicData {
const struct SPBasicSuite
*pica_basicP;
A_long aegp_plug_id;
AEGP_RQM_Refcon aegp_refconPV;
} AEGP_RQM_BasicData;
Function Purpose
AEGP_GetAppVersion Obtain the app version. The app version is a handle to a
NULL-terminated A_UTF16Char string, and must be
disposed with AEGP_FreeMemHandle.
AEGP_GetAppVersion(
AEGP_RQM_SessionId sessid,
AEGP_MemHandle *utf_app_versionPH0);
AEGP_GetNumJobItemRenderSettings Get the number of render settings for the job with the
index specified.
AEGP_GetNumJobItemRenderSettings(
AEGP_RQM_SessionId sessid,
AEGP_RQM_ItemId itemid,
A_long *num_settingsPL);
AEGP_GetNumJobItemOutputModules Get the number of output modules for the job with the
index specified.
AEGP_GetNumJobItemOutputModules(
AEGP_RQM_SessionId sessid,
AEGP_RQM_ItemId itemid,
A_long *num_outputmodulesPL);
Function Purpose
AEGP_GetNumJobItemOutputModule Get the number of settings for the output module with
Settings the index specified.
AEGP_GetNumJobItemOutputModuleSettings(
AEGP_RQM_SessionId sessid,
outputModuleIndex,
AEGP_RQM_ItemId itemid,
A_long
A_long *num_settingsPL);
outputModuleIndex,
AEGP_RQM_ItemId itemid,
A_long
A_long settingIndex,
AEGP_MemHandle *utf_setting_namePH0,
AEGP_MemHandle *utf_setting_valuePH0);
warningIndex,
A_long outputModuleIndex,
A_long
AEGP_MemHandle *utf_warning_valuePH0);
Function Purpose
AEGP_GetJobItemFrameProperty Get a specific property on a job item frame. The property
name and values are handle to NULL-terminated
A_UTF16Char strings, and must be disposed with
AEGP_FreeMemHandle.
AEGP_GetJobItemFrameProperty(
AEGP_RQM_SessionId sessid,
AEGP_RQM_ItemId itemid,
AEGP_RQM_FrameId frameid,
A_long propertyIndex,
AEGP_MemHandle *utf_property_namePH0,
AEGP_MemHandle *utf_property_valuePH0);
AEGP_GetJobItemOutputModule Get a specific property off a job item output module. The
Property property name and values are handle to NULL-
terminated A_UTF16Char strings, and must be
disposed with AEGP_FreeMemHandle.
AEGP_GetJobItemOutputModuleProperty(
AEGP_RQM_SessionId sessid,
AEGP_RQM_ItemId itemid,
A_long outputModuleIndex,
A_long propertyIndex,
AEGP_MemHandle *utf_property_namePH0,
AEGP_MemHandle *utf_property_valuePH0);
Every item in the render queue has at least one output module specified. Use this suite to
query and control all aspects of the output modules attached to a given render item. You may
also add and remove output modules. Factoid: For each frame rendered for a given render
item, the list of output modules is traversed. So, for frame 0, output module 0, then 1, then
2 are called.
Function Purpose
AEGP_GetOutputModule Retrieves the indexed output module. NOTE:
ByIndex AEGP_OutputModuleRefH is an opaque data type, and can’t be
manipulated directly; you must use our accessor functions to
modify it.
AEGP_GetOutputModuleByIndex(
AEGP_RQItemRefH rq_itemH,
A_long outmod_indexL,
AEGP_OutputModuleRefH *outmodPH);
Function Purpose
AEGP_GetPostRenderAction Retrieves the post-render action setting for the referenced
AEGP_OutputModuleRefH.
AEGP_GetPostRenderAction(
AEGP_RQItemRefH rq_itemH,
AEGP_OutputModuleRefH outmodH,
AEGP_PostRenderAction *actionP);
AEGP_PostRenderAction will be one of the following:
AEGP_PostRenderOptions_IMPORT
AEGP_PostRenderOptions_
IMPORT_AND_REPLACE_USAGE
AEGP_PostRenderOptions_SET_PROXY
AEGP_GetEnabledOutputs Retrieves which output types are enabled for the referenced
AEGP_OutputModuleRefH.
AEGP_GetEnabledOutputs(
AEGP_RQItemRefH rq_itemH,
AEGP_OutputModuleRefH outmodH,
AEGP_OutputTypes *typesP);
AEGP_OutputTypes will contain one or both of the following
values:
AEGP_OutputType_VIDEO
AEGP_OutputType_AUDIO
NOTE: These are flags, not an enumeration.
AEGP_SetEnabledOutputs Specifies which output types are enabled for the referenced
AEGP_OutputModuleRefH.
AEGP_SetEnabledOutputs(
AEGP_RQItemRefH rq_itemH,
AEGP_OutputModuleRefH outmodH,
AEGP_OutputTypes enabled_types);
Function Purpose
AEGP_GetOutputChannels Retrieves which video channels are enabled for output in the
referenced AEGP_OutputModuleRefH.
AEGP_GetOutputChannels(
AEGP_RQItemRefH rq_itemH,
AEGP_OutputModuleRefH outmodH,
AEGP_VideoChannels *outchannelsP);
AEGP_VideoChannels will be one of the following:
AEGP_VideoChannels_RGB
AEGP_VideoChannels_RGBA
AEGP_VideoChannels_ALPHA
AEGP_SetOutputChannels Specifies which video channels are enabled for output in the
referenced AEGP_OutputModuleRefH.
AEGP_SetOutputChannels(
AEGP_RQItemRefH rq_itemH,
AEGP_OutputModuleRefH outmodH,
AEGP_VideoChannels outchannels);
Function Purpose
AEGP_GetCropInfo Retrieves whether or not the cropping is enabled for the referenced
AEGP_OutputModuleRefH, and the rectangle to be used.
AEGP_GetCropInfo(
AEGP_RQItemRefH rq_itemH,
AEGP_OutputModuleRefH outmodH,
A_Boolean *is_enabledBP,
A_Rect *crop_rectP);
AEGP_GetSoundFormatInfo Retrieves whether or not audio output is enabled for the referenced
AEGP_OutputModuleRefH, and the settings to be used.
AEGP_GetSoundFormatInfo(
AEGP_RQItemRefH rq_itemH,
AEGP_OutputModuleRefH outmodH,
AEGP_SoundDataFormat *formatP,
A_Boolean *enabledPB);
AEGP_SetSoundFormatInfo Specifies whether or not audio output is enabled for the referenced
AEGP_OutputModuleRefH, and the settings to be used.
AEGP_SetSoundFormatInfo(
AEGP_RQItemRefH rq_itemH,
AEGP_OutputModuleRefH outmodH,
AEGP_SoundDataFormat format_info,
A_Boolean enabledB);
Function Purpose
AEGP_SetOutputFilePath Specifies the path to which AEGP_OutputModuleRefH‘s output
file will be written. The file path is a NULL-terminated UTF-16
string with platform separators.
AEGP_SetOutputFilePath(
AEGP_RQItemRefH rq_itemH,
AEGP_OutputModuleRefH outmodH,
const A_UTF16Char *pathZ);
These functions provide a way for effects (and AEGPs) to obtain information about the
context of an applied effect. NOTE: Any time you modify or rely on data from outside the
normal render pipeline, you run the risk of dependency problems. There is no way for After
Function Purpose
AEGP_GetEffectLayer Obtain the layer handle of the layer to which the effect is
applied.
AEGP_GetEffectLayer(
PF_ProgPtr effect_ref,
AEGP_LayerH *layerPH);
aegp_plugin_id,
AEGP_GetNewEffectForEffect(
AEGP_PluginID
PF_ProgPtr effect_ref,
AEGP_EffectRefH *effectPH);
time_scaleLu,
long what_timeL,
unsigned long
A_Time *comp_timePT);
AEGP_GetEffectCamera Obtain the camera (if any) being used by After Effects to
view the effect’s layer.
AEGP_GetEffectCamera(
PF_ProgPtr effect_ref,
const A_Time *comp_timePT,
AEGP_LayerH camera_layerPH);
The model view for the camera matrix is inverse of the matrix obtained from
AEGP_GetEffectCameraMatrix() . Also note that our matrix is row-based; OpenGL’s is
column-based.
Function Purpose
AEGP_GetNumThreads Ask After Effects how many threads are currently available.
AEGP_GetNumThreads(
A_long *num_threadsPL);
The FIMSuite allows file types handled by AEGPs to appear as part of the After Effects
import dialog, and drag-and-drop messaging. These are not for use by AEIOs! Rather, they
are for importing projects which are best represented as After Effects compositions.
Function Purpose
AEGP_RegisterImport Registers the name of the file type(s) supported by the plug-in. Upon
Flavor return, imp_refP will be a valid opaque reference, or
AE_FIM_ImportFlavorRef_NONE.
*nameZ,
AEGP_RegisterImportFlavor(
const char
AE_FIM_ImportFlavorRef *imp_refP);
AEGP_RegisterImport Registers an array of file types and file extensions (the two arrays need
FlavorFileTypes not be of equal length) supported by the AEGP.
imp_ref,
AEGP_RegisterImportFlavorFileTypes(
num_filekindsL,
AE_FIM_ImportFlavorRef
*kindsAP,
long
num_fileextsL,
const AEIO_FileKind
long
const AEIO_FileKind *extsAP);
ref,
AEGP_RegisterImportFlavorImportCallbacks(
AE_FIM_ImportFlavorRef
AE_FIM_ImportFlags single_flag,
const AE_FIM_ImportCallbacks *imp_cbsP);
imp_options,
AEGP_SetImportedItem(
AE_FIM_ImportOptions
AEGP_ItemH imported_itemH);
As soon as we showed developers the initial implementation of AEGP suites, they wanted to
“cheat” and use them from within effects. This is certainly possible, but please keep in mind
that depending on factors outside the effect API (i.e., any information you get from the
Effects can use some AEGP suites to take advantage of camera and lighting information, as
well as the AEGP_GetLayerParentComp and AEGP_GetCompBGColor functions. This
should not be interpreted to mean that effects can use any AEGP suite calls. Also, see the
Events chapter for more information on effects adding keyframes.
AEGP_PFInterfaceSuite is the starting point. The functions in this suite allow you to
retrieve the AEGP_LayerH for the layer to which the effect is applied, and the
AEGP_EffectRefH for the instance of your effect. AEGP_RegisterWithAEGP allows you
to get an AEGP_PluginID, which is needed for many AEGP calls.
One word: Don’t. Effects cannot allow the results of AEGP queries to control what is
rendered, without appropriately storing those query results (usually in sequence data),
cancelling their own render, and forcing a re-render using the queried information. This is
tricky. Failure to do so will result in nasty, subtle caching bugs guaranteed to cause hair loss
and weight gain.
AEGP DETAILS
HAVE A COOKIE
In cases where After Effects must preserve state information around the functions your
AEGP calls (as when an artisan is rendering a frame, or a keyframer is adding and removing
a series of keyframes from the same stream), you’ll call begin() and end() functions.
Typically, the begin function will return an opaque identifier, or ‘cookie’, which you must
then pass to the functions being used. The end function will properly dispose of the cookie.
See AEGP_StartAddKeyframes() for an example.
Solids have names in the After Effects UI, but not in their PF_LayerDef . Consequently,
their names cannot be retrieved by AEGP_GetItemName or AEGP_GetLayerName .
However, you can use the ItemH associated with them to AEGP_GetItemName .
8: Artisans
NOTE: If you’re considering developing an Artisan, please talk it over with us first.
The Artisan API exposes function hooks necessary for a plug-in to provide rendered output
of 3D layers, taking over completely from After Effects (which still handles all rendering of
2D layers). There can be only one Artisan per composition, chosen from within the
Composition Settings > Advanced dialog. Artisans render the 3D environment, asking After
Effects for information about each element in the composition. As you might guess, this is a
vast and tedious process. This API is not recommended for anyone without a strong need to
override After Effects’ 3D rendering.
Artisans may share information with effects written to communicate with them, but effects
may not initiate this communication. Many of the suites used by Artisans require a
rendering context which is generated only after all effects have been applied to the layer.
INTERACTIVE ARTISANS
These differ from standard artisans in that they handle all layers in a composition (not just
those which the user has made 3D), and they will only ever be called for onscreen display,
never for rendered final output (the rendering calls “fall through” to the default artisan).
Below are the data types most commonly used in the Artisan API.
Type Describes
AEGP_SoundDataH The audio settings used for a given layer.
HORZ? VERT?
After Effects’ matrix is row based; OpenGL’s is column based. This means more work for
you. Yay, billable hours!
An Artisan is nearly an application unto itself. Because we realized early in the After Effects
5.0 that there are many ways to approach the problems inherent in 3D rendering;
intersections and shading, for example. We provided an API with which we and third parties
(yes, we really do use our own APIs) could implement any 3D rendering scheme desired.
After Effects is not a 3D modeling application. Users work in a responsive mode, switching
to higher quality only at for proofing or final output. Consider providing at least two quality
modes, one for layout and another for final output. Be conscious of render time in low
quality mode.
REGISTERING AN ARTISAN
An Artisan is an AEGP, and has a single entry point. Artisans must also register their own
function entry points and have a special callback for this purpose. See
AEGP_RegisterArtisan() .
PR_ArtisanEntryPoints
global_setup_func0 Called only once, right after GP_Main. The global data is common across
all instances of the plug-in. If you allocate memory during Global Setup,
you must free it during your global_setdown_func.
*in_dataP,
PR_GlobalSetupFunc(
const PR_InData
PR_GlobalContextH global_contextH,
PR_GlobalDataH *global_dataPH);
setup_instance_func0 Allocate and instantiate any data specific to this instance of your Artisan.
PR_InstanceSetupFunc(
const PR_InData *in_dataP,
PR_GlobalContextH global_contextH,
PR_InstanceContextH instance_contextH,
PR_GlobalDataH global_dataH,
PR_InstanceFlags flags,
PR_FlatHandle flat_dataH0,
PR_InstanceDataH *instance_dataPH);
setdown_instance_func0 Deallocate and free any data specific to this instance of your Artisan.
PR_InstanceSetdownFunc(
const PR_InData *in_dataP,
PR_GlobalContextH global_contextH,
PR_InstanceContextH instance_contextH,
PR_GlobalDataH global_dataH,
PR_InstanceDataH instance_dataH);
PR_ArtisanEntryPoints
flatten_instance_func0 Flatten your data in preparation to being written to disk. (making sure it’s
OS independent, if your Artisan is).
PR_FlattenInstanceFunc(
const PR_InData *in_dataP,
PR_GlobalContextH global_contextH,
PR_InstanceContextH instance_contextH,
PR_GlobalDataH global_dataH,
PR_InstanceDataH instance_dataH,
PR_FlatHandle *flatH);
do_instance_dialog_func0 If your Artisan has a additional parameters (accessed through its Options
dialog), this function will be called to get and set them.
*in_dataP,
PR_DoInstanceDialogFunc(
global_contextH,
const PR_InData
instance_contextH,
PR_GlobalContextH
global_dataH,
PR_InstanceContextH
instance_dataH,
PR_GlobalDataH
PR_InstanceDataH
PR_DialogResult *resultP);
PR_DialogResultis either
PR_DialogResult_NO_CHANGE or
PR_DialogResult_CHANGE_MADE.
frame_setup_func0 Perform any setup necessary to render a frame (called immediately before
rendering).
PR_FrameSetupFunc(
const PR_InData *in_dataP,
PR_GlobalContextH global_contextH,
PR_InstanceContextH instance_contextH
PR_RenderContextH render_contextH,
PR_GlobalDataH global_dataH,
PR_InstanceDataH instance_dataH,
PR_RenderDataH *render_dataPH);
PR_ArtisanEntryPoints
render_func Render the scene.
PR_FrameRenderFunc(
const PR_InData *in_dataP,
PR_GlobalContextH global_contextH,
PR_InstanceContextH instance_contextH
PR_RenderContextH render_contextH,
PR_GlobalDataH global_dataH,
PR_InstanceDataH instance_dataH,
PR_RenderDataH render_dataH);
query_func0 Artisans can draw their own projection axes, should the need arise. After
Effects will call this function to obtain the transform between the
composition world and those axes, as well as for a number of other
functions related to on- and off-screen preview drawing (the former is
relevant only to interactive artisans).
PR_QueryFunc(
const PR_InData *in_dataP,
PR_GlobalContextH global_contextH,
PR_InstanceContextH instance_contextH
PR_QueryContextH query_contextH,
PR_QueryType query_type,
PR_GlobalDataH global_dataH,
PR_InstanceDataH instance_dataH);
PR_QueryType can be one of the following:
PR_QueryType_NONE = 0,
PR_QueryType_TRANSFORM,
PR_QueryType_INTERACTIVE_WINDOW_DISPOSE,
PR_QueryType_INTERACTIVE_WINDOW_CLEAR,
PR_QueryType_INTERACTIVE_WINDOW_FROZEN_PROXY,
PR_QueryType_INTERACTIVE_SWAP_BUFFER,
PR_QueryType_INTERACTIVE_DRAW_PROCS,
PR_QueryType_PREPARE_FOR_LINE_DRAWING,
PR_QueryType_UNPREPARE_FOR_LINE_DRAWING,
PR_QueryType_GET_CURRENT_CONTEXT_SAFE_FOR_LINE_DRAWING,
PR_QueryType_GET_ARTISAN_QUALITY
New in CS6.
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.
Function Purpose
AEGP_GetCompToRender Given the render context provided to the Artisan at render time, returns a
handle to the composition.
render_contextH,
AEGP_GetCompToRender(
PR_RenderContextH
AEGP_CompH *compPH)
AEGP_GetNumLayersToRender Given the render context, returns the number of layers the Artisan needs
to render.
render_contextH,
AEGP_GetNumLayersToRender(
PR_RenderContextH
A_long *num_to_renderPL)
AEGP_GetNthLayerContextTo Used to build a list of layers to render after determining the total number
Render of layers that need rendering by the Artisan.
render_contextH,
AEGP_GetNthLayerContextToRender(
PR_RenderContextH
A_long n,
AEGP_RenderLayerContextH*layer_indexPH)
AEGP_RenderLayerContextH layer_contextH,
const PR_RenderContextH render_contextH,
AEGP_LayerH *layerPH);
*layerPH,
AEGP_RenderLayerContextHlayer_contextH,
AEGP_LayerH
AEGP_SubLayerIndex *sublayerP);
Function Purpose
AEGP_GetTopLayerFromLayer With collapsed geometrics “on” this gives the layer in the root com-
Context position containing the layer context. With collapsed geometrics off
this is the same as AEGP_GetLayerFromLayerContext.
AEGP_GetTopLayerFromLayerContext(
AEGP_RenderLayerContextH l_contextH,
const PR_RenderContextH r_contextH,
AEGP_LayerH *layerPH);
AEGP_GetCompRenderTime Given the render context, returns the current point in (composition) time
to render.
render_contextH,
AEGP_GetNthLayerIndexToRender(
PR_RenderContextH
A_long *time,
A_long *time_step)
AEGP_GetCompDestination Given the render context, returns a buffer in which to place the final
Buffer rendered output.
render_contextH,
AEGP_GetCompToRender(
PR_RenderContextH
AEGP_CompH compH,
PF_EffectWorld *dst);
AEGP_GetROI Given the render context provided to the Artisan at render time, returns a
handle to the composition.
render_contextH,
AEGP_GetROI(
PR_RenderContextH
A_LegacyRect *roiPR);
Function Purpose
AEGP_RenderTexture Given the render context and layer, returns the layer texture. All
parameters with a trailing ‘0’ are optional; the returned
PF_EffectWorld can be NULL.
render_contextH,
AEGP_RenderTexture(
PR_RenderContextH
AEGP_LayerH layerH,
AEGP_RenderHints render_hints,
A_FloatPoint *suggested_scaleP0,
A_FloatRect *suggsted_src_rectP0,
A_Matrix3 *src_matrixP0,
PF_EffectWorld *render_bufferP);
AEGP_RenderHints contains one or more of the following:
AEGP_RenderHints_NONE
AEGP_RenderHints_IGNORE_EXTENTS
AEGP_RenderHints_NO_TRANSFER_MODE
AEGP_RenderHints_NO_TRANSFER_MODE prevents
application of opacity & transfer mode; for use with RenderLayer calls.
render_contextH,
AEGP_DisposeTexture(
PR_RenderContextH
AEGP_LayerH layerH,
AEGP_WorldH *dst0);
render_contextH,
AEGP_GetFieldRender(
PR_RenderContextH
PF_Field *field);
AEGP_ReportArtisan Given the render context provided to the Artisan at render time, returns a
Progress handle to the composition. Note: this is NOT thread-safe on Mac OS;
only use this function when the current thread ID is 0.
render_contextH,
AEGP_ReportArtisanProgress(
PR_RenderContextH
A_long countL,
A_long totalL);
Function Purpose
AEGP_IsBlankCanvas Determines whether the PR_RenderContextH is blank (empty).
render_contextH,
AEGP_IsBlankCanvas(
PR_RenderContextH
A_Boolean *is_blankPB);
AEGP_GetRenderLayerTo Given a render context and a layer (at a given time), retrieves the 4 by 4
WorldXform transform to move between their coordinate spaces.
AEGP_GetRenderLayerToWorldXform(
PR_RenderContextH render_contextH,
AEGP_RenderLayerContextH layer_contextH,
const A_Time *comp_timeP,
A_Matrix4 *transform);
AEGP_GetRenderOpacity Returns the opacity of the given layer context at the given time, within the
render context.
render_contextH,
AEGP_GetRenderOpacity(
AEGP_RenderLayerContextH layer_contextH,
PR_RenderContextH
AEGP_IsRenderLayerActive Returns whether or not a given layer context is active within the render
context, at the given time.
AEGP_IsRenderLayerActive(
AEGP_RenderLayerContextH layer_contextH,
PR_RenderContextH render_contextH,
AEGP_SetArtisan Sets the progress information for a rendering Artisan. countL is the
LayerProgress number of layers completed, num_layersL is the total number of
layers the Artisan is rendering.
AEGP_SetArtisanLayerProgress(
render_contextH,
countL,
PR_RenderContextH
A_long
A_long num_layersL);
Function Purpose
AEGP_RenderLayerPlus Similar to AEGP_RenderLayer, but takes into account the
AEGP_RenderLayerContextH.
AEGP_RenderLayerPlus(
layerH,
PR_RenderContextH r_contextH,
AEGP_RenderLayerContextH l_contextH,
AEGP_LayerH
AEGP_RenderHints render_hints,
AEGP_WorldH *bufferP);
rnder_contextH,
AEGP_GetTrackMatteContext(
fill_contextH,
PR_RenderContextH
AEGP_RenderLayerContextH
AEGP_RenderLayerContextH *mattePH);
render_contextH,
AEGP_RenderTextureWithReceipt(
AEGP_RenderLayerContextH layer_contextH,
PR_RenderContextH
render_hints,
*suggested_scaleP0,
AEGP_RenderHints
A_FloatPoint
*src_matrixP0,
A_FloatRect *suggest_src_rectP0,
A_Matrix3
AEGP_RenderReceiptH *receiptPH,
AEGP_WorldH *dstPH);
Function Purpose
AEGP_RenderLayerPlus An improvement over AEGP_RenderLayerPlus, this function
WithReceipt also provides an AEGP_RenderReceiptH for caching purposes.
AEGP_RenderLayerPlusWithReceipt(
layerH,
PR_RenderContextH render_contextH,
AEGP_RenderLayerContextH layer_contextH,
AEGP_LayerH
AEGP_RenderHints render_hints,
AEGP_NumEffectsToRenderType num_effectsS,
AEGP_RenderReceiptH *receiptPH,
AEGP_WorldH *bufferPH);
current_contextH,
AEGP_CheckRenderReceipt(
AEGP_RenderLayerContextH
PR_RenderContextH
current_lyr_ctxtH,
AEGP_RenderReceiptH old_receiptH,
A_Boolean check_aceB,
AEGP_NumEffectsToRenderType num_effectsS,
AEGP_RenderReceiptStatus
*receipt_statusP);
AEGP_RenderLayerContextH
PR_RenderContextH current_contextH,
current_lyr_contextH,
num_effectsS,
AEGP_NumEffectsToRenderType
AEGP_RenderReceiptH *render_receiptPH);
AEGP_GetNumBinsToRender Returns the number of bins After Effects wants the artisan to
render.
contextH,
AEGP_GetNumBinsToRender(
const PR_RenderContextH
A_long *num_binsPL);
Function Purpose
AEGP_SetNthBin Sets the given render context to be the n-th bin to be rendered by
After Effects.
A_long n);
AEGP_GetRenderLayer Retrieves the transform to correctly orient the layer being rendered
ToWorldXform2D3D with the output world. Pass TRUE for only_2dB to constrain the
transform to two dimensions.
render_contextH,
AEGP_GetRenderLayerToWorldXform2D3D(
AEGP_RenderLayerContextH layer_contextH,
PR_RenderContextH
*comp_timeP,
only_2dB,
const A_Time
A_Boolean
A_Matrix4 *transformP);
*scale_xPF,
const PR_RenderContextH
A_FpLong
A_FpLong *scale_yPF);
Function Purpose
AEGP_GetViewportOrigin Retrieves to origin of the source, within the frame (necessary to
translate between the two), for the given PR_RenderContextH.
contextH,
AEGP_GetViewportOrigin(
*origin_xPL,
const PR_RenderContextH
A_long
A_long *origin_yPL);
AEGP_GetViewportRect Retrieves the bounding rectangle for the area to be drawn, for the
given PR_RenderContextH.
contextH,
AEGP_GetViewportRect(
const PR_RenderContextH
A_LegacyRect *v_rectPR);
AEGP_GetFallowColor Retrieves the color used for the fallow regions in the given
PR_RenderContextH.
contextH,
AEGP_GetFallowColor(
const PR_RenderContextH
PF_Pixel8 *fallow_colorP);
Function Purpose
AEGP_ArtisanMustRender Determines whether or not the artisan must render the current
AsLayer AEGP_RenderLayerContextH as a layer.
AEGP_ArtisanMustRenderAsLayer(
const PR_RenderContextH contextH,
AEGP_RenderLayerContextH layer_contextH,
A_Boolean *use_txturePB);
Function Purpose
AEGP_MapCompToLayerTime New in CC. Unlike AEGP_ConvertCompToLayerTime, this
handles time remapping with collapsed or nested comps.
AEGP_MapCompToLayerTime(
PR_RenderContextH render_contextH,
AEGP_RenderLayerContextH layer_contextH,
const A_Time *comp_timePT,
A_Time *layer_timePT);
Convert between render and instance contexts, and manage global data specific to the
artisan.
Function Purpose
AEGP_GetGlobalContext Given an instance context, returns a handle to the global context.
FromInstanceContext
AEGP_GetGlobalContextFromInstanceContext(
const PR_InstanceContextH
instance_contextH,
PR_GlobalContextH
*global_contextPH);
AEGP_GetInstanceContext Given the render context, returns a handle to the instance context.
FromRenderContext
render_contextH,
AEGP_GetInstanceContextFromRenderContext(
const PR_RenderContextH
PR_InstanceContextH *instnc_ctextPH);
PR_InstanceContextH *instnce_contextPH);
Function Purpose
AEGP_GetRenderData Given a render context, returns the associated render data.
AEGP_GetRenderData(
const PR_RenderContextH render_contextH,
PR_RenderDataH *render_dataPH);
SMILE! CAMERAS
Obtains the camera geometry, including camera properties (type, lens, depth of field, focal
distance, aperture, et cetera).
Function Purpose
AEGP_GetCamera Given a layer handle and time, returns the current camera layer handle.
render_contextH,
AEGP_GetCamera(
PR_RenderContextH
const A_Time *comp_timeP,
AEGP_LayerH *camera_layerPH);
aegp_layerH,
AEGP_GetCameraType(
AEGP_LayerH
AEGP_CameraType *camera_typeP;
The camera type can be the following:
AEGP_CameraType_NONE = -1
AEGP_CameraType_PERSPECTIVE
AEGP_CameraType_ORTHOGRAPHIC
AEGP_GetDefaultCamera Given a composition handle, returns the camera distance to the image
DistanceToImagePlane plane.
AEGP_GetDefaultCamera
DistanceToImagePlane(
AEGP_CompH compH,
A_FpLong *dist_to_planePF)
AEGP_GetCameraFilmSize Retrieves the size (and units used to measure that size) of the film used by
the designated camera.
AEGP_GetCameraFilmSize(
camera_layerH,
AEGP_FilmSizeUnits *film_size_unitsP,
AEGP_LayerH
A_FpLong *film_sizePF0);
Function Purpose
AEGP_SetCameraFilmSize Sets the size (and unites used to measure that size) of the film used by the
designated camera.
AEGP_SetCameraFilmSize)(
camera_layerH,
AEGP_FilmSizeUnits film_size_units,
AEGP_LayerH
A_FpLong *film_sizePF0);
Camera orientation is in composition coordinates, and the rotations are in layer (the
camera’s layer) coordinates. If the camera layer has a parent, the position is in a coordinate
space relative to the parent.
Internally, we use composition width and height to set the matrix described by the OpenGL
specification as
The orthographic matrix describes the projection. The position of the camera is described by
another, scaled matrix. The inverse of the camera position matrix provides the “eye”
coordinates.
FOCUS ON FOCAL
Remember, focal length affects field of view; focal distance only affects depth of field.
FILM SIZE
In the real world, film size is measured in millimeters. In After Effects, it’s measured in
pixels. Multiply by 72 and divide by 25.4 to move from millimeters to pixels. Field of view is
more complex;
Function Purpose
AEGP_GetLightType Retrieves the AEGP_LightType of the specified camera
layer.
AEGP_GetLightType(
AEGP_LayerH light_layerH,
AEGP_LightType *light_typeP);
AEGP_LightType will be one of the following:
AEGP_LightType_PARALLEL
AEGP_LightType_SPOT
AEGP_LightType_POINT
AEGP_LightType_AMBIENT
The formula for parallel lights is found in Foley and Van Dam’s “Introduction to Computer
Graphics” (ISBN 0-201-60921-5) as is the formula for point lights. We use the half angle
variant proposed by Jim Blinn instead.
Suppose we have a point on a layer and want to shade it with the light. Let V be the unit
vector from the layer point to the eye point. Let L be the unit vector to the light (in the
parallel light case this is constant). Let H be (V+L)/2 (normalized). Let N be the unit normal
vector to the layer.The amount of specular reflected light is S * power(H Dot N,
shine), where S is the specular coefficient.
After Effects relies upon Artisans to draw 3D layer handles. If your Artisan chooses not to
respond to this call, the default Artisan will draw 3D layer handles for you. Querying
transforms is important for optimization of After Effects’ caching.
The coordinate system is positive x to right, positive y down, positive z into the screen. The
origin is the upper left corner. Rotations are x then y then z. For matrices the translate is the
bottom row, orientations are quaternions (which are applied first), then any x-y-z rotation
after that. As a general rule, use orientation or rotation but not both. Also use rotations if
you need control over angular velocity.
These functions give artisans information about the transforms they’ll need in order to
correctly place layers within a composition and respond appropriately to the various queries
After Effects will send to their PR_QueryFunc entry point function. As that entry point is
optional, so is your artisan’s response to the queries; however, if you don’t, your users may
be disappointed that (while doing interactive preview drawing) all the camera and light
indicators vanish, until they stop moving! Artisans are complex beasts; contact us if you have
any questions.
Function Purpose
AEGP_QueryXformGetSrcType Given a query context, returns trasnsform source currently being
modified.
query_contextH,
AEGP_QueryXformGetSrcType(
PR_QueryContextH
AEGP_QueryXformType *src_type);
The query context will be one of the following:
AEGP_Query_Xform_LAYER,
AEGP_Query_Xform_WORLD,
AEGP_Query_Xform_VIEW,
AEGP_Query_Xform_SCREEN
query_contextH,
AEGP_QueryXformGetDstType(
PR_QueryContextH
AEGP_QueryXformType *dst_type);
AEGP_QueryXformGetLayer Used if the source or destination type is a layer. Given a query context,
returns the layer handle.
query_contextH,
AEGP_QueryXformGetLayer(
PR_QueryContextH
AEGP_LayerH *layerPH);
Function Purpose
AEGP_QueryXformGetComp Given a query context, returns the current composition handle.
query_contextH,
AEGP_QueryXformGetComp(
PR_QueryContextH
AEGP_CompH *compPH);
AEGP_QueryXformGet Given a query context, returns the time of the associated view.
ViewTime
query_contextH,
AEGP_QueryXformGetViewTime(
PR_QueryContextH
A_Time *time);
AEGP_QueryXformGetCamera Given a query context, returns the current camera layer handle.
query_contextH,
AEGP_QueryXformGetCamera(
PR_QueryContextH
AEGP_LayerH *camera_layerPH);
query_contextH,
AEGP_QueryXformGetXform(
PR_QueryContextH
A_Matrix4 *xform);
AEGP_QueryXformSetXform Given a query context, return the matrix transform you compute in
xform.
query_contextH,
AEGP_QueryXformSetXform(
PR_QueryContextH
A_Matrix4 *xform);
AEGP_QueryWindowRef Sets the window reference to be used (by After Effects) for the
given PR_QueryContextH.
AEGP_QueryWindowRef(
PR_QueryContextH q_contextH,
AEGP_PlatformWindowRef *window_refP);
q_contextH,
AEGP_QueryWindowClear(
AEGP_PlatformWindowRef *window_refP,
PR_QueryContextH
A_LegacyRect *boundsPR);
Function Purpose
AEGP_QueryFrozenProxy Returns whether or not the textures used in the given
PR_QueryContextH should be frozen.
AEGP_QueryFrozenProxy(
PR_QueryContextH q_contextH,
A_Boolean *onPB);
AEGP_QueryDrawProcs Sets the interactive drawing functions After Effects will call while
drawing camera and lighting handles into the artisan’s provided
context.
AEGP_QueryDrawProcs(
PR_QueryContextH query_contextH,
PR_InteractiveDrawProcs *window_refP);
AEGP_QueryPrepareFor Informs After Effects about the context into which it will be
LineDrawing drawing.
AEGP_QueryPrepareForLineDrawing(
PR_QueryContextH query_contextH,
AEGP_PlatformWindowRef *window_refP,
A_LegacyRect *viewportP,
A_LPoint *originP,
A_FloatPoint *scaleP);
query_contextH,
AEGP_QueryUnprepareForLineDrawing(
PR_QueryContextH
AEGP_PlatformWindowRef *window_refP);
We’ve added the ability for artisans to provide functions After Effects can use to do basic
drawing functions for updating the comp window display during preview, including camera,
light, and wireframe preview modeling.
Function Purpose
x,
PR_Draw_MoveToFunc PR_Draw_MoveToFunc(
short
short y);
x,
PR_Draw_LineToFunc PR_Draw_LineToFunc(
short
short y);
PR_Draw_ForeColorFunc PR_Draw_ForeColorFunc(
const A_Color *fore_color);
PR_Draw_FrameRectFunc PR_Draw_FrameRectFunc(
const A_Rect *rectPR );
PR_Draw_PaintRectFunc PR_Draw_PaintRectFunc(
const A_Rect *rectPR );
9: AEIOs
AEIOs are AEGPs that perform media file import and/or export. AEIOs do everything for a
file of a given type that After Effects (or the plug-ins which ship with After Effects) would
normally do. On the import side, AEIOs can open existing files, manage file-specific
interpretation options, and provide audio and frames from the file to After Effects in
AEGP_SoundWorld and PF_EffectWorld format. Additionally, AEIOs can create files
interactively, asking users for the settings they’d like instead of reading them from a file. On
the export side, AEIOs can create and manage output options for render queue items, create
output files and save frames (provided by After Effects as PF_EffectWorlds) into those
files.
AEIOs work with uncompressed video with pixels in ARGB order from low to high-byte.
Pixels can be 8-bit, 16-bit, or 32-bit float per channel. AEIOs must handle their own
compression/decompression of any codecs supported.
AEIO, OR AEGP?
AEIOs provide pixels and audio data to After Effects. If you’re writing an importer/exporter
for a file format that represents timeline or project format (referencing file formats
supported by After Effects or other installed AEIOs), write an AEGP and add its command
to the Import/Export submenu.
After Effects supports MediaCore importer plug-ins. MediaCore is a set of shared libraries
that grew out of Premiere Pro; thus the MediaCore APIs are described in the Premiere Pro
SDK.
Only MediaCore importer plug-ins support an importer priority system: The highest priority
importer gets the first opportunity to import a file, and if the particular imported file isn’t
supported, the next-highest priority importer will then have the opportunity to try importing
it, and so on. MediaCore importers cannot defer file import to an AEIO. So if your goal is to
take over file handling for any file type for which After Effects already provides a plug-in,
you need to develop a MediaCore importer plug-in.
If the above constraints haven’t already answered whether you need to build an AEIO or
MediaCore importer, then you’ll likely want to build a MediaCore importer, which can be
used across the video and audio applications including Premiere Pro, Media Encoder,
Prelude, SpeedGrade, and Audition.
HOW IT WORKS
From within its entry point function, an AEIO populates a structure of function pointers
with the names of the functions it wants called in response to certain events. Many of these
function hooks are optional.
For many AEIO hook functions, you can ask After Effects to perform default processing
(this capability is noted in each hook’s descriptions). Unless you have compelling reasons to
do otherwise, return AEIO_Err_USE_DFLT_CALLBACK from the function, and let After
Effects do the work. This is also a good way to learn the calling sequence before beginning
implementation.
During your plug-in’s entry point function, populate a AEIO_ModuleInfo describing the
filetype(s) the AEIO supports, and an AEIO_FunctionBlock structure that points to your
file handling functions. For some of these functions, you can rely on After Effects’ default
behavior by returning AEIO_Err_USE_DFLT_CALLBACK. However, you must still provide a
function matching the required signature, that does so. Once you’ve filled out both these
structures, call AEGP_RegisterIO() .
In the AEIO_ModuleInfo that you pass in to the register call, you provide the file type and
description information that After Effects uses in the Import dialog, for the “Files of type”
drop-down on Windows, or the Enable drop-down on MacOS. As of CS6, file extensions
cannot be more than three characters long, even though we have a few built-in importers
with longer extensions.
INSPEC, OUTSPEC
CALLING SEQUENCE
As with all AEGPs, the entry point function exported in the plug-in’s PiPL is called during
launch. During this function, the AEIO must provide function pointers to required
functions and describe their capabilities, then pass the appropriate structures to
AEGP_RegisterIO() .
IMPORT
When users select a file in the file import dialog which is of a type handled by your AEIO,
its AEIO_VerifyFileImportable() function will be called; it’s called again for each
such file the user imports. AEIO_InitInSpecFromFile() will be called for each file;
parse the file, and use the various set functions to describe it to After Effects. Also,
construct any options data associated with the file, and save that data using
AEGP_SetInSpecOptionsHandle() . After Effects then calls the plug-in’s
AEIO_GetInSpecInfo() function, to get descriptive text about the file for display in the
project window. As noted in the description of this function, it may be called for folders as
well; we recommend that, if there is no valid options data for the file, you do nothing and
return no error (that’s what our AEIOs do).
AEIO_CountUserData() is then sent; if the AEIO indicates that there is user data
present, AEIO_GetUserData() will follow. After Effects will then request that the plug-in
draw a frame of video (for the project window thumbnail) by sending
AEIO_DrawSparseFrame() .
Once the supported file is added to a composition, user interaction will generate calls to
AEIO_DrawSparseFrame() and AEIO_GetSound() .
When the project is saved, and if there is options data associated with the AEIO_InSpec,
After Effects will send AEIO_FlattenOptions() during which the AEIO parses the
options data, and creates a representation of it that contains no references to external
memory. Likewise, the presence of any AEIO_OutSpec options data will result in
AEIO_GetFlatOutputOptions() being sent.
If the user adds an item to the render queue and chooses the AEIO’s supported output
format, AEIO_InitOutputSpec() will be sent. Use the various get functions to obtain
information about the output settings, and store any pertinent information using
AEGP_SetOutSpecOptionsHandle() , followed by
AEIO_GetFlatOutputOptions() . AEIO_GetDepths() is sent so After Effects can
determine what output pixel bit depths the AEIO supports.
AEIO_GetOutputInfo() is sent so that file name, type and subtype information can be
displayed in the output module details.
When the user clicks on the Format Options button, in the render queue,
AEIO_UserOptionsDialog() is called.
When the user actually clicks on the “Render” button, AEIO_SetOutputFile() will be
called, followed by AEIO_GetSizes() (your AEIO is responsible for determining whether
the destination has sufficient disk space available).
Before the video frames are sent, AEIO_StartAdding() is sent for the AEIO to open the
file handle and write out the file header. If the AEIO supports a video or audio format,
AEIO_AddSoundChunk() is sent for each audio chunk, and an AEIO_AddFrame() for
each video frame. If the AEIO supports sequences of still images, AEIO_OutputFrame()
is called repeatedly. After Effects sends a PF_EffectWorld representation of the frame to
be output. AEIO_WriteLabels() is called (for each frame) to give the plug-in a chance to
write out field and alpha interpretation information. AEIO_EndAdding() is sent when
there are no more frames (or audio) to be output. Close the output file.
This is the structure where your AEIO will define its basic properties. Notice that, in
addition to describing the filetypes and extensions supported by your AEIO, you also
describe your signature and behavior using the AEIO_ModuleFlags. We love flags.
create_kind The Mac OS four character code for files created by your
AEIO.
AEIOs set these flags (like effect plug-ins use global outflags) in AEIO_ModuleInfo.flags
to indicate their behavior to After Effects. Some flags are only relevant to input, and some
are only relevant to output.
AEIO_MFlag_ The AEIO will adopt the sequence options of its Input
SEQUENCE_OPTIONS_OK parent if a folder is selected.
AEIO_MFlag_INPUT_OPTIONS The AEIO has user options associated with each Input
input sequence. NOTE: the options information
must be flat (not referring to any data contained
in external pointers or handles).
AEIO_MODULEFLAGS2
AEIO_MFlag2_CAN_DRAW_FLOAT The AEIO can draw into float (32-bpc) worlds. Input
During its main entry point function, each AEIO plug-in must fill in an
AEIO_FunctionBlock, providing pointers to the functions After Effects will call for
different file-related tasks.
The table below shows which functions are needed for input, and which ones are needed for
output. For a bare-bones implementation, start with the functions that are noted as
“Required” in the right column. You can often invoke “best-case” behavior by having After
Effects handle the call for you (by returning AEIO_Err_USE_DFLT_CALLBACK).
For a barebones AEIO for video input only, implement the following functions:
AEIO_InitInSpecFromFile or AEIO_InitInSpecInteractive (depending on whether the
source is a file or interactively generated), AEIO_DisposeInSpec, AEIO_GetInSpecInfo,
AEIO_DrawSparseFrame, AEIO_CloseSourceFiles, and AEIO_InqNextFrameTime (using
AEIO_Err_USE_DFLT_CALLBACK is fine).
Starting from the IO sample, it is best to leave the other functions defined too, and fill them
in further as needed.
AEIO_InitInSpec- Using some form of user interaction (and not a file Input Yes, for
Interactive path provided by After Effects), describe the audio interactiv
and video your generated AEIO_InSpecH ely
contains. generated
media
AEIO_InitInSpecInteractive(
AEIO_BasicData *basic_dataP,
AEIO_InSpecH inH);
inH,
AEIO_BasicData *basic_dataP,
AEIO_InSpecH
A_Boolean *changed0);
inH,
AEIO_BasicData *basic_dataP,
*tr,
AEIO_InSpecH
const A_Time
A_LRect *extent);
inH,
AEIO_BasicData *basic_dataP,
AEIO_InSpecH
AEIO_Verbiage *verbiageP);
This function gets called OFTEN; every time we
refresh the project panel. Keep allocations to a
minimum. In the AEIOs that ship with After
Effects, we check for a valid optionsH (using
AEGP_GetInSpecOptionsHandle); if we find
one, we use the information from within it. If not,
we do nothing. This is important; if your AEIO
handles still images, this function will get called for
the folder containing the stills. Hopefully, there
won’t be an optionsH associated with it (unless
you’re writing a truly bizarre AEIO).
inH,
AEIO_BasicData *basic_dataP,
AEIO_InSpecH
AEIO_Quality qual,
const AEIO_RationalScale *rs0,
*duration0,
const A_Time *tr,
const A_Time
const A_Rect
*required_region0,
PF_EffectWorld *wP,
originy,
A_long* originx,
A_long*
AEIO_DrawingFlags
*draw_flagsP);
NOTE: return data as linear light (1.0), and After
Effects will perform any necessary transformations
to bring the footage into the working colorspace.
inH,
AEIO_BasicData *basic_dataP,
AEIO_InSpecH
A_Time *tr);
*basic_dataP,
AEIO_GetSound(
AEIO_BasicData
AEIO_InSpecH inH,
AEIO_SndQuality quality,
const AEIO_InterruptFuncs
*interrupt_funcsP0,
const A_Time *startPT,
const A_Time *durPT,
A_u_long start_sampLu,
A_u_long num_samplesLu,
void *dataPV);
AEIO_SndQuality may be:
AEIO_SndQuality_APPROX, (this quality is
used to draw the audio waveform)
AEIO_SndQuality_LO,
AEIO_SndQuality_HI
inH,
AEIO_BasicData *basic_dataP,
AEIO_InSpecH
time_dir,
const A_Time *base_time_tr,
AEIO_TimeDir
A_Boolean *found0,
A_Time *key_time_tr0);
outH,
AEIO_BasicData *basic_dataP,
AEIO_OutSpecH
A_Boolean *user_interacted);
NOTE: The first time your AEIO is used, After
Effects caches the last-known-good optionsH in
its preferences. When testing this function, delete
your preferences often.
outH,
AEIO_BasicData *basic_dataP,
AEIO_OutSpecH
AEIO_Handle *optionsH);
outH,
AEIO_BasicData *basic_dataP,
AEIO_OutSpecH
PF_EffectWorld *sample0,
A_Boolean
*interacted0);
outH,
AEIO_BasicData *basic_dataP,
AEIO_OutSpecH
A_UTF16Char *file_pathZ);
AEIO_StartAdding Prepare to add frames to the output file. This is a Output Yes, for
good time to create the ouput file(s) on disk, and to writing
write any header information to such files. This is formats
also your first opportunity to allocate pixel buffers that
based on valid output spec values. support
multiple
AEIO_StartAdding(
frames
outH,
AEIO_BasicData *basic_dataP,
AEIO_OutSpecH
A_long flags);
AEIO_AddFrame Add frame(s) to output file. You may pass a pointer Output Yes, for
to a function you want called if the user interrupts writing
the render. formats
that
AEIO_AddFrame(
support
AEIO_BasicData *basic_dataP,
multiple
AEIO_OutSpecH outH,
frames
A_long frame_index,
A_long frames,
PF_EffectWorld *wP,
const A_LPoint *origin0,
A_Boolean was_compressedB,
AEIO_InterruptFuncs *inter0);
AEIO_EndAdding Perform any clean-up associated with adding frames. Output Yes, for
writing
AEIO_EndAdding(
formats
AEIO_BasicData *basic_dataP,
that
AEIO_OutSpecH outH,
support
A_long flags);
multiple
frames
AEIO_Flush Destroy any options or user data associated with the Output Yes
OutSpecH.
AEIO_Flush(
AEIO_BasicData *basic_dataP,
AEIO_OutSpecH outH);
AEIO_Add- Add the given sound to the output file. Output Yes, for
SoundChunk writing
AEIO_AddSoundChunk(
formats
outH,
AEIO_BasicData *basic_dataP,
with
AEIO_OutSpecH
audio
const A_Time *start,
AEIO_SndWorldH swH);
outH,
AEIO_BasicData *basic_dataP,
AEIO_OutSpecH
AEIO_OptionsFlags *which);
outH,
AEIO_BasicData *basic_dataP,
AEIO_OutSpecH
A_char *suffix);
inH,
AEIO_BasicData *basic_dataP,
AEIO_InSpecH
A_Boolean *interactedPB);
AEIO_GetNum- Enumerate the auxiliary (beyond red, green, blue and Input No
AuxChannels alpha) channels of data contained in an
AEIO_InSpecH.
AEIO_GetNumAuxChannels(
AEIO_BasicData *basic_dataP,
AEIO_InSpecH inH,
A_long *num_channelsPL);
*basic_dataP,
AEIO_GetAuxChannelDesc(
AEIO_BasicData
AEIO_InSpecH inH,
long chan_indexL,
PF_ChannelDesc *descP);
AEIO_GetNth- Retrieve data from the nth auxiliary file, for the Input No, if no
AuxFileSpec specified frame. The path is a handle to a NULL- aux files
terminated A_UTF16Char string, and must be
disposed with AEGP_FreeMemHandle.
AEIO_GetNthAuxFileSpec(
AEIO_BasicData *basic_dataP,
frame_numL,
AEIO_InSpecH seqH,
A_long
A_long n,
AEGP_MemHandle *pathPH);
AEIO_Close- Close (or open, depending upon closeB) the Input Yes
SourceFiles source files for an AEIO_InSpecH. When the user
Collects Files, the AEIO will first be asked to close
its source files, then re-open them.
AEIO_CloseSourceFiles(
AEIO_BasicData *basic_dataP,
AEIO_InSpecH seqH,
A_Boolean closeB);
TRUE for close, FALSE for open.
AEIO_SetUserData Set user data (of the given index and type) for the Output No
given AEIO_OutSpecH.
AEIO_SetUserData(
AEIO_BasicData *basic_dataP,
AEIO_OutSpecH outH,
A_u_long typeLu,
A_u_long indexLu,
const AEIO_Handle dataH);
AEIO_GetUserData Describe the user data (at the index and of the type Input No
given) associated with the AEIO_InSpecH.
*basic_dataP,
AEIO_GetUserData(
AEIO_BasicData
AEIO_InSpecH inH,
A_u_long typeLu,
A_u_long indexLu,
A_u_long max_sizeLu,
AEIO_Handle *dataPH);
AEIO_MarkerType marker_type,
A_long
void *marker_dataPV,
AEIO_InterruptFuncs
*inter0);
AEIO_ModuleSignature
AEIO_BasicData *basic_dataP,
sig,
const A_UTF16Char
*file_pathZ,
A_Boolean *importablePB);
outH,
AEIO_BasicData *basic_dataP,
AEIO_OutSpecH
A_Boolean *interacted0);
*basic_dataP,
AEIO_AddMarker3(
AEIO_BasicData
AEIO_OutSpecH outH,
A_long frame_index,
AEGP_ConstMarkerValP marker_valP,
AEIO_RenderMarkerFlag marker_flag,
AEIO_InterruptFuncs *inter0);
AEIO_GetMimeType Describe the output mime type. This is used for Output No
XMP support.
AEIO_GetMimeType(
AEIO_BasicData *basic_dataP,
AEIO_OutSpecH outH,
A_long mime_type_sizeL,
char *mime_typeZ);
These functions manage an input specification, After Effects’ internal representation of data
gathered from any source. Any image or audio data in After Effects (except solids) is
obtained from an input specification handle, or AEIO_InSpecH
AEGP_SetInSpecOptionsHandle Sets the options data for the given AEIO_InSpecH. Must
be allocated using the MemorySuite.
AEGP_SetInSpecOptionsHandle(
AEIO_InSpecH inH,
void *optionsPV,
void **old_optionsPPV);
AEGP_GetInSpecFilePath Retrieves the file path for the AEIO_InSpecH. The file
path is a handle to a NULL-terminated A_UTF16Char
string, and must be disposed with
AEGP_FreeMemHandle.
AEGP_GetInSpecFilePath(
AEIO_InSpecH inH,
AEGP_MemHandle *file_nameZ);
AEGP_GetInSpecSize Retrieves the size (in bytes) of the data referenced by the
AEIO_InSpecH.
AEGP_GetInSpecSize(
AEIO_InSpecH inH,
AEIO_FileSize *sizePLLu);
AEGP_SetInSpecSize Indicates to After Effects the size (in bytes) of the data
referenced by the AEIO_InSpecH.
AEGP_SetInSpecSize(
AEIO_InSpecH inH,
AEIO_FileSize sizeL);
AEGP_GetInSpecDimensions Retrieves the width and height of the image data in the
AEIO_InSpecH.
AEGP_GetInSpecDimensions(
AEIO_InSpecH inH,
A_long *widthPL0,
A_long *heightPL0);
AEGP_SetInSpecDimensions Indicates to After Effects the width and height of the image
data in the AEIO_InSpecH.
AEGP_SetInSpecDimensions(
AEIO_InSpecH inH,
A_long widthL,
A_long heightL);
AEGP_SetInSpecSoundRate Sets the sampling rate (in samples per second) for the audio
data referenced by the AEIO_InSpecH.
AEGP_SetInSpecSoundRate(
AEIO_InSpecH inH,
A_FpLong rateF);
AEGP_ClearInSpecNativeStart- New in CC. Clear the native start time of the footage.
Time Setting the native start time to 0 using
AEGP_SetInSpecNativeStartTime doesn't do this.
It still means there is a special native start time provided.
AEGP_ClearInSpecNativeStartTime(
AEIO_InSpecH inH);
These functions manage all interactions with an output specification in After Effects’ render
queue.
AEGP_GetOutSpecFilePath Obtains the path for the AEIO_OutSpecH. The file path is
a handle to a NULL-terminated A_UTF16Char string, and
must be disposed with AEGP_FreeMemHandle.
If file_rsrvdPB returns TRUE, the plug-in should not
overwrite it (After Effects has already created an empty file);
doing so can cause network renders to fail.
AEGP_GetOutSpecFilePath(
AEIO_OutSpecH outH,
AEGP_MemHandle *unicode_pathPH,
A_Boolean *file_rsrvdPB););
IMPLEMENTATION DETAILS
EXPORT BIT-DEPTH
In the Output Module Settings, the user can choose a Depth based on the options the AEIO
declares support for in AEIO_GetDepths() . If a plug-in supports higher bit-depth
exports, it should be able to handle these higher bit-depth PF_EffectWorlds passed in
AEIO_AddFrame() or AEIO_OutputFrame() , even when the export setting is not set to
the same depth. The frame delivered to the AEIO, and the final output will not necessarily
be the same depth. You may get frames passed in the project bit-depth instead of the final
output if After Effects thinks that will be higher quality.
It’s possible to use either user data allocations or options handles to store metadata about a
file. We use user data for information that’s to be embedded in the file (presuming the file
format supports such information); marker data, field labels, etc. We use option handles for
information about the file; output settings, dimensions, details of compression settings used.
Both Premiere Pro and Premiere Elements set PF_InData>appl_id to ‘PrMr’. In this
chapter, we will describe the AE API support in Premiere Pro, but generally the same
support exists in corresponding versions of Premiere Elements. If you need to distinguish
between Premiere Pro and Premiere Elements, you may use the Premiere-specific App Info
Suite, available from the Premiere Pro SDK headers.
PF_InData> PF_InData>
Application Versions
version.major version.minor
Premiere Pro CC and Premiere Pro CC 2014 13 4
Note that the versioning used by Premiere Pro and Premiere Elements does not mean that
they support the same API features After Effects did at the same version. It is simply meant
to distinguish from one version to the next.
Use the common plug-in folder as described here. If you try to install an effect plug-in only
to the Premiere Pro plug-ins directory, you will be surprised to find that your effect is not
rendered when you export to disk through Adobe Media Encoder, an entirely separate
application. Oh, and you’ll also miss out on project interchange and copy / paste between
Premiere Pro and After Effects.
PLUG-INS... RELOADED
On it’s first launch, Premiere Pro loads all the plug-ins, reads the PiPL, and sends
PF_Cmd_GLOBAL_SETUP to determine the plug-ins’ capabilities. To save time on future
application launches, it saves some of these capabilities in what we call the plug-in cache (the
registry on Windows, a Property List file on Mac OS). The next time the application is
launched, the cached information is used wherever possible, rather than loading the plug-ins.
When debugging, you can always force a reload of all the plug-ins by holding down the Shift
key when launching Premiere Pro.
If your effect needs to be reloaded each time, there is a way to disable this caching. The plug-
in can use the PF Cache On Load Suite in AE_CacheOnLoadSuite.h (from the Premiere
Pro SDK headers) to call PF_SetNoCacheOnLoad() during PF_Cmd_GLOBAL_SETUP. For
the second parameter of that function, pass a non-zero value if you want your effect to show
up in the UI. Pass zero if loading failed, but you still want Premiere Pro to attempt to load
it again on the next relaunch.
We’ve tried to provide robust compatibility for After Effects effect plug-ins in Premiere Pro.
There are underlying differences in the render pipeline that lead to differences, and we
realize the API implementation may not be perfect. If you run into anomalous or just plain
confusing behavior, please let us know. Below is an overview of some differences you will
notice the first time you install your AE effect into PPro and apply it to a clip.
TIME
Premiere Pro uses slightly different time values in PF_InData. For example in CS4:
Rendering in PAL, time_scale is 50, time_step is 1, field gives field order (in After
Effects, for field rendering, scale is 3200, step is 64, or for progressive rendering, scale is
3200, step is 128.
It's the ratio of time-related values that produces the time value, not specifically the
time_scale value. It's possible Premiere Pro will use different time_scales in the future,
so please don't hard code. Just be aware that it does not necessarily use the exact same values
as After Effects.
FRAME DIMENSIONS
Differences between source footage and the project/composition are handled differently. For
example, in CS4, when importing an NTSC clip in a PAL sequence,
PF_InData>width,height are (598,480) and PF_InData->pixel_aspect_ratio is
(768,702). In AE, width,height are (720,480) and pixel_aspect_ratio is (10,11).
PF_INDATA
Premiere Pro handles field rendering differently than After Effects. While field rendering,
PF_InData>field gives the current field being rendered, ignoring whether or not
PF_OutFlag_PIX_INDEPENDENT flag was set.
In Premiere Pro, effects receive the quality setting of the monitor window in
PF_InData>quality . This differs from After Effects, where the source layer’s quality
setting is provided here.
PARAMETER UI
Many suites supported by After Effects are not implemented in the Premiere Pro host. In
several cases, even if a suite is missing in Premiere Pro, an equivalent macro function is
available. Here are a few examples:
WorldTransformSuite1()->convolve() in_data->utils->convolve()
FillMatteSuite2()->fill() PF_FILL()
PF_PixelDataSuite1->get_pixel_data8() PF_GET_PIXEL_DATA8()
The sample projects demonstrate alternate ways of handling a missing suite, by checking for
the host application and version. The Portable sample project demonstrates both host
application and version checking.
No AEGP calls are supported by Premiere Pro. However, there are some interesting
parallels in the header PrSDKAESupport.h. For example, you can use the Utility Suite in
that header to get the frame rate or field type of the source footage, or to get the speed
applied to the clip.
Note that other suites from the Premiere Pro SDK cannot be used in AE effects.
MULTITHREADING
Premiere Pro was built to provide real-time playback of footage with effects wherever
possible. The render scheduling is much more aggressive and multithreaded rendering is a
basic requirement. This is quite different than After Effects, where users are building layers
upon layers of effects and more willing to wait for a RAM preview.
Therefore, an effect should not expect to receive render requests in order of increasing time.
Also, effects should not depend on static, non-constant variables.
When the flag is set, we don't clone the sequence data across all the threads and we only call
into the plug-in on one thread at a time. Premiere Pro will still render using multiple
threads, but the effect will only render on one thread at a time, and the same sequence data
will be used. This flag is useful for plug-ins that provide their own internal multithreading,
or plug-ins that render frames based on previous frames, such as image stabilizers.
BIGGER DIFFERENCES
As long as an effect only supports the basic ARGB_8u pixel format supported by After
Effects, Premiere Pro will try to imitate the After Effects hosting behavior and hide various
differences because of the different render pipeline architecture. But if an effect wants to
support additional pixel formats, such as 32-bit RGB, be prepared to handle further
divergent behavior.
When rendering native pixel formats, Premiere will send PF_Cmd_RENDER once for each
field, rather than for each frame. The PF_InData->field will indicate which field is being
rendered, the PF_LayerDef->height will be half of the frame height, and the
PF_LayerDef->rowbytes will be double the normal value.
PIXEL FORMATS
Premiere Pro provides function suites for declaring support for pixel formats other than the
8-bit RGB format used by After Effects - ARGB_8u. These pixel formats include the
Premiere Pro native 8-bit RGB format - BGRA_8u, as well as YUV, 32-bit formats, and
more. For a more detailed discussion of the various pixel formats, see the Premiere Pro SDK
Guide, chapter 3, in the section “Pixel Formats and Colorspaces”.
After Effects functions such as PF_BLEND() have not been enhanced to work with pixel
formats beyond 8-bit RGB.
Premiere Pro does not support After Effects 16-bit rendering or SmartFX. For 32-bit
rendering in Premiere Pro, you’ll need to declare support for one of the 32-bit pixel formats
(see previous section), and then implement 32-bit rendering for PF_Cmd_RENDER. You can
support multiple render depths this way. See the SDK Noise sample project for an example.
Depending on the clip(s) to which an effect is applied, 32-bit processing is not always
necessary to preserve the quality of the source input. But there are settings to force 32-bit
rendering, to give effects processing finer granularity and more headroom, if desired. Go to
Settings>Sequence Settings> Video Previews>Maximum Bit Depth, to control previewing
from the timeline. For export to file, use Export Settings>Video>Basic Settings>Render at
Maximum Depth.
Before CS6, PF_CHECKOUT_PARAM() only returned 8-bit ARGB buffers, regardless of the
pixel format currently being used for rendering. Starting in CS6, an effect can opt in to get
frames in the same format as the render request, whether it is 32-bit float, YUV, etc.
Plug-ins may request this behavior, but existing plug-ins will continue working receiving 8-
bit ARGB frames. The call is EffectWantsCheckedOutFramesToMatch
RenderPixelFormat(), in the PF Utility Suite, defined in PrSDKAESupport.h. The call
should be made on PF_Cmd_GLOBAL_SETUP, the same selector where an effect would
already advertise support beyond 8-bit RGB using AddSupportedPixelFormat().
EFFECTS PRESETS
Premiere Pro uses a different preset scheme than After Effects. From the Premiere Pro SDK
Guide:
Effect presets appear in the Presets bin in the Effects panel, and can be applied just like
Effects with specific parameter settings and keyframes. Effect presets can be created as
follows:
While this is logged as bug #1235407, there is a simple workaround: Create two separate
parameters, and have the custom UI control the slider param using parameter supervision.
PREMIERE ELEMENTS
Premiere Elements (but not Premiere Pro) displays visual icons for each effect. You will
need to provide icons for your effects, or else an empty black icon will be shown for your
effects, or even worse behavior in Premiere Elements 8. The icons are 60x45 PNG files, and
are placed here:
The filename should be the match name of the effect, which you specify in the PiPL,
prefixed with “AE.” So if the match name was “ MatchName”, then the filename should be
“ AE.MatchName.png”
UNSUPPORTED FEATURES
Premiere Pro is currently known to not support the following features of the After Effects
API:
(If you would like a feature with a "-" bullet, please email Premiere Pro API Engineering
with the feature request. Numbers preceded by an ‘F’ are feature request numbers, and the
others are bug numbers)
Premiere Pro attempts to load AEGP plug-ins. To detect this and avoid any problem
behavior, your command hook function can access a suite which is only provided by After
Effects; AEGP_CanvasSuite is a fine candidate. If the suite isn’t present, return an error.
The plug-in will be placed on Premiere Pro’s “don’t load these” list.
OTHER HOSTS?
“Adobe neither supports nor recommends the creation of Adobe-compatible third-party hosts.
While it may be possible to create a partially functional host by reverse engineering from the plug-
in API specification, we do not recommend it and will not support you in doing so.”
REALITY SANDWICH
We realize that, for developers like you, one good way to grow your market is to ensure that
your plug-ins work in as many hosts as possible. Our SmartFX API has created quite a bit of
distance between the After Effects API and the implementations available in the rest of the
plug-in hosting world. We will do what we can to help the other hosts support newer
features. If you encounter problems in third party hosts, please refer them to us if they need
assistance.
AEFX_CLR_STRUCT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .70
AEGP_StreamSuite1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .235
area . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .156
Audio-specific Float Slider Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .175
cbs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .155
cmd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .48
continue_refcon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .157
current_frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .156
data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .79
Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .176
depth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .157
Draw Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .157
effect_win . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .155
evt_in_flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .155
evt_out_flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .155
extent_hint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .79
flat_sdata_size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .61
frame_data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .61
GET_LAYER2COMP_XFORM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .172
global_data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .61
Graphics Utility Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .98
height . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61, 79
HLS pixel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .135
in_data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .48
index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .156
last_time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .157
luminance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .136
modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .157
my_version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .61
name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .61
num_clicks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .157
num_params . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .61
origin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .61
out_data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .49
out_flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .61
param_title_frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .156
Parameter supervision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .108
Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .61
PF_ABORT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .100
PF_ADD_PARAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .69
PF_Arbitrary_FLAT_SIZE_FUNC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .116
PF_Arbitrary_INTERP_FUNC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .117
PF_Arbitrary_PRINT_SIZE_FUNC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .117
PF_CHECKIN_LAYER_AUDIO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .103
PF_CHECKIN_PARAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .102
return_msg . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61, 63
rowbytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .79
screen_point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .157
send_drag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .157
update_rect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .157
when . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .157
width . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61, 79
world_flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .79