├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── docs ├── CNAME ├── _global │ ├── .gitignore │ ├── css │ │ ├── global-syntax-highlight.css │ │ └── global.css │ ├── hooks │ │ ├── inline_pre_to_code_fence.py │ │ └── merge_inherited_config.py │ ├── js │ │ └── global.js │ ├── mkdocs.yml │ ├── overrides │ │ ├── 404.html │ │ ├── main.html │ │ ├── partials │ │ │ ├── copyright.html │ │ │ └── toc-item.html │ │ └── templates │ │ │ ├── print_site_banner.tpl │ │ │ └── print_site_cover_page.tpl │ ├── readme.md │ ├── requirements.txt │ └── scripts │ │ └── update-common-components.py ├── _static │ ├── AE_Log.png │ ├── Unlock.png │ ├── appleclang-symbols.png │ ├── debugmonitor.png │ ├── extra.css │ └── mac_universal_build.png ├── aegps │ ├── aegp-details.md │ ├── aegp-suites.md │ ├── aegps.md │ ├── cheating-effect-usage-of-aegp-suites.md │ ├── data-types.md │ ├── implementation.md │ └── overview.md ├── aeios │ ├── AEIO_ModuleInfo.md │ ├── aeios.md │ ├── calling-sequence.md │ ├── implementation-details.md │ └── new-kids-on-the-function-block.md ├── artisans │ ├── artisan-data-types.md │ └── artisans.md ├── audio │ ├── accessing-audio-data.md │ ├── audio-considerations.md │ ├── audio-data-structures.md │ ├── audio-specific-float-slider-variables.md │ ├── audio.md │ └── global-outflags.md ├── effect-basics │ ├── PF_EffectWorld.md │ ├── PF_InData.md │ ├── PF_OutData.md │ ├── PF_ParamDef.md │ ├── command-selectors.md │ ├── effect-basics.md │ ├── entry-point.md │ ├── errors.md │ └── parameters.md ├── effect-details │ ├── accessing-camera-light-information.md │ ├── accessing-function-suites.md │ ├── arbitrary-data-parameters.md │ ├── changing-parameter-orders.md │ ├── color-space-conversion.md │ ├── compute-cache-api.md │ ├── effect-details.md │ ├── global-sequence-frame-data.md │ ├── graphics-utility-suites.md │ ├── image-buffer-management-functions.md │ ├── interaction-callback-functions.md │ ├── iteration-suites.md │ ├── memory-allocation.md │ ├── motion-blur.md │ ├── multi-frame-rendering-in-ae.md │ ├── parameter-supervision.md │ ├── parameters-floating-point-values.md │ ├── pixel-aspect-ratio.md │ ├── tips-tricks.md │ ├── useful-utility-functions.md │ └── working-with-paths.md ├── effect-ui-events │ ├── PF_EventExtra.md │ ├── PF_EventUnion.md │ ├── custom-ui-and-drawbot.md │ ├── effect-ui-events.md │ ├── tips-and-tricks.md │ └── ui-callbacks.md ├── history.md ├── index.md ├── intro │ ├── apple-silicon-support.md │ ├── compatibility-across-multiple-versions.md │ ├── debugging-plug-ins.md │ ├── exceptions.md │ ├── how-to-start-creating-plug-ins.md │ ├── localization.md │ ├── next-steps.md │ ├── other-integration-possibilities.md │ ├── pipl-resources.md │ ├── sample-projects.md │ ├── sdk-audience.md │ ├── symbol-export.md │ ├── third-party-plug-in-hosts.md │ ├── what-can-i-do.md │ ├── whats-new.md │ └── where-installers-should-put-plug-ins.md ├── ppro │ ├── basic-host-differences.md │ ├── bigger-differences.md │ ├── multithreading.md │ ├── other-hosts.md │ ├── plug-in-installation.md │ ├── plug-ins-reloaded.md │ ├── ppro.md │ ├── premiere-elements.md │ └── unsupported-features.md └── smartfx │ └── smartfx.md ├── mkdocs.yml ├── readme.md └── requirements.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Override linguist skipping main folder 2 | docs/** -linguist-documentation 3 | docs/** linguist-detectable 4 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - main 8 | permissions: 9 | contents: write 10 | jobs: 11 | deploy: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | - name: Configure Git Credentials 18 | run: | 19 | git config user.name github-actions[bot] 20 | git config user.email 41898282+github-actions[bot]@users.noreply.github.com 21 | 22 | - uses: actions/setup-python@v5 23 | with: 24 | python-version: 3.x 25 | 26 | - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV 27 | 28 | - uses: actions/cache@v4 29 | with: 30 | key: mkdocs-material-${{ env.cache_id }} 31 | path: .cache 32 | restore-keys: | 33 | mkdocs-material- 34 | 35 | - name: Install Python dependencies 36 | uses: py-actions/py-dependency-install@v4 37 | 38 | - run: mkdocs gh-deploy --force 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.sublime-project 2 | *.sublime-workspace 3 | .DS_Store 4 | .vscode/ 5 | __pycache__/ 6 | site/ 7 | venv/ 8 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | ae-plugins.docsforadobe.dev 2 | -------------------------------------------------------------------------------- /docs/_global/.gitignore: -------------------------------------------------------------------------------- 1 | *.sublime-project 2 | *.sublime-workspace 3 | .DS_Store 4 | .vscode/ 5 | __pycache__/ 6 | site/ 7 | venv/ 8 | -------------------------------------------------------------------------------- /docs/_global/css/global-syntax-highlight.css: -------------------------------------------------------------------------------- 1 | /* Set light & dark mode syntax highlight */ 2 | 3 | @media screen { 4 | /* Light mode */ 5 | [data-md-color-scheme="default"] { 6 | --md-code-fg-color: #36464e; 7 | --md-code-bg-color: #f5f5f5; 8 | --md-code-hl-color: #4287ff; 9 | 10 | --md-code-hl-constant-color: #6e59d9; 11 | --md-code-hl-function-color: #a846b9; 12 | --md-code-hl-keyword-color: #3f6ec6; 13 | --md-code-hl-number-color: #d52a2a; 14 | --md-code-hl-special-color: #db1457; 15 | --md-code-hl-string-color: #1c7d4d; 16 | --md-code-hl-comment-color: var(--md-default-fg-color--light); 17 | --md-code-hl-generic-color: var(--md-default-fg-color--light); 18 | --md-code-hl-name-color: var(--md-code-fg-color); 19 | --md-code-hl-operator-color: var(--md-default-fg-color--light); 20 | --md-code-hl-punctuation-color: var(--md-default-fg-color--light); 21 | --md-code-hl-variable-color: var(--md-default-fg-color--light); 22 | } 23 | 24 | /* Dark mode */ 25 | [data-md-color-scheme="slate"] { 26 | --md-code-bg-color: #272a35; 27 | --md-code-fg-color: #d5d8e2d1; 28 | --md-code-hl-color: #2977ff; 29 | 30 | --md-code-hl-constant-color: #9383e2; 31 | --md-code-hl-function-color: #c973d9; 32 | --md-code-hl-keyword-color: #6791e0; 33 | --md-code-hl-number-color: #e6695b; 34 | --md-code-hl-special-color: #f06090; 35 | --md-code-hl-string-color: #2fb170; 36 | --md-code-hl-comment-color: var(--md-default-fg-color--light); 37 | --md-code-hl-generic-color: var(--md-default-fg-color--light); 38 | --md-code-hl-name-color: var(--md-code-fg-color); 39 | --md-code-hl-operator-color: var(--md-default-fg-color--light); 40 | --md-code-hl-punctuation-color: var(--md-default-fg-color--light); 41 | --md-code-hl-variable-color: var(--md-default-fg-color--light); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /docs/_global/css/global.css: -------------------------------------------------------------------------------- 1 | /* 2 | Fix issue with 'code' text in tables wrapping to multiple lines 3 | Excludes any preformatted code blocks within tables 4 | */ 5 | td code:not(.md-code__content) { 6 | white-space: nowrap; 7 | } 8 | -------------------------------------------------------------------------------- /docs/_global/hooks/inline_pre_to_code_fence.py: -------------------------------------------------------------------------------- 1 | # Converts inline
code
blocks to pygments-highlighted html 2 | # Custom hook to highlight and format
code
code
blocks 3 | # 4 | # This is used for
 blocks embedded in tables, as these otherwise are skipped by pygments
 5 | #
 6 | # Note: It's possible this can be done better with Python-markdown inline patterns (https://python-markdown.github.io/reference/markdown/inlinepatterns),
 7 | #   but the below works For Now
 8 | 
 9 | import re
10 | import markdown
11 | 
12 | import mkdocs
13 | from mkdocs.structure.pages import Page
14 | from mkdocs.config.defaults import MkDocsConfig
15 | from mkdocs.structure.files import Files
16 | 
17 | from pymdownx.highlight import HighlightExtension
18 | 
19 | # Get current mkdocs config
20 | user_extensions = MkDocsConfig.markdown_extensions.__dict__.get('configdata');
21 | highlight_config = dict()
22 | 
23 | if 'pymdownx.highlight' in user_extensions:
24 |     highlight_config = user_extensions.get('pymdownx.highlight')
25 | 
26 | ExistingHighlighter = HighlightExtension().get_pymdownx_highlighter()(**highlight_config)
27 | 
28 | def on_page_content(html: str, page: Page, config: MkDocsConfig, files: Files, **kwargs):
29 |     def inline_pre_to_code_fence(match):
30 |         raw = match.group()
31 | 
32 |         ## Check for language
33 |         lang = ''
34 |         langmatch = re.search('lang="(.*?)"', raw)
35 | 
36 |         if langmatch:
37 |             lang = langmatch.group(1)
38 | 
39 |         ## Remove first tag
40 |         pre = re.sub('', '', raw)
41 | 
42 |         ## Strip end tag
43 |         pre = re.sub('
', '', pre) 44 | 45 | ## Swap html linebreaks 46 | pre = re.sub('
', '\n', pre) 47 | 48 | return ExistingHighlighter.highlight(pre, lang) 49 | 50 | result = re.sub('(.+)', inline_pre_to_code_fence, html) 51 | 52 | return result 53 | -------------------------------------------------------------------------------- /docs/_global/hooks/merge_inherited_config.py: -------------------------------------------------------------------------------- 1 | # Handles merging mkdocs config in a way the native inheritance feature doesn't quite cover 2 | # 3 | # This relies on a key in "extra.overrides" 4 | # Valid keys are `custom_dir: str` and `hooks: [-path/to.py, -path/to.py]`, e.g. 5 | # 6 | # ```yml 7 | # extra: 8 | # overrides: 9 | # custom_dir: overrides 10 | # extra_css: 11 | # - docs/_global/css/global.css 12 | # - docs/_global/css/global-syntax-highlight.css 13 | # extra_javascript: 14 | # - docs/_global/js/global.js 15 | # hooks: 16 | # - hooks/local_override.py 17 | # - hooks/local_override2.py 18 | # not_in_nav: 19 | # - gitignore_style/path/to/exclude 20 | # theme_features: 21 | # - theme.feature1 22 | # - theme.feature2 23 | # ``` 24 | 25 | import os 26 | 27 | from pathspec.gitignore import GitIgnoreSpec 28 | 29 | import mkdocs 30 | from mkdocs.config.defaults import MkDocsConfig 31 | from mkdocs.config.config_options import (File, FilesystemObject, Hooks, ListOfItems, PathSpec) 32 | from mkdocs.structure.files import (File as FileStructure, Files) 33 | 34 | # Load any local files into mkdocs 35 | def append_local_files(files: Files, config: MkDocsConfig, local_files: list[str]): 36 | for local_file_path in local_files: 37 | local_file = FileStructure( 38 | path= local_file_path, 39 | src_dir=config["docs_dir"] + "/../", 40 | dest_dir=config["site_dir"], 41 | use_directory_urls=False, 42 | ) 43 | 44 | files.append(local_file) 45 | 46 | # Load any override hooks 47 | def merge_local_hooks(config: MkDocsConfig, hooks: list[str]): 48 | try: 49 | paths = ListOfItems(File(exists=True)).validate(hooks) 50 | except Exception as e: 51 | raise e 52 | 53 | for name, path in zip(hooks, paths): 54 | config.plugins[name] = Hooks._load_hook(mkdocs, name, path) 55 | 56 | # Handle multiple "not in nav" entries 57 | # These are of a pathspec.gitignore.GitIgnoreSpec format and need to be converted to a multiline string 58 | def merge_local_not_in_nav(config: MkDocsConfig, not_in_nav: list[GitIgnoreSpec]): 59 | nav_str = "\n".join(not_in_nav) 60 | config["not_in_nav"] += PathSpec().run_validation(nav_str) 61 | 62 | # Add additional theme_override folder 63 | def merge_local_theme_override(config: MkDocsConfig, custom_dir: str): 64 | try: 65 | local_override_path = FilesystemObject(exists=True).validate(custom_dir) 66 | except Exception as e: 67 | raise e 68 | 69 | config.theme.dirs.insert(1, local_override_path) 70 | 71 | # Load any override theme features 72 | def merge_local_theme_features(config: MkDocsConfig, theme_features: list[str]): 73 | for local_feature in theme_features: 74 | config.theme["features"].append(local_feature) 75 | 76 | 77 | 78 | ##### MkDocs Event Hooks 79 | 80 | def on_files(files: Files, config: MkDocsConfig): 81 | if "overrides" in config.extra: 82 | extra_overrides = config.extra["overrides"] 83 | 84 | if "extra_css" in extra_overrides: 85 | extra_css = extra_overrides["extra_css"] 86 | append_local_files(files, config, extra_css) 87 | 88 | if "extra_javascript" in extra_overrides: 89 | extra_javascript = extra_overrides["extra_javascript"] 90 | append_local_files(files, config, extra_javascript) 91 | 92 | def on_config(config: MkDocsConfig): 93 | if "overrides" in config.extra: 94 | extra_overrides = config.extra["overrides"] 95 | 96 | # Keep Hooks first 97 | if "hooks" in extra_overrides: 98 | hooks = extra_overrides["hooks"] 99 | merge_local_hooks(config, hooks) 100 | 101 | if "custom_dir" in extra_overrides: 102 | custom_dir = extra_overrides["custom_dir"] 103 | merge_local_theme_override(config, custom_dir) 104 | 105 | if "extra_css" in extra_overrides: 106 | extra_css = extra_overrides["extra_css"] 107 | config.extra_css.extend(extra_css) 108 | 109 | if "extra_javascript" in extra_overrides: 110 | extra_javascript = extra_overrides["extra_javascript"] 111 | config.extra_javascript.extend(extra_javascript) 112 | 113 | if "not_in_nav" in extra_overrides: 114 | not_in_nav = extra_overrides["not_in_nav"] 115 | merge_local_not_in_nav(config, not_in_nav) 116 | 117 | if "theme_features" in extra_overrides: 118 | theme_features = extra_overrides["theme_features"] 119 | merge_local_theme_features(config, theme_features) 120 | -------------------------------------------------------------------------------- /docs/_global/js/global.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docsforadobe/after-effects-plugin-guide/57465fc7f03463ad2c714b82d570c6c0d067646a/docs/_global/js/global.js -------------------------------------------------------------------------------- /docs/_global/mkdocs.yml: -------------------------------------------------------------------------------- 1 | # Shared config for all repos 2 | copyright: All content is copyright Adobe Systems Incorporated. 3 | 4 | extra: 5 | homepage: https://docsforadobe.dev 6 | 7 | # Using overrides here as we can't inherit "extra_css" 8 | overrides: 9 | extra_css: 10 | - docs/_global/css/global.css 11 | - docs/_global/css/global-syntax-highlight.css 12 | extra_javascript: 13 | - docs/_global/js/global.js 14 | 15 | hooks: 16 | - docs/_global/hooks/inline_pre_to_code_fence.py 17 | - docs/_global/hooks/merge_inherited_config.py 18 | 19 | markdown_extensions: 20 | admonition: {} 21 | markdown_grid_tables: {} 22 | md_in_html: {} 23 | pymdownx.details: {} 24 | pymdownx.highlight: 25 | line_spans: __span 26 | pygments_lang_class: true 27 | pymdownx.superfences: {} 28 | pymdownx.tabbed: 29 | alternate_style: true 30 | pymdownx.tasklist: 31 | custom_checkbox: true 32 | toc: 33 | title: Page Contents 34 | permalink: true 35 | toc_depth: 3 36 | 37 | not_in_nav: | 38 | _global 39 | 40 | plugins: 41 | git-revision-date-localized: {} 42 | search: 43 | separator: '[\s\-,\.:!=\[\]()"/]+' 44 | 45 | # Note: print-site must be last! 46 | print-site: 47 | add_cover_page: true 48 | add_print_site_banner: true 49 | cover_page_template: "docs/_global/overrides/templates/print_site_cover_page.tpl" 50 | print_page_title: "Offline Docs" 51 | print_site_banner_template: "docs/_global/overrides/templates/print_site_banner.tpl" 52 | 53 | theme: 54 | name: material 55 | custom_dir: docs/_global/overrides 56 | features: 57 | - announce.dismiss 58 | - content.action.edit 59 | - content.action.view 60 | - content.code.copy 61 | - search.highlight 62 | - search.suggest 63 | - toc.follow 64 | palette: 65 | # Palette toggle for dark mode 66 | - media: "(prefers-color-scheme: dark)" 67 | primary: black 68 | scheme: slate 69 | toggle: 70 | icon: material/brightness-4 71 | name: Switch to light mode 72 | 73 | # Palette toggle for light mode 74 | - media: "(prefers-color-scheme: light)" 75 | primary: white 76 | scheme: default 77 | toggle: 78 | icon: material/brightness-7 79 | name: Switch to dark mode 80 | -------------------------------------------------------------------------------- /docs/_global/overrides/404.html: -------------------------------------------------------------------------------- 1 | {% extends "main.html" %} 2 | 3 | 4 | {% block extrahead %} 5 | 10 | {% endblock %} 11 | 12 | {% block content %} 13 |

404 - Not found

14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /docs/_global/overrides/main.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block announce %} 4 | Welcome to the new docsforadobe guide! 5 | 6 | This is a work in progress. 7 | 8 | Please provide all feedback via 9 | 10 | 11 | {% include ".icons/octicons/comment-discussion-16.svg" %} 12 | 13 | the org's discussion forum 14 | . 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /docs/_global/overrides/partials/copyright.html: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 26 | -------------------------------------------------------------------------------- /docs/_global/overrides/partials/toc-item.html: -------------------------------------------------------------------------------- 1 |
  • 2 | 3 | 4 | {{ toc_item.title }} 5 | 6 | 7 | 8 | 9 | {% if toc_item.children %} 10 | 19 | {% endif %} 20 |
  • 21 | -------------------------------------------------------------------------------- /docs/_global/overrides/templates/print_site_banner.tpl: -------------------------------------------------------------------------------- 1 | 6 | 7 |
    8 | 9 |

    Note – This box will disappear during export!

    10 | 11 |

    This page has combined all site pages into one, and can be exported using native browser features.

    12 | 13 |

    You can export to PDF using File > Print > Save as PDF, or save as a single-page HTML file via File > Save As.

    14 | 15 |
    16 |

    Warning

    17 | 18 |

    Note that users may have issues printing to PDF on Firefox.

    19 |
    20 | 21 |
    22 | -------------------------------------------------------------------------------- /docs/_global/overrides/templates/print_site_cover_page.tpl: -------------------------------------------------------------------------------- 1 |
    2 | 3 | {% if config.site_name %} 4 |

    {{ config.site_name }}

    5 | {% endif %} 6 | 7 | {% if config.extra.homepage %} 8 | by

    {{ config.extra.homepage }}

    9 | {% endif %} 10 | 11 |
    12 | 13 | 14 | 15 | 16 | {% if config.site_description %} 17 | 18 | 19 | 20 | 21 | {% endif %} 22 | 23 | {% if config.site_url %} 24 | 25 | 26 | 27 | 28 | {% endif %} 29 | 30 | {% if config.repo_url %} 31 | 32 | 33 | 34 | 35 | {% endif %} 36 | 37 | {% if config.copyright %} 38 | 39 | 40 | 41 | 42 | {% endif %} 43 | 44 |
    Description{{ config.site_description }}
    Hosted at{{ config.site_url }}
    Repository{{ config.repo_url }}
    Copyright{{ config.copyright }}
    45 | -------------------------------------------------------------------------------- /docs/_global/readme.md: -------------------------------------------------------------------------------- 1 | # docsforadobe.dev MkDocs Config 2 | 3 | This repo holds the common components shared between this org's hosted MkDocs documentation projects. 4 | 5 | The idea is that this repo will be kept up-to-date with global config, and each child repo will use the provided script to download the latest commit from this repo, and have its "local" MkDocs config point to the downloaded files from this repo. 6 | 7 | In all cases, each child repo will be able to *override* config items here as needed. 8 | 9 | ## Updating This Repo 10 | 11 | See [Modifying Common Components](https://docsforadobe.dev/contributing/common-components/modifying-common-components/) in the org contribution guide for info on how this repo works, and best practices for modifying it. 12 | -------------------------------------------------------------------------------- /docs/_global/requirements.txt: -------------------------------------------------------------------------------- 1 | markdown_grid_tables 2 | mkdocs 3 | mkdocs-git-revision-date-localized-plugin 4 | mkdocs-material 5 | mkdocs-print-site-plugin 6 | -------------------------------------------------------------------------------- /docs/_global/scripts/update-common-components.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import tarfile 4 | import tempfile 5 | import urllib.request 6 | 7 | org_name = "docsforadobe" 8 | repo_name = "docsforadobe-mkdocs-config" 9 | destination_dir = "./docs/_global" 10 | 11 | def download_github_repo(org_name, repo_name, destination_dir): 12 | tar_url = f"https://api.github.com/repos/{org_name}/{repo_name}/tarball/main" 13 | 14 | response = urllib.request.urlopen(tar_url) 15 | 16 | if (response): 17 | with tempfile.TemporaryDirectory() as temp_dir: 18 | tar = tarfile.open(fileobj=response, mode="r|gz") 19 | tar_extraction_path = os.path.join(temp_dir, tar.firstmember.name) 20 | 21 | tar.extractall(path=temp_dir) 22 | 23 | # If already exist, remove first 24 | if (os.path.isdir(destination_dir)): 25 | shutil.rmtree(destination_dir) 26 | 27 | # Move from temp folder to destination folder 28 | shutil.move(tar_extraction_path, destination_dir) 29 | 30 | download_github_repo(org_name, repo_name, destination_dir) 31 | -------------------------------------------------------------------------------- /docs/_static/AE_Log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docsforadobe/after-effects-plugin-guide/57465fc7f03463ad2c714b82d570c6c0d067646a/docs/_static/AE_Log.png -------------------------------------------------------------------------------- /docs/_static/Unlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docsforadobe/after-effects-plugin-guide/57465fc7f03463ad2c714b82d570c6c0d067646a/docs/_static/Unlock.png -------------------------------------------------------------------------------- /docs/_static/appleclang-symbols.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docsforadobe/after-effects-plugin-guide/57465fc7f03463ad2c714b82d570c6c0d067646a/docs/_static/appleclang-symbols.png -------------------------------------------------------------------------------- /docs/_static/debugmonitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docsforadobe/after-effects-plugin-guide/57465fc7f03463ad2c714b82d570c6c0d067646a/docs/_static/debugmonitor.png -------------------------------------------------------------------------------- /docs/_static/extra.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docsforadobe/after-effects-plugin-guide/57465fc7f03463ad2c714b82d570c6c0d067646a/docs/_static/extra.css -------------------------------------------------------------------------------- /docs/_static/mac_universal_build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/docsforadobe/after-effects-plugin-guide/57465fc7f03463ad2c714b82d570c6c0d067646a/docs/_static/mac_universal_build.png -------------------------------------------------------------------------------- /docs/aegps/aegp-details.md: -------------------------------------------------------------------------------- 1 | # AEGP Details 2 | 3 | ## Have A Cookie 4 | 5 | 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. 6 | 7 | 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()` (under [AEGP_KeyframeSuite3](aegp-suites.md#aegp_keyframesuite3)) for an example. 8 | 9 | --- 10 | 11 | ## Modifying Items In The Render Queue 12 | 13 | If you call `AEGP_AddCompToRenderQueue` (from [AEGP_RenderQueueSuite1](aegp-suites.md#aegp_renderqueuesuite1)), or if the user manually adds or removes a composition from the render queue, all references to render queue items are invalidated. Similarly, adding or removing output modules invalidates any such references for each render queue item. 14 | 15 | --- 16 | 17 | ## Names And Solids 18 | 19 | Solids have names in the After Effects UI, but not in their `PF_LayerDef` [PF_EffectWorld / PF_LayerDef](../effect-basics/PF_EffectWorld.md). Consequently, their names cannot be retrieved by `AEGP_GetItemName` (in [AEGP_ItemSuite9](aegp-suites.md#aegp_itemsuite9)) or `AEGP_GetLayerName` (in [AEGP_LayerSuite9](aegp-suites.md#aegp_layersuite9)). 20 | 21 | However, you can use the ItemH associated with them to `AEGP_GetItemName` (from [AEGP_ItemSuite9](aegp-suites.md#aegp_itemsuite9)). 22 | 23 | --- 24 | 25 | ## Reporting Errors And Problems 26 | 27 | Use `AEGP_ItemSuite>AEGP_ReportInfo()` to report information to users, and identify your plug-in. AEIO plug-ins use the msg_func pointer contained in the AEIO_BasicData they're passed (with every function) instead. 28 | 29 | --- 30 | 31 | ## Transforms: What Happens First? 32 | 33 | After Effects computes rotation based on auto-orientation (towards path, or point of interest), then computes Orientation, then computes X, Y, and Z rotation. 34 | 35 | --- 36 | 37 | ## Accessing Pixels From Effect Layer Parameters 38 | 39 | Use `AEGP_GetNewStreamValue` (in [AEGP_StreamSuite5](aegp-suites.md#aegp_streamsuite5)) to get the layer's `layer_id`, then the new `AEGP_GetLayerFromLayerID` (in [AEGP_LayerSuite9](aegp-suites.md#aegp_layersuite9)) to get the `AEGP_LayerH`. 40 | -------------------------------------------------------------------------------- /docs/aegps/aegps.md: -------------------------------------------------------------------------------- 1 | # AEGPs 2 | 3 | The After Effects General Plug-in (AEGP) API is powerful and broad, offering functionality beyond what is available to effect plug-ins. 4 | 5 | To users, AEGPs appear to be part of After Effects. 6 | 7 | They can add, intercept, and trigger menu commands, access the keyframe database, and register functions as part of After Effects' internal messaging. 8 | 9 | AEGPs can add and remove items to projects and compositions, add and remove filters and keyframes. 10 | 11 | Once its command is triggered, AEGPs use the numerous PICA function suites (described in this section) to work with every After Effects item. 12 | 13 | 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. 14 | 15 | 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. 16 | -------------------------------------------------------------------------------- /docs/aegps/cheating-effect-usage-of-aegp-suites.md: -------------------------------------------------------------------------------- 1 | # Cheating Effect Usage of AEGP Suites 2 | 3 | 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 AEGP APIs) can lead to trouble. If After Effects thinks an effect has all the information it needs to render, it won't (for example) update its parameters based on changes made through an AEGP function. We're actively working on this dependency issue for future versions, but bear it in mind as you write effects which "masquerade" as AEGPs. 4 | 5 | Effects can use some AEGP suites to take advantage of camera and lighting information, as well as the `AEGP_GetLayerParentComp` and `AEGP_GetCompBGColor` functions, from [AEGP_CompSuite11](aegp-suites.md#aegp_compsuite11). This should not be interpreted to mean that effects can use *any* AEGP suite calls. Also, see [Effect UI & Events](../effect-ui-events/effect-ui-events.md) for more information on effects adding keyframes. 6 | 7 | [AEGP_PFInterfaceSuite](aegp-suites.md#aegp_pfinterfacesuite1) 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` from [AEGP_UtilitySuite6](aegp-suites.md#aegp_utilitysuite6) allows you to get an AEGP_PluginID, which is needed for many AEGP calls. 8 | 9 | --- 10 | 11 | ## Depending on AEGP Queries 12 | 13 | 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. 14 | 15 | This is tricky. 16 | 17 | Failure to do so will result in nasty, subtle caching bugs guaranteed to cause hair loss and weight gain. 18 | -------------------------------------------------------------------------------- /docs/aegps/implementation.md: -------------------------------------------------------------------------------- 1 | # Implementation 2 | 3 | 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. 4 | 5 | AEGPs interact with After Effects through PICA function suites. 6 | 7 | AEGPs are not loaded in a specific order. 8 | 9 | Check the version of the AEGP API (from within your AEGP's entry point function) to confirm whether a given suite will be available. 10 | 11 | AEGPs may also use any effect API suite function which doesn't require a PF_ProgPtr (obtained by effects from PF_InData). 12 | 13 | --- 14 | 15 | ## Entry Point 16 | 17 | ```cpp 18 | A_Err AEGP_PluginInitFuncPrototype( 19 | struct SPBasicSuite *pica_basicP, 20 | A_long major_versionL, 21 | A_long minor_versionL, 22 | AEGP_PluginID aegp_plugin_id, 23 | AEGP_GlobalRefcon *global_refconP) 24 | ``` 25 | 26 | The plug-in's entry point, exported in the [PiPL Resources](../intro/pipl-resources.md), is called just once during launch; all other calls to the AEGP go to the functions it's registered. 27 | 28 | This is very different from the effect plug-in model, where all communication comes through the same entry point. 29 | 30 | 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). 31 | 32 | The AEGP [API Versions](../intro/compatibility-across-multiple-versions.md#api-versions) can help distinguish between different versions of After Effects, in case the AEGP needs to behave differently or handle different behavior. 33 | 34 | 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). 35 | 36 | --- 37 | 38 | ## Specialization 39 | 40 | AEIOs and Artisans must register with After Effects in order to receive the messaging streams on which they depend. 41 | 42 | Like everything else in the AEGP API, this is done through a function suite; in this case, the aptly-named AEGP_RegisterSuite. 43 | 44 | --- 45 | 46 | ## Example: Adding A Menu Item 47 | 48 | During your entry point function, use `AEGP_GetUniqueCommand()` from [Command Suite](aegp-suites.md#aegp_commandsuite1) to obtain a command ID from After Effects, for use with `AEGP_InsertMenuCommand`. Use a different ID for each menu item you add. 49 | 50 | Using AEGP_RegisterSuite's `AEGP_RegisterCommandHook()`, tell After Effects which function to call when your menu item(s) are selected. The function you register using `AEGP_RegisterUpdateMenuHook()` enables and disabling your menu item(s). Your menu item(s) will be permanently disabled unless you register a menu updating function. 51 | 52 | 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. 53 | 54 | --- 55 | 56 | ## Private Data 57 | 58 | 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. 59 | 60 | 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. 61 | 62 | Where possible, use these refcons to store information, not statics and global variables. This becomes especially important when dealing with multi-threading issues. 63 | 64 | Use `global_refconPV` for your globals (like your `aegp_plugin_id`) and refcon for hook-function-specific storage. 65 | 66 | A potential "multiple instances of After Effects" gotcha; when a second, command-line instance of After Effects is launched, all of an AEGP's handles are duplicated. If this causes problems (and it may), provide code that attaches saved handles to specific instantiations of your plug-in. 67 | 68 | --- 69 | 70 | ## Threading 71 | 72 | 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. 73 | 74 | There is one call that is thread safe: `AEGP_CauseIdleRoutinesToBeCalled()`. 75 | 76 | But since `SPBasicSuite` itself is not thread safe, you'll need to stash off the function pointer in the main thread. 77 | -------------------------------------------------------------------------------- /docs/aegps/overview.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | AEGPs use Plug-In Component Architecture (PICA) function suites to access all functionality. 4 | 5 | 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). 6 | 7 | AEGPs can also request a suite and, if it's not present, provide replacement functionality themselves. 8 | 9 | --- 10 | 11 | ## AEGP Communication With After Effects 12 | 13 | For effect plug-ins, all communication with After Effects occurs through a single entry point function. This is not the case with AEGPs. 14 | 15 | 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. 16 | 17 | This registration must be performed from within the plug-in's entry function, using the [Register Suite](aegp-suites.md#aegp_registersuites5). 18 | 19 | --- 20 | 21 | ## Different Tasks, Same API 22 | 23 | AEGPs work in the same manner, regardless of specialization. 24 | 25 | They can be simple, just [adding one menu item](implementation.md#example-adding-a-menu-item) to trigger an external application, or complex like Artisans. 26 | 27 | While any plug-in can access any function suite, only plug-ins of the appropriate type will have access to all the required parameters. 28 | 29 | 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. 30 | -------------------------------------------------------------------------------- /docs/aeios/aeios.md: -------------------------------------------------------------------------------- 1 | # AEIOs 2 | 3 | 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. 4 | 5 | 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. 6 | 7 | --- 8 | 9 | ## AEIO, or AEGP? 10 | 11 | AEIOs provide pixels and audio data to After Effects. 12 | 13 | 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. 14 | 15 | --- 16 | 17 | ## AEIO For Import, Or MediaCore Importer? 18 | 19 | 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](http://ppro-plugin-sdk.aenhancers.com/). 20 | 21 | 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. 22 | 23 | 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. 24 | 25 | --- 26 | 27 | ## How It Works 28 | 29 | 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. 30 | 31 | --- 32 | 33 | ## What Would After Effects Do? 34 | 35 | For many AEIO hook functions, you can ask After Effects to perform default processing (this capability is noted in each hook's descriptions). 36 | 37 | Unless you have compelling reasons to do otherwise, return `AEIO_Err_USE_DFLT_CALLBACK` from the function, and let After Effects do the work. 38 | 39 | This is also a good way to learn the calling sequence before beginning implementation. 40 | 41 | --- 42 | 43 | ## Registering Your AEIO 44 | 45 | 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()` from [AEGP_RegisterSuites5](../aegps/aegp-suites.md#aegp_registersuites5). 46 | 47 | 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. 48 | 49 | --- 50 | 51 | ## InSpec, OutSpec 52 | 53 | On most import-related functions, an `AEIO_InSpecH` is passed. On most output-related functions, an `AEIO_OutSpecH` is passed. 54 | 55 | What are these mysterious handles? These opaque data handles can be used with [AEGP_IOInSuite5](new-kids-on-the-function-block.md#aegp_ioinsuite5) and [AEGPIOOutSuite4](new-kids-on-the-function-block.md#aegpiooutsuite4), to set or query for information about the import or output. 56 | 57 | For example, on an import, you'll use `AEIO_InSpecH` when calling `AEGP_SetInSpecDimensions` in AEGP_IOInSuite. 58 | 59 | And during an export, you'll use `AEIO_OutSpecH` when calling `AEGP_GetOutSpecDimensions` in `AEGP_IOOutSuite`. So use these handles to exchange information with After Effects about the details of the input or output. 60 | -------------------------------------------------------------------------------- /docs/aeios/calling-sequence.md: -------------------------------------------------------------------------------- 1 | # Calling Sequence 2 | 3 | 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()](../aegps/aegp-suites.md#aegp_registersuites5). 4 | 5 | --- 6 | 7 | ## Import 8 | 9 | When users select a file in the file import dialog which is of a type handled by your AEIO, its [AEIO_VerifyFileImportable()](new-kids-on-the-function-block.md#aeio_functionblock4) function will be called; it's called again for each such file the user imports. [AEIO_InitInSpecFromFile()](new-kids-on-the-function-block.md#aeio_functionblock4) 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()](new-kids-on-the-function-block.md#aegp_ioinsuite5). 10 | 11 | After Effects then calls the plug-in's [AEIO_GetInSpecInfo()](new-kids-on-the-function-block.md#aeio_functionblock4) 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). 12 | 13 | [AEIO_CountUserData()](new-kids-on-the-function-block.md#aeio_functionblock4) is then sent; if the AEIO indicates that there is user data present, [AEIO_GetUserData()](new-kids-on-the-function-block.md#aeio_functionblock4) 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()](new-kids-on-the-function-block.md#aeio_functionblock4). 14 | 15 | Once the supported file is added to a composition, user interaction will generate calls to `AEIO_DrawSparseFrame()` and [AEIO_GetSound()](new-kids-on-the-function-block.md#aeio_functionblock4). 16 | 17 | When the project is saved, and if there is options data associated with the AEIO_InSpec, After Effects will send [AEIO_FlattenOptions()](new-kids-on-the-function-block.md#aeio_functionblock4) 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()](new-kids-on-the-function-block.md#aeio_functionblock4) being sent. 18 | 19 | --- 20 | 21 | ## Export 22 | 23 | If the user adds an item to the render queue and chooses the AEIO's supported output format, [AEIO_InitOutputSpec()](new-kids-on-the-function-block.md#aeio_functionblock4) will be sent. Use the various get functions to obtain information about the output settings, and store any pertinent information using [AEGP_SetOutSpecOptionsHandle()](new-kids-on-the-function-block.md#aeio_functionblock4), followed by `AEIO_GetFlatOutputOptions()`. [AEIO_GetDepths()](new-kids-on-the-function-block.md#aeio_functionblock4) is sent so After Effects can determine what output pixel bit depths the AEIO supports. [AEIO_GetOutputInfo()](new-kids-on-the-function-block.md#aeio_functionblock4) is sent so that file name, type and subtype information can be displayed in the output module details. 24 | 25 | When the user clicks on the Format Options button, in the render queue, [AEIO_UserOptionsDialog()](new-kids-on-the-function-block.md#aeio_functionblock4) is called. 26 | 27 | When the user actually clicks on the "Render" button, [AEIO_SetOutputFile()](new-kids-on-the-function-block.md#aeio_functionblock4) will be called, followed by [AEIO_GetSizes()](new-kids-on-the-function-block.md#aeio_functionblock4) (your AEIO is responsible for determining whether the destination has sufficient disk space available). 28 | 29 | Before the video frames are sent, [AEIO_StartAdding()](new-kids-on-the-function-block.md#aeio_functionblock4) 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()](new-kids-on-the-function-block.md#aeio_functionblock4) is sent for each audio chunk, and an [AEIO_AddFrame()](new-kids-on-the-function-block.md#aeio_functionblock4) for each video frame. 30 | 31 | If the AEIO supports sequences of still images, [AEIO_OutputFrame()](new-kids-on-the-function-block.md#aeio_functionblock4) is called repeatedly. After Effects sends a PF_EffectWorld representation of the frame to be output. 32 | 33 | [AEIO_WriteLabels()](new-kids-on-the-function-block.md#aeio_functionblock4) is called (for each frame) to give the plug-in a chance to write out field and alpha interpretation information. [AEIO_EndAdding()](new-kids-on-the-function-block.md#aeio_functionblock4) is sent when there are no more frames (or audio) to be output. Close the output file. 34 | -------------------------------------------------------------------------------- /docs/aeios/implementation-details.md: -------------------------------------------------------------------------------- 1 | # Implementation Details 2 | 3 | ## Export Bit-Depth 4 | 5 | In the Output Module Settings, the user can choose a Depth based on the options the AEIO declares support for in `AEIO_GetDepths()` from [AEIO_FunctionBlock4](new-kids-on-the-function-block.md#new-kids-on-the-function-block). 6 | 7 | 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. 8 | 9 | The frame delivered to the AEIO, and the final output will not necessarily be the same depth. 10 | 11 | You may get frames passed in the project bit-depth instead of the final output if After Effects thinks that will be higher quality. 12 | 13 | --- 14 | 15 | ## User Data vs. Options 16 | 17 | It's possible to use either user data allocations or options handles to store metadata about a file. 18 | 19 | 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. 20 | 21 | We use option handles for information about the file; output settings, dimensions, details of compression settings used. 22 | -------------------------------------------------------------------------------- /docs/artisans/artisans.md: -------------------------------------------------------------------------------- 1 | # Artisans 2 | 3 | !!! note 4 | If you're considering developing an Artisan, please talk it over with us first. 5 | 6 | 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. 7 | 8 | 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. 9 | 10 | --- 11 | 12 | ## Interactive Artisans 13 | 14 | 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). 15 | -------------------------------------------------------------------------------- /docs/audio/accessing-audio-data.md: -------------------------------------------------------------------------------- 1 | # Accessing Audio Data 2 | 3 | Use `PF_CHECKOUT_LAYER_AUDIO` from [Interaction Callbacks](../effect-details/interaction-callback-functions.md) to retrieve an audio layer. 4 | 5 | This layer is opaque; use `PF_GET_AUDIO_DATA` to access specific details about that audio. 6 | 7 | As with pixel data, it's important that you check in the audio as soon as possible. 8 | 9 | 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` from [Frame Selectors](../effect-basics/command-selectors.md#frame-selectors). 10 | 11 | --- 12 | 13 | ## Extending Audio Clips 14 | 15 | You cannot extend the length of an audio clip through the API. 16 | 17 | 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. 18 | 19 | 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. 20 | 21 | Document the steps users should take when applying your effect. 22 | -------------------------------------------------------------------------------- /docs/audio/audio-considerations.md: -------------------------------------------------------------------------------- 1 | # Audio Considerations 2 | 3 | The After Effects audio API supports sampling rates up to 96Khz, in as many formats as possible. 4 | 5 | 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. 6 | 7 | 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. 8 | 9 | Audio filters encounter different issues than do image filters. 10 | 11 | Investigate the SDK sample for one possible implementation of audio rendering. 12 | -------------------------------------------------------------------------------- /docs/audio/audio-data-structures.md: -------------------------------------------------------------------------------- 1 | # Audio Data Structures 2 | 3 | The following data types are used by After Effects to describe audio data. 4 | 5 | +----------------------+----------------------------------------------------------------------------------------------------------------------+ 6 | | Structure | Description | 7 | +======================+======================================================================================================================+ 8 | | `PF_SoundFormat` | Indicates whether the audio is in unsigned pulse code modulation (PCM), signed PCM, or floating point format. | 9 | +----------------------+----------------------------------------------------------------------------------------------------------------------+ 10 | | `PF_SoundSampleSize` | Samples are in 1, 2, or 4 byte format. | 11 | +----------------------+----------------------------------------------------------------------------------------------------------------------+ 12 | | `PF_SoundChannels` | Indicates whether the audio is mono or stereo. | 13 | +----------------------+----------------------------------------------------------------------------------------------------------------------+ 14 | | `PF_SoundFormatInfo` | Contains the sampling rate, number of channels, sample size, and format of the audio to which it refers. | 15 | +----------------------+----------------------------------------------------------------------------------------------------------------------+ 16 | | `PF_SoundWorld` | Use `PF_SoundWorlds` to represent audio. | 17 | | | | 18 | | | In addition to a `PF_SoundFormatInfo`, they contain the length of the audio, and a pointer to the actual audio data. | 19 | +----------------------+----------------------------------------------------------------------------------------------------------------------+ 20 | 21 | `PF_SoundFormat`, `PF_SoundSampleSize`, and `PF_SoundChannels` are all contained within a `PF_SoundFormatInfo`. 22 | 23 | `PF_SoundWorlds` contain a `PF_SoundFormatInfo`, and further instance-specific information. 24 | -------------------------------------------------------------------------------- /docs/audio/audio-specific-float-slider-variables.md: -------------------------------------------------------------------------------- 1 | # Audio-Specific Float Slider Variables 2 | 3 | `PF_Param_FLOAT_SLIDERs` contain several parameters not found in other sliders; flags, phase, and curve tolerance. 4 | 5 | --- 6 | 7 | ## Flags 8 | 9 | The only flag available is `PF_FSliderFlag_WANT_PHASE`. 10 | 11 | This registers the effect to receive updated phase information from After Effects during audio rendering. 12 | 13 | To understand what this flag does, turn it off and check your output. 14 | 15 | --- 16 | 17 | ## Phase 18 | 19 | This is where the requested phase value is stored. 20 | 21 | --- 22 | 23 | ## Curve Tolerance 24 | 25 | 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). 26 | 27 | --- 28 | 29 | ## What's Zero, Really? 30 | 31 | When amplitude is zero, After Effects is at -192db. 32 | -------------------------------------------------------------------------------- /docs/audio/audio.md: -------------------------------------------------------------------------------- 1 | # Audio 2 | 3 | After Effects can process audio encoded at up to 96Khz, floating point (24-bit) resolution, mono or stereo. 4 | 5 | We provide high quality resampling. 6 | 7 | `PF_InData` and `PF_OutData` both contain information specific to audio handling. 8 | 9 | While audio isn't the focus of After Effects' feature set, it is an important component of compositing and pre-visualization workflows. 10 | 11 | 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. 12 | -------------------------------------------------------------------------------- /docs/audio/global-outflags.md: -------------------------------------------------------------------------------- 1 | # Global Outflags 2 | 3 | All audio effects must set either `PF_OutFlag_AUDIO_EFFECT_TOO` or `PF_OutFlag_AUDIO_EFFECT_ONLY`. 4 | 5 | `PF_OutFlag_I_USE_AUDIO` is for visual effects that check out audio data, but don't modify it. 6 | 7 | `PF_OutFlag_AUDIO_FLOAT_ONLY`, `PF_OutFlag_AUDIO_IIR` and `PF_OutFlag_I_SYNTHESIZE_AUDIO` provide greater control over audio output (see [PF_OutFlags](../effect-basics/PF_OutData.md#pf_outflags) for more details). 8 | -------------------------------------------------------------------------------- /docs/effect-basics/effect-basics.md: -------------------------------------------------------------------------------- 1 | # Effect Basics 2 | 3 | This chapter will provide all the information you need to know to understand how a basic effect plug-in works. 4 | 5 | These details are fundamental to every effect plug-in. 6 | 7 | By the time you finish this chapter, you'll be ready for the fun stuff; modifying pixels! 8 | -------------------------------------------------------------------------------- /docs/effect-basics/entry-point.md: -------------------------------------------------------------------------------- 1 | # Entry Point 2 | 3 | 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. 4 | 5 | For all effect plug-ins, the entry point function must have the following signature: 6 | 7 | ```cpp 8 | PF_Err main ( 9 | PF_Cmd cmd, 10 | PF_InData *in_data, 11 | PF_OutData *out_data, 12 | PF_ParamDef *params[], 13 | PF_LayerDef *output, 14 | void *extra) 15 | ``` 16 | 17 | The name of the entry point function above is "main", but it can be whatever is specified in [PiPL Resources](../intro/pipl-resources.md). 18 | 19 | Before each call to the entry point function, After Effects updates [PF_InData](PF_InData.md) and the plug- in's parameter array PF_ParamDef[] (except as noted). 20 | 21 | After the plug-in returns from its call, After Effects checks [PF_OutData](PF_OutData.md) for changes and, when appropriate, uses the PF_LayerDef the effect has rendered. 22 | 23 | --- 24 | 25 | ## Entry Point Function Parameters 26 | 27 | +-----------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 28 | | Argument | Purpose | 29 | +===============================================+=================================================================================================================================================================================+ 30 | | [cmd](command-selectors.md) | After Effects sets the [Command Selectors](command-selectors.md) to tell the plug-in what to do. | 31 | +-----------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 32 | | [in_data](PF_InData.md) | Information about the application's state and the data the plug-in is being told to act upon. | 33 | | | | 34 | | | Pointers to numerous interface and image manipulation functions are also provided. | 35 | +-----------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 36 | | [out_data](PF_OutData.md) | Pass back information to After Effects by setting fields within out_data. | 37 | +-----------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 38 | | [params](parameters.md) | An array of the plug-in's parameters at the time provided in in_data> current_time. | 39 | | | | 40 | | | `params[0]` is the input image (a [PF_EffectWorld / PF_LayerDef](PF_EffectWorld.md)) to which the effect should be applied. | 41 | | | | 42 | | | These values are only valid during certain selectors (this is noted in the [selector descriptions](command-selectors.md#calling-sequence)). | 43 | | | | 44 | | | Parameters are discussed at length here: [PF_ParamDef](PF_ParamDef.md). | 45 | +-----------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 46 | | [output](PF_EffectWorld.md) | The output image, to be rendered by the effect plug-in and passed back to After Effects. | 47 | | | | 48 | | | Only valid during certain selectors. | 49 | +-----------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 50 | | [extra](../effect-ui-events/PF_EventExtra.md) | The extra parameter varies with the command sent or (in the case of [PF_Cmd_EVENT](command-selectors.md#messaging), the [event type](../effect-ui-events/effect-ui-events.md)). | 51 | | | | 52 | | | Used primarily for event management and [Parameter Supervision](../effect-details/parameter-supervision.md). | 53 | +-----------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 54 | -------------------------------------------------------------------------------- /docs/effect-basics/errors.md: -------------------------------------------------------------------------------- 1 | # Errors 2 | 3 | Always, always, *always* (always!) return a `PF_Err` from `main()`. Plug-ins must pass all errors back to After Effects. 4 | 5 | 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. 6 | 7 | Be vigilant about returning the right error code, and disposing of any memory you've allocated. 8 | 9 | Really. We're serious. 10 | 11 | --- 12 | 13 | ## Error Codes 14 | 15 | +-------------------------------------+------------------------------------------------------------------------------------------------------------------------------+ 16 | | Error | Meaning | 17 | +=====================================+==============================================================================================================================+ 18 | | `PF_Err_NONE` | Success. | 19 | +-------------------------------------+------------------------------------------------------------------------------------------------------------------------------+ 20 | | `PF_Err_OUT_OF_MEMORY` | Memory allocation failed. | 21 | | | | 22 | | | Note that RAM preview will cause this condition, so After Effects will be expecting to receive this error from your plug-in. | 23 | +-------------------------------------+------------------------------------------------------------------------------------------------------------------------------+ 24 | | `PF_Err_INTERNAL_STRUCT_DAMAGED` | Problems using a data structure. | 25 | +-------------------------------------+------------------------------------------------------------------------------------------------------------------------------+ 26 | | `PF_Err_INVALID_INDEX` | Problems finding/using array member. | 27 | +-------------------------------------+------------------------------------------------------------------------------------------------------------------------------+ 28 | | `PF_Err_UNRECOGNIZED_PARAM_TYPE` | Problem with parameter data. | 29 | +-------------------------------------+------------------------------------------------------------------------------------------------------------------------------+ 30 | | `PF_Err_INVALID_CALLBACK` | Problems accessing function through pointer. | 31 | +-------------------------------------+------------------------------------------------------------------------------------------------------------------------------+ 32 | | `PF_Err_BAD_CALLBACK_PARAM` | Problems using a parameter passed to a callback. | 33 | +-------------------------------------+------------------------------------------------------------------------------------------------------------------------------+ 34 | | `PF_Interrupt_CANCEL` | Both effect and AEGP callbacks can return this to effects, if a user action aborts a render. | 35 | | | | 36 | | | If the effect gets this error from a callback, it should stop processing the frame and return the error to the host. | 37 | | | | 38 | | | Failure to pass the error back may result in misrendered frames being cached. | 39 | +-------------------------------------+------------------------------------------------------------------------------------------------------------------------------+ 40 | | `PF_Err_CANNOT_PARSE_KEYFRAME_TEXT` | Return this from `PF_Arbitrary_SCAN_FUNC` when problems occur parsing the clipboard into keyframe data. | 41 | +-------------------------------------+------------------------------------------------------------------------------------------------------------------------------+ 42 | 43 | --- 44 | 45 | ## Error Reporting Policy 46 | 47 | After Effects has a consistent policy for error handling; follow it. 48 | 49 | 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. 50 | 51 | After Effects considers errors from the operating system, encountered during your plug-in's execution, to be yours. 52 | 53 | If you get an error code back from one of our callback functions, pass it back to After Effects; we've already reported it. 54 | 55 | 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. 56 | 57 | To report an error from within a plug-in, set `PF_OutFlag_DISPLAY_ERROR_MESSAGE`, and describe the error in [PF_OutData>return_msg](PF_OutData.md#pf_outdata). 58 | 59 | Doing so will enter your error into the render log, and prevent system hangs in renders driven by a render engine or scripting. 60 | 61 | --- 62 | 63 | ## Dig In! 64 | 65 | 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! 66 | 67 | 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. 68 | 69 | To this end, After Effects exposes a tremendous amount of its internal functionality via function suites. 70 | 71 | By relying on After Effects code for utility functions, you should be able to get your image processing algorithms implemented quickly. 72 | 73 | This will discussed in [Effect Details](../effect-details/effect-details.md). 74 | -------------------------------------------------------------------------------- /docs/effect-details/accessing-camera-light-information.md: -------------------------------------------------------------------------------- 1 | # Accessing Camera & Light Information 2 | 3 | Using functions provided in the [AEGP_PFInterfaceSuite](../aegps/aegp-suites.md#aegp_pfinterfacesuite1), effects can access camera and lighting information for the layer to which they're applied; see the Resizer sample. 4 | 5 | You can also use many of the other functions from AE_GeneralPlug.h; the possibilities are vast. 6 | -------------------------------------------------------------------------------- /docs/effect-details/accessing-function-suites.md: -------------------------------------------------------------------------------- 1 | # Accessing the After Effects Function Suites 2 | 3 | If you are writing C++ code, accessing the suites should be done using the AEFX_SuiteScoper which automatically acquires the suite when needed and disposes of it when done. 4 | 5 | Here is an example using AEFX_SuiteScope to access the PF_GPUDeviceSuite1 suite: 6 | 7 | ```cpp 8 | AEFX_SuiteScoper gpu_suite = AEFX_SuiteScoper( 9 | in_dataP, 10 | kPFGPUDeviceSuite, 11 | kPFGPUDeviceSuiteVersion1, 12 | out_dataP); 13 | ``` 14 | 15 | !!! note 16 | AEFX_SuiteScoper will throw an Exception, `A_Err_MISSING_SUITE`, if the requested suite cannot be acquired and the optional second template argument, `ALLOW_NO_SUITE`, is set to false. 17 | 18 | If you set `ALLOW_NO_SUITE` to `false`, please ensure you wrap the `AEFX_SuiteScoper<>` call with a try/catch wrapper. 19 | 20 | If `ALLOW_NO_SUITE` is set to `true`, then you should check the returned pointer is not NULL before using it. 21 | 22 | Once you have the suite you may make calls to any function in the suite list so: 23 | 24 | ```cpp 25 | gpu_suite->GetDeviceInfo(in_dataP->effect_ref, extraP->input->device_index, &device_info); 26 | ``` 27 | 28 | 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. 29 | 30 | Behind the scenes, both of these methods acquire PICA function suites using `AcquireSuite`, a member function of the `SPBasicSuite` pointed to in `PF_InData`. 31 | 32 | --- 33 | 34 | ## Suite Versions 35 | 36 | 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. 37 | 38 | 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. 39 | 40 | --- 41 | 42 | ## Threading 43 | 44 | 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. 45 | -------------------------------------------------------------------------------- /docs/effect-details/changing-parameter-orders.md: -------------------------------------------------------------------------------- 1 | # Changing Parameter Orders, the Nice Way 2 | 3 | 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. 4 | 5 | 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. 6 | 7 | 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... 8 | 9 | *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.* 10 | 11 | Before calling PF_ADD_PARAM(), specify the disk ID in the PF_ParamDef.uu.id field. If no value is specified, After Effects makes parameters sequential starting with 1. The parameter's information is tagged with this ID when saved. In this way, After Effects can still understand that, although your "Foobarocity" slider is now the fourth parameter passed, it's the same parameter as when it was second. 12 | 13 | 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. 14 | 15 | --- 16 | 17 | ## Change defaults? Change IDs 18 | 19 | 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. 20 | 21 | Presto! Instant support call. 22 | 23 | This is another prime use case for `PF_ParamFlag_USE_VALUE_FOR_OLD_PROJECTS` from [Parameter Flags](../effect-basics/PF_ParamDef.md#parameter-flags). 24 | -------------------------------------------------------------------------------- /docs/effect-details/color-space-conversion.md: -------------------------------------------------------------------------------- 1 | # Color Space Conversion 2 | 3 | Different pixel formats are useful for different operations. After Effects exposes its internal functions through PF_ColorCallbacksSuite. Here are the supported formats. 4 | 5 | --- 6 | 7 | ## Pixel Types For Different Color Spaces 8 | 9 | | Pixel Type | Data Structure | 10 | | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | 11 | | 8 bpc ARGB |
    typedef struct {
    A_u_char alpha, red, green, blue;
    } PF_Pixel8;
    | 12 | | 16 bpc ARGB |
    typedef struct {
    A_u_short alpha, red, green, blue;
    } PF_Pixel16;
    | 13 | | 32 bpc ARGB |
    typedef struct {
    PF_FpShort alpha, red, green, blue;
    } PF_PixelFloat, PF_Pixel32;
    | 14 | | HLS (Hue, Lightness, Saturation) |
    typedef PF_Fixed PF_HLS_PIXEL[3]
    | 15 | | YIQ (luminance, in-phase chrominance, quadrature chrominance) |
    typedef PF_Fixed PF_YIQ_PIXEL[3]
    | 16 | 17 | --- 18 | 19 | Plug-ins can draw on image processing algorithms written for nearly any color space by using the following callback functions. 20 | 21 | ## Color Space Conversion Callbacks 22 | 23 | | Function | Purpose | Replaces | 24 | | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | 25 | | RGBtoHLS | Given an RGB pixel, returns an HLS (hue, lightness, saturation) pixel. HLS values are scaled from 0 to 1 in fixed point. | `PF_RGB_TO_HLS` | 26 | | HLStoRGB | Given an HLS pixel, returns an RGB pixel. | `PF_HLS_TO_RGB` | 27 | | RGBtoYIQ | Given an RGB pixel, returns a YIQ (luminance, inphase chrominance, quadrature chrominance) pixel. Y is 0 to 1 in fixed point, I is -0.5959 to 0.5959 in fixed point, and Q is -0.5227 to 0.5227 in fixed point. | `PF_RGB_TO_YIQ` | 28 | | YIQtoRGB | Given a YIQ pixel, returns an RGB pixel. | `PF_YIQ_TO_RGB` | 29 | | Luminance | Given an RGB pixel, returns 100 times its luminance value (0 to 25500). | `PF_LUMINANCE` | 30 | | Hue | Given an RGB pixel, eturns its hue angle mapped from 0 to 255, where 0 is 0 degrees and 255 is 360 degrees. | `PF_HUE` | 31 | | Lightness | Given an RGB pixel, returns its lightness value (0 to 255). | `PF_LIGHTNESS` | 32 | | Saturation | Given an RGB pixel, returns its saturation value (0 to 255). | `PF_SATURATION` | 33 | -------------------------------------------------------------------------------- /docs/effect-details/effect-details.md: -------------------------------------------------------------------------------- 1 | # Effect Details 2 | 3 | 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. 4 | 5 | --- 6 | 7 | ## Free Code == Good 8 | 9 | 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. 10 | 11 | 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. 12 | 13 | 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. 14 | 15 | No, really, use the provided functions. Seriously. 16 | -------------------------------------------------------------------------------- /docs/effect-details/global-sequence-frame-data.md: -------------------------------------------------------------------------------- 1 | # Global, Sequence, & Frame Data 2 | 3 | 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. 4 | 5 | Use global data for information common to all instances of the effect: static variables and data, bitmaps, pointers to other DLLs or external applications. If your effect supports Multi-Frame Rendering, any static or global variables must be free of race conditions (see [What does it mean for an effect to be thread-safe?](multi-frame-rendering-in-ae.md#what-does-it-mean-for-an-effect-to-be-thread-safe) for more information). 6 | 7 | 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 or in the new [Compute Cache For Multi-Frame Rendering](multi-frame-rendering-in-ae.md#compute-cache-for-multi-frame-rendering). 8 | 9 | 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. 10 | 11 | --- 12 | 13 | ## Persistence 14 | 15 | 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 reopening the project, and must be re-connected. We call this process "flattening" and "unflattening" the sequence data. 16 | 17 | !!! note 18 | The Compute Cache does not store its contents to the project file. The data stored in the cache must be recreated during render. 19 | 20 | --- 21 | 22 | ## Validating Sequence Data 23 | 24 | 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. 25 | 26 | When asked to render frame N, assuming you have your cached data calculated up to frame N-1, call `PF_GetCurrentState()` / `PF_AreStatesIdentical()` from [PF_ParamUtilSuite3](parameter-supervision.md#pf_paramutilsuite3) to see if the cache of calculated data is still valid given the current parameter settings. 27 | 28 | The state of all parameters (except those with [PF_ParamFlag_EXCLUDE_FROM_HAVE_INPUTS_CHANGED](../effect-basics/PF_ParamDef.md#parameter-flags) set), including layer parameters (including [param[0]](../effect-basics/PF_ParamDef.md#param-zero)) are checked over the passed time span. 29 | 30 | This is done efficiently, as the change tracking is done with timestamps. 31 | 32 | 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. 33 | 34 | To test that it is working, apply your effect with one parameter keyframed on every frame. RAM Preview to fill the cache, then change one of the keyframes. The related frame and all dependent frames (e.g. later frames, in the case of a simulation) should lose their cache marks and require re-rendering. Similarly, upstream changes to sources of layer parameters should cause time-selective invalidation of the cache. 35 | 36 | --- 37 | 38 | ## Flattened And Unflattened Sequence Data 39 | 40 | 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. 41 | 42 | Upon receiving [PF_Cmd_SEQUENCE_FLATTEN](../effect-basics/command-selectors.md#sequence-selectors), put data referenced by pointers into one contiguous block from which you can later recover the old structure. 43 | 44 | If your sequence data contains a pointer to a long, allocate 4 bytes in which to store the flattened data. You must handle platform-specific byte ordering. 45 | 46 | Remember, your users (the ones who bought two copies of your plug-in, anyway) may want the same project to work on macOS and Windows. 47 | 48 | After Effects sends [PF_Cmd_SEQUENCE_RESETUP](../effect-basics/command-selectors.md#sequence-selectors) when the data is reloaded, for either flat or unflat data. 49 | 50 | Use a flag at a common offset within both structures to indicate the data's state. 51 | 52 | ```cpp 53 | typedef struct { 54 | A_char* messageZ; 55 | PF_FpLong big_numF; 56 | void* temp_storage; 57 | } non_flat_data; 58 | 59 | typedef struct { 60 | char message[256]; 61 | PF_FpLong big_numF; 62 | A_Boolean big_endianB; 63 | } flat_data; 64 | ``` 65 | 66 | --- 67 | 68 | ## Resizing Sequence Data 69 | 70 | During [PF_Cmd_SEQUENCE_SETUP](../effect-basics/command-selectors.md#sequence-selectors), allocate a handle for data specific to this instance of your effect. 71 | 72 | You may modify the contents, but not the size, of the sequence data during any selector. 73 | 74 | You may resize the sequence data handle only during the following selectors: 75 | 76 | - `PF_Cmd_AUDIO_SETUP` 77 | - `PF_Cmd_AUDIO_SETDOWN` 78 | - `PF_Cmd_FRAME_SETUP` 79 | - `PF_Cmd_FRAME_SETDOWN` 80 | - `PF_Cmd_AUDIO_RENDER` 81 | - `PF_Cmd_RENDER` 82 | - `PF_Cmd_SEQUENCE_SETUP` 83 | - `PF_Cmd_SEQUENCE_SETDOWN` 84 | - `PF_Cmd_SEQUENCE_FLATTEN` 85 | - `PF_Cmd_SEQUENCE_RESETUP` 86 | - `PF_Cmd_DO_DIALOG` 87 | 88 | --- 89 | 90 | ## Accessing sequence_data at Render Time with Multi-Frame Rendering 91 | 92 | When enabling Multi-Frame Rendering on an effect, the `sequence_data` object will be read-only/const during Render and accessible on each render thread via the `PF_EffectSequenceDataSuite1` suite. 93 | 94 | ### PF_EffectSequenceDataSuite1 95 | 96 | +---------------------------+--------------------------------------------------------------------------------------------------------------------------------+ 97 | | Function | Purpose | 98 | +===========================+================================================================================================================================+ 99 | | `PF_GetConstSequenceData` | Retrieves the read-only const sequence_data object for a rendering thread when Multi-Frame Rendering is enabled for an effect. | 100 | | | | 101 | | |
    PF_Err(*PF_GetConstSequenceData)(
    PF_ProgPtr effect_ref,
    PF_ConstHandle \*sequence_data);
    | 102 | +---------------------------+--------------------------------------------------------------------------------------------------------------------------------+ 103 | 104 | ```cpp 105 | static PF_Err Render( 106 | PF_InData *in_dataP, 107 | PF_OutData *out_dataP, 108 | PF_ParamDef *params[], 109 | PF_LayerDef *output ) 110 | { 111 | PF_ConstHandle seq_handle; 112 | 113 | AEFX_SuiteScoper seqdata_suite = 114 | AEFX_SuiteScoper( 115 | in_dataP, 116 | kPFEffectSequenceDataSuite, 117 | kPFEffectSequenceDataSuiteVersion1, 118 | out_dataP); 119 | 120 | PF_ConstHandle const_seq; 121 | seqdata_suite->PF_GetConstSequenceData(in_data->effect_ref, &const_seq); 122 | 123 | // cast const_seq to the type used when storing to sequence_data 124 | 125 | // rest of render function code... 126 | } 127 | ``` 128 | -------------------------------------------------------------------------------- /docs/effect-details/image-buffer-management-functions.md: -------------------------------------------------------------------------------- 1 | # Image Buffer Management Functions 2 | 3 | Use these functions to create and destroy [PF_EffectWorld / PF_LayerDef](../effect-basics/PF_EffectWorld.md), and to find out their bit-depth. 4 | 5 | --- 6 | 7 | ## PF_WorldSuite2 8 | 9 | +---------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 10 | | Function | Description | 11 | +=====================+=================================================================================================================================================================================================================================================+ 12 | | `PF_NewWorld` | Creates a new `PF_EffectWorld`. | 13 | | | | 14 | | |
    PF_Err PF_NewWorld(
    PF_ProgPtr effect_ref,
    A_long widthL,
    A_long heightL,
    PF_Boolean clear_pixB,
    PF_PixelFormat pixel_format,
    PF_EffectWorld \*worldP);
    | 15 | +---------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 16 | | `PF_DisposeWorld` | Disposes of a `PF_EffectWorld`. | 17 | | | | 18 | | |
    PF_Err PF_DisposeWorld(
    PF_ProgPtr effect_ref,
    PF_EffectWorld \*worldP);
    | 19 | +---------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 20 | | `PF_GetPixelFormat` | Get the pixel format for a given `PF_EffectWorld`. | 21 | | | | 22 | | |
    PF_Err PF_GetPixelFormat(
    const PF_EffectWorld \*worldP,
    PF_PixelFormat \*pixel_formatP);
    | 23 | | | | 24 | | | `pixel_formatP` can be: | 25 | | | | 26 | | | - `PF_PixelFormat_ARGB32` - standard 8-bit RGB | 27 | | | - `PF_PixelFormat_ARGB64` - 16-bit RGB | 28 | | | - `PF_PixelFormat_ARGB128` - 32-bit floating point RGB | 29 | +---------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 30 | -------------------------------------------------------------------------------- /docs/effect-details/memory-allocation.md: -------------------------------------------------------------------------------- 1 | # Memory Allocation 2 | 3 | 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. 4 | 5 | If you're wrapping existing C++ classes, create a base class that implements new and delete for that class and derive from it. To overload the STL, we don't recommend you overload global new and delete. Instead provide an allocator as part of the template definition. 6 | 7 | Handles passed to you by After Effects are locked for you before you're called, and unlocked once you return. 8 | 9 | --- 10 | 11 | ## PF_HandleSuite1 12 | 13 | +------------------------+----------------------------------------------------------------------------------------------------------+----------------------+ 14 | | Function | Purpose | Replaces | 15 | +========================+==========================================================================================================+======================+ 16 | | `host_new_handle` | Allocates a new handle. | `PF_NEW_HANDLE` | 17 | | | | | 18 | | |
    PF_Handle (*host_new_handle)(
    A_HandleSize size);
    | | 19 | +------------------------+----------------------------------------------------------------------------------------------------------+----------------------+ 20 | | `host_lock_handle` | Locks a handle. | `PF_LOCK_HANDLE` | 21 | | | | | 22 | | |
    void (*host_lock_handle)(
    PF_Handle pf_handle);
    | | 23 | +------------------------+----------------------------------------------------------------------------------------------------------+----------------------+ 24 | | `host_unlock_handle` | Unlocks a handle. | `PF_UNLOCK_HANDLE` | 25 | | | | | 26 | | |
    void (*host_unlock_handle)(
    PF_Handle pf_handle);
    | | 27 | +------------------------+----------------------------------------------------------------------------------------------------------+----------------------+ 28 | | `host_dispose_handle` | Frees a handle. | `PF_DISPOSE_HANDLE` | 29 | | | | | 30 | | |
    void (*host_dispose_handle)(
    PF_Handle pf_handle);
    | | 31 | +------------------------+----------------------------------------------------------------------------------------------------------+----------------------+ 32 | | `host_get_handle_size` | Returns the size, in bytes, of the reallocatable block whose handle is passed in. | `PF_GET_HANDLE_SIZE` | 33 | | | | | 34 | | |
    A_HandleSize (*host_get_handle_size)(
    PF_Handle pf_handle);
    | | 35 | +------------------------+----------------------------------------------------------------------------------------------------------+----------------------+ 36 | | `host_resize_handle` | Resizes a handle. | `PF_RESIZE_HANDLE` | 37 | | | | | 38 | | |
    PF_Err (*host_resize_handle)(
    A_HandleSize new_sizeL, PF_Handle \*handlePH);
    | | 39 | +------------------------+----------------------------------------------------------------------------------------------------------+----------------------+ 40 | -------------------------------------------------------------------------------- /docs/effect-details/motion-blur.md: -------------------------------------------------------------------------------- 1 | # Motion Blur 2 | 3 | Effects handle their own motion blur, using [PF_InData>shutter_angle](../effect-basics/PF_InData.md#pf_indata-members) along with [PF_InData>shutter_phase](../effect-basics/PF_InData.md#pf_indata-members). 4 | 5 | The plug-in must set [PF_OutFlag_I_USE_SHUTTER_ANGLE](../effect-basics/PF_OutData.md#pf_outflags) so After Effects knows it needs this information. 6 | 7 | They must [check out](interaction-callback-functions.md#interaction-callback-functions) their own parameters at other times to examine their change over the shutter interval. 8 | 9 | If the plug-in checks out parameters outside this interval, set [PF_OutFlag_WIDE_TIME_INPUT](../effect-basics/PF_OutData.md#pf_outflags). 10 | 11 | Doing so allows After Effects to compare the parameters within the sampling interval, and determine if they've changed. 12 | -------------------------------------------------------------------------------- /docs/effect-details/parameters-floating-point-values.md: -------------------------------------------------------------------------------- 1 | # Parameters & Floating Point Values 2 | 3 | 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. 4 | 5 | That's right, even with over-bright colors, we'd only ever tell you '255, 255, 255'. Yeah, right. 6 | 7 | Well, we can't live the lie any longer! Given a color parameter (passed to you by After Effects in your effect's parameter array), this function returns a floating point representation, including any high dynamic range component. 8 | 9 | --- 10 | 11 | ## PF_ColorParamSuite1 12 | 13 | +-----------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 14 | | Function | Purpose | 15 | +=======================+=======================================================================================================================================================================================+ 16 | | `PF_GetFloatingPoint` |
    PF_Err PF_GetFloatingPointColorFromColorDef(
    PF_ProgPtr effect_ref,
    const PF_ParamDef \*color_defP,
    PF_PixelFloat \*fp_colorP);
    | 17 | | | | 18 | | `ColorFromColorDef` | | 19 | +-----------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 20 | 21 | --- 22 | 23 | ## PF_PointParamSuite1 24 | 25 | We also provide a way to get floating point values for point parameters. 26 | 27 | +-----------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 28 | | Function | Purpose | 29 | +=======================+=======================================================================================================================================================================================+ 30 | | `PF_GetFloatingPoint` |
    PF_Err PF_GetFloatingPointValueFromPointDef(
    PF_ProgPtr effect_ref,
    const PF_ParamDef \*point_defP,
    A_FloatPoint \*fp_pointP);
    | 31 | | | | 32 | | `ValueFromPointDef` | | 33 | +-----------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 34 | 35 | --- 36 | 37 | ## PF_AngleParamSuite1 38 | 39 | New in CS6.0.2, we now provide a way to get floating point values for angle parameters. 40 | 41 | +-----------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 42 | | Function | Purpose | 43 | +=======================+=======================================================================================================================================================================================+ 44 | | `PF_GetFloatingPoint` |
    PF_Err PF_GetFloatingPointValueFromAngleDef(
    PF_ProgPtr effect_ref,
    const PF_ParamDef \*angle_defP,
    A_FloatLong \*fp_valueP);
    | 45 | | | | 46 | | `ValueFromAngleDef` | | 47 | +-----------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 48 | -------------------------------------------------------------------------------- /docs/effect-details/pixel-aspect-ratio.md: -------------------------------------------------------------------------------- 1 | # Pixel Aspect Ratio 2 | 3 | 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. 4 | 5 | Simple effects needn't do any work to match up [point parameters](../effect-basics/parameters.md) 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. 6 | 7 | --- 8 | 9 | ## Don't Assume Pixels Are Square, Or 1-To-1 10 | 11 | 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. 12 | 13 | Second, even if it *is* a square coordinate system, it's not necessarily the same size as the final output. This means that any slider which defines a size in pixels will be a problem when the image is rendered downsampled; the width of anti-aliasing filters changes based on downsample factor. 14 | 15 | 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. 16 | 17 | 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. 18 | 19 | If an effect already has coordinate transformation machinery in its pipeline, there's an alternative that's often simpler. Many algorithms require some sort of coordinate transformation; using matrices to set up a transformation, for example. But there are other easily adaptable algorithms, for example a texture generation effect that computes the value of each pixel based solely on its position. In this case, the code must take the raw pixel position and account for pixel aspect ratio and downsample factor. 20 | 21 | --- 22 | 23 | ## Suggested Approach 24 | 25 | 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. 26 | 27 | 1. When getting your point parameters, go immediately to floating point and a full resolution square pixel system, like this. 28 | 29 | ```cpp 30 | x *= in_data>pixel_aspect_ratio.num / (float)in_data>pixel_aspect_ratio.den; 31 | x *= in_data>downsample_x.den / (float)in_data>downsample_x.num; 32 | y *= in_data>downsample_y.den / (float)in_data>downsample_y.num; 33 | ``` 34 | 35 | 1. Perform all setup (define transformation matrices, generate coordinates for later scan conversion, compute values based on the distance between points, rotating things, et cetera) in this coordinate space. Note that you're not actually dealing with pixels in this stage; you're just manipulating coordinates or coordinate transformations. 36 | 2. 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. 37 | 38 | 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. 39 | 40 | --- 41 | 42 | ## Applying User Input In Pixels 43 | 44 | 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. 45 | 46 | --- 47 | 48 | ## Test Test Test! 49 | 50 | 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. 51 | 52 | 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. 53 | -------------------------------------------------------------------------------- /docs/effect-details/tips-tricks.md: -------------------------------------------------------------------------------- 1 | # Tips & Tricks 2 | 3 | ## Best Practices 4 | 5 | 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. 6 | 7 | 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). 8 | 9 | --- 10 | 11 | ## Responsiveness 12 | 13 | Make your plug-ins as responsive as possible using `PF_ABORT()` and `PF_PROGRESS()` from [Interaction Callbacks](interaction-callback-functions.md#interaction-callbacks). 14 | 15 | We actually test all our effects for interrupt-ability; you'd be surprised how cranky users can get waiting for your pokey effect to finish processing a film resolution sequence! 16 | 17 | After Effects' iteration functions inherently provide this functionality; you don't need to worry about calling the above functions from within your pixel processing functions. 18 | 19 | --- 20 | 21 | ## Make Your Effect Easy To Find 22 | 23 | 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. 24 | 25 | 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. 26 | 27 | Save it to the name by which you want users to find the plug-in. 28 | 29 | Have your plug-in's installer put the resultant .ffx file into the \\Presets directory, next to the After Effects executable. 30 | 31 | Your preset will show up when users search for the name to which it was saved. 32 | 33 | --- 34 | 35 | ## Sampling Pixels At (x,y) 36 | 37 | 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. 38 | 39 | ```cpp 40 | PF_Pixel *sampleIntegral32(PF_EffectWorld &def, int x, int y){ 41 | return (PF_Pixel*)((char*)def.data + 42 | (y * def.rowbytes) + 43 | (x * sizeof(PF_Pixel))); 44 | } 45 | 46 | PF_Pixel16 *sampleIntegral64(PF_EffectWorld &def, int x, int y){ 47 | assert(PF_WORLD_IS_DEEP(&def)); 48 | return (PF_Pixel16*)((char*)def.data + 49 | (y * def.rowbytes) + 50 | (x * sizeof(PF_Pixel16))); 51 | } 52 | ``` 53 | 54 | Special thanks to Paul Miller for answering this question. 55 | 56 | --- 57 | 58 | ## Where's The Center Of A Pixel? 59 | 60 | 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). 61 | 62 | 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. 63 | 64 | The matrix functions (`transform_world` from [PF_WorldTransformSuite1](graphics-utility-suites.md#pf_worldtransformsuite1)) don't have this problem. 65 | 66 | 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). 67 | 68 | --- 69 | 70 | ## Text Layer Origin 71 | 72 | Almost all layer types have their origin in the upper-left corner. Not so with text layers! 73 | 74 | A text layer origin by default is at the bottom-left baseline position of the first character. You can see this if you create a text item and then pick the layer so the anchor point shows up. 75 | 76 | Look at where the default anchor point location is. The transform is not at the corner of the layer rectangle. 77 | 78 | --- 79 | 80 | ## Clean Slate 81 | 82 | 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: 83 | 84 | ```cpp 85 | src_rect.left = in_data>output_origin_x; 86 | src_rect.right = src_rect.left + input>width; 87 | src_rect.top = in_data>output_origin_y; 88 | src_rect.bottom = src_rect.top + input>height; 89 | 90 | err = PF_FILL(NULL, NULL, output); 91 | 92 | if (!err) { 93 | err = PF_COPY(¶ms[0]>u.ld, output, NULL, &src_rect); 94 | } 95 | ``` 96 | 97 | --- 98 | 99 | ## Caching Behavior 100 | 101 | After Effects provides numerous ways to specify caching behavior. `PF_OutFlag_NON_PARAM_VARY`, `PF_OutFlag_WIDE_TIME_INPUT`, `PF_OutFlag_I_USE_SHUTTER_ANGLE`, `PF_OutFlag_I_SYNTHESIZE_AUDIO`, `PF_OutFlag2_I_USE_3D_CAMERA`, and `PF_OutFlag2_I_USE_3D_LIGHTS` (all from [PF_OutFlags](../effect-basics/PF_OutData.md#pf_outflags)) all influence caching decisions. 102 | 103 | Supporting [dynamic outflags](../effect-basics/PF_OutData.md#pf_outflags) can greatly improve performance, preventing After Effects from invalidating your effect's cache as aggressively as it otherwise would. 104 | 105 | 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? 106 | 107 | --- 108 | 109 | ## Global Performance Cache Consideratons 110 | 111 | 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: 112 | 113 | 1. In Preferences > Media & Disk Cache, disable the Disk Cache 114 | 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) 115 | 3. Relaunch 116 | 117 | If you ever encounter a glitch, it likely a legitimate bug in your effect, such as improper rectangle handling in SmartFX. 118 | 119 | On the other hand, if you fix a rendering bug in your plug-in and ship an update, you can't expect all users will empty their disk caches. A user may have a disk cache of the buggy frame and it needs to be invalidated. What to do? Update your plug-in's effect version. This value (and the AE build number) is part of the cache key, so if you update it any frames cached containing content from your plug-in will no longer match. 120 | 121 | --- 122 | 123 | ## Some Thoughts On Time From A Long-Time Developer 124 | 125 | Stoney Ballard put together the following summary of how time works with effects; you may find it helpful. 126 | 127 | There are five `in_data` parameters that describe time to a filter: 128 | 129 | - `current_time` 130 | - `time_step` 131 | - `local_time_step` 132 | - `total_time` 133 | - `time_scale` 134 | 135 | Their values are dependent on: 136 | 137 | - The frame being rendered 138 | - The duration of the layer and composition The frame rate of the comp 139 | - Any Time Stretch Any Time Remapping 140 | - The time behavior of an outer composition (one enclosing the composition with the layer being filtered) 141 | - The setting of the "Preserve frame rate when nested or in render queue" (PFR) switch 142 | 143 | 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 144 | 145 | 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. 146 | 147 | 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 layer is. This may cause total_time to be larger. It has nothing to do with the actual time map, just whether or not it's enabled. 148 | 149 | 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. 150 | 151 | 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. 152 | 153 | Looked at from the other direction: 154 | 155 | 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. 156 | 157 | The value of local_time_step is affected only by Time Stretch. It can never be zero, but it can be negative. 158 | 159 | 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). 160 | 161 | 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. 162 | 163 | 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. 164 | 165 | 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 166 | 167 | 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. 168 | 169 | --- 170 | 171 | ## Rate x Time == Pain! 172 | 173 | 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. 174 | 175 | 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. 176 | 177 | --- 178 | 179 | ## Testing 180 | 181 | 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? 182 | 183 | If you receive `PF_Err_OUT_OF_MEMORY` (from [Error Codes](../effect-basics/errors.md#error-codes)) when requesting memory, do you pass it back to After Effects? 184 | 185 | What happens when your video effect is applied to an audio-only layer? Test with projects created using older versions of your plug-in. 186 | -------------------------------------------------------------------------------- /docs/effect-ui-events/PF_EventExtra.md: -------------------------------------------------------------------------------- 1 | # PF_EventExtra 2 | 3 | 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](../effect-basics/entry-point.md) function. 4 | 5 | The `PF_EventUnion` (sent in the `PF_EventExtra`) varies with the event type, and contains information specific to that event. 6 | 7 | +-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 8 | | Member | Purpose | 9 | +=================+========================================================================================================================================================================================+ 10 | | `contextH` | Handle to the `PF_Context`. | 11 | | | | 12 | | | This drawing context is used with the [Drawbot suites](custom-ui-and-drawbot.md) for drawing, and also for the [UI Callbacks](ui-callbacks.md). | 13 | +-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 14 | | `e_type` | Which [event](effect-ui-events.md) is occurring. | 15 | +-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 16 | | `u` | A [PF_EventUnion](PF_EventUnion.md) containing information specific to the event. | 17 | +-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 18 | | `effect_win` | A `PF_EffectWindowInfo` about the event if it occurs within the effects window. | 19 | | | | 20 | | | Otherwise, as of After Effects 5.0, effect_win can be replaced by a `PF_WindowUnion`. | 21 | | | | 22 | | | This struct contains both a `PF_EffectWindowInfo` and an `PF_ItemWindowInfo`, which (for now) is simply the port rectangle for the item window. | 23 | | | | 24 | | | Replacement only occurs if `PF_USE_NEW_WINDOW_UNION` was defined during compilation; otherwise, it will continue to be just a `PF_EffectWindowInfo`. | 25 | +-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 26 | | `cbs` | Pointer to [UI Callbacks](ui-callbacks.md), which are needed to translate points between layer, composition, and screen coordinate systems. | 27 | +-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 28 | | `evt_in_flags` | Event Input Flags. This currently contains only one value, `PF_EI_DONT_DRAW`, which you should check before drawing! | 29 | +-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 30 | | `evt_out_flags` | One or more of the following, combined with a bitwise OR operation: | 31 | | | | 32 | | | - `PF_EO_NONE` | 33 | | | - `PF_EO_HANDLED_EVENT` tells After Effects you've handled the event. | 34 | | | - `PF_EO_ALWAYS_UPDATE` forces After Effects to rerender the composite in response to every click or drag; this is the same behavior generated by 'alt-scrubbing' the parameter value. | 35 | | | - `PF_EO_NEVER_UPDATE` prevents After Effects from rerendering the composite until the user stops clicking and dragging. | 36 | | | - `PF_EO_UPDATE_NOW` tells After Effects to update the view immediately after the event returns after calling `PF_InvalidateRect` | 37 | +-----------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 38 | 39 | 40 | --- 41 | 42 | ## PF_Context 43 | 44 | PF_Context details the event's UI context. 45 | 46 | +--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 47 | | Member | Purpose | 48 | +====================+====================================================================================================================================================================+ 49 | | `magic` | Do not change. | 50 | +--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 51 | | `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?). | 52 | | | | 53 | | | - `PF_Window_COMP`, | 54 | | | - `PF_Window_LAYER`, | 55 | | | - `PF_Window_EFFECT` | 56 | +--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 57 | | `reserved_flt` | Do not change. | 58 | +--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 59 | | `plugin_state[4]` | An array of 4 `A_longs` which the plug-in can use to store state information for a given context. | 60 | +--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 61 | | `reserved_drawref` | A `DRAWBOT_DrawRef` for use with the [Drawbot suites](custom-ui-and-drawbot.md). | 62 | +--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 63 | | `*reserved_paneP` | Do not change. | 64 | +--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 65 | 66 | --- 67 | 68 | ## PF_EffectWindowInfo 69 | 70 | If an event occurs in the ECP, an PF_EffectWindowInfo is sent in PF_EventExtra. 71 | 72 | +---------------------+--------------------------------------------------------------------------------------------------------------------------------------------+ 73 | | Member | Purpose | 74 | +=====================+============================================================================================================================================+ 75 | | `index` | This indicates which parameter in the effect window is being affected. The controls are numbered from 0 to the number of controls minus 1. | 76 | +---------------------+--------------------------------------------------------------------------------------------------------------------------------------------+ 77 | | `area` | This indicates if the control title (`PF_EA_PARAM_TITLE`) or the control itself (`PF_EA_CONTROL`) are being affected. | 78 | | | | 79 | | | The title is the area still visible when the parameter's topic ("twirly") is spun up. | 80 | +---------------------+--------------------------------------------------------------------------------------------------------------------------------------------+ 81 | | `current_frame` | A PF_Rect indicating the full frame of the area occupied by the control. | 82 | +---------------------+--------------------------------------------------------------------------------------------------------------------------------------------+ 83 | | `param_title_frame` | A PF_Rect indicating the title area of the control. | 84 | +---------------------+--------------------------------------------------------------------------------------------------------------------------------------------+ 85 | | `horiz_offset` | A horizontal offset from the left side of the title area in which to draw into the title. | 86 | +---------------------+--------------------------------------------------------------------------------------------------------------------------------------------+ 87 | -------------------------------------------------------------------------------- /docs/effect-ui-events/effect-ui-events.md: -------------------------------------------------------------------------------- 1 | # Effect UI & Events 2 | 3 | Effects can provide custom UI in two areas: (1) the Effect Controls Window (custom ECW UI), and (2) the Composition or Layer Windows (Custom Comp UI). 4 | 5 | Effects that use custom UI should set `PF_OutFlag_CUSTOM_UI` (from [PF_OutFlags](../effect-basics/PF_OutData.md#pf_outflags) during `PF_Cmd_GLOBAL_SETUP` (from [Global Selectors](../effect-basics/command-selectors.md#global-selectors)), and handle the PF_Cmd_EVENT selector. 6 | 7 | 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](../effect-details/arbitrary-data-parameters.md#arbitrary-data-parameters). 8 | 9 | Parameters that have a custom UI should set `PF_PUI_CONTROL` (from [Parameter UI Flags](../effect-basics/PF_ParamDef.md#parameter-ui-flags)) when [adding the parameter](../effect-details/interaction-callback-functions.md#interaction-callbacks). 10 | 11 | Custom Comp UI allows an effect to provide direct manipulation of the video in the Composition or Layer Windows. 12 | 13 | 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. 14 | 15 | Effects should register themselves to receive events by calling PF_REGISTER_UI. 16 | 17 | After Effects can send events to effects for user interface handling and parameter management, integrating effects into its central message queue. 18 | 19 | While many events are sent in response to user input, After Effects also sends events to effects which manage arbitrary data parameters. 20 | 21 | The type of event is specified in [PF_EventExtra->e_type](PF_EventExtra.md#pf_eventextra) and the various events are described below. 22 | 23 | --- 24 | 25 | ## Events 26 | 27 | +--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ 28 | | Event | Indicates | 29 | +==========================+=================================================================================================================================================+ 30 | | `PF_Event_NEW_CONTEXT` | The user created a new context (probably by opening a window) for events. | 31 | | | | 32 | | | The plug-in is allowed to store state information inside the context using the context handle. | 33 | | | | 34 | | | [PF_EventUnion](PF_EventUnion.md#pf_eventunion) contains valid context and type, but everything else should be ignored. | 35 | +--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ 36 | | `PF_Event_ACTIVATE` | The user activated a new context (probably by bringing a window into the foreground). [PF_EventUnion](PF_EventUnion.md#pf_eventunion) is empty. | 37 | +--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ 38 | | `PF_Event_DO_CLICK` | The user clicked within the effect's UI. [PF_EventUnion](PF_EventUnion.md#pf_eventunion) contains a `PF_DoClickEventInfo`. | 39 | | | | 40 | | | Handle the mouse click and respond, passing along drag info; see sample code), within a context. | 41 | | | | 42 | | | !!! note | 43 | | | As of 7.0, do *not* block until mouse-up; instead, rely on `PF_Event_DRAG`. | 44 | +--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ 45 | | `PF_Event_DRAG` | Also a Click Event, [PF_EventUnion](PF_EventUnion.md#pf_eventunion) contains a `PF_DoClickEventInfo`. | 46 | | | | 47 | | | Request this by returning `send_drag == TRUE` from `PF_Event_DO_CLICK`. | 48 | | | | 49 | | | Do this so After Effects can see new data from the user's changes. | 50 | +--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ 51 | | `PF_Event_DRAW` | Draw! [PF_EventUnion](PF_EventUnion.md#pf_eventunion) contains a `PF_DrawEventInfo`. | 52 | +--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ 53 | | `PF_Event_DEACTIVATE` | The user has deactivated a context (probably by bringing another window into the foreground). `PF_EventUnion` is empty. | 54 | +--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ 55 | | `PF_Event_CLOSE_CONTEXT` | A context has been closed by the user. `PF_EventUnion` will be empty. | 56 | +--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ 57 | | `PF_Event_IDLE` | A context is open but nothing is happening. `PF_EventUnion` is empty. | 58 | +--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ 59 | | `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`. | 60 | | | | 61 | | | Use OS-specific calls to implement a custom cursor; tell After Effects you've done so by setting `PF_CursorType` to `PF_Cursor_CUSTOM`. | 62 | | | | 63 | | | Use an After Effects cursor whenever possible to preserve interface continuity. | 64 | +--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ 65 | | `PF_Event_KEYDOWN` | Keystroke. [PF_EventUnion](PF_EventUnion.md#pf_eventunion) contains a `PF_KeyDownEvent`. | 66 | +--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ 67 | | `PF_Event_MOUSE_EXITED` | New in CS6. Notification that the mouse is no longer over a specific view (layer or comp only). | 68 | +--------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------+ 69 | -------------------------------------------------------------------------------- /docs/effect-ui-events/tips-and-tricks.md: -------------------------------------------------------------------------------- 1 | # Tips & Tricks 2 | 3 | ## UI Performance 4 | 5 | Experiment with `PF_EO_ALWAYS_UPDATE` and `PF_EO_NEVER_UPDATE` from [PF_EventExtra](PF_EventExtra.md), to find a happy medium between responsiveness and accuracy. 6 | 7 | On macOS, the foreground and background colors are not set to white and black when custom UI draw events are sent. 8 | 9 | This is by design; you don't have to change the background color when you're drawing directly into our context. 10 | 11 | --- 12 | 13 | ## How Deep Are My Pixels? 14 | 15 | There is no way to determine the bit depth of the layer(s) being processed during events. 16 | 17 | However, you can cache the last-known pixel depth in your sequence data. 18 | 19 | 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. 20 | 21 | You can also check the depth of your input world during `PF_Cmd_RENDER`. 22 | 23 | --- 24 | 25 | ## Arbitrary Data 26 | 27 | An arbitrary data parameter is an excellent way to manage your custom UI. 28 | 29 | Store state, preference, and last-item-used information in an arb, and you'll always be able to recover it. 30 | 31 | After Effects manages parameters with a much richer message stream than custom UIs. 32 | 33 | --- 34 | 35 | ## Custom UI Implementation for Color Sampling, Using Keyframes 36 | 37 | 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. 38 | 39 | 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. 40 | 41 | The plug-in stores the color value in sequence data, and cancels the render, requesting a redraw of the affected parameter(s). 42 | 43 | Finally, during the draw, the plug-in adds appropriate keyframes to its color parameter stream using the [AEGP_KeyframeSuite](../aegps/aegp-suites.md#aegp_keyframesuite3). 44 | 45 | Yes, this means the effect needs to [Cheating Effect Usage of AEGP Suites](../aegps/cheating-effect-usage-of-aegp-suites.md) and use the AEGP API. 46 | -------------------------------------------------------------------------------- /docs/history.md: -------------------------------------------------------------------------------- 1 | # Version History 2 | 3 | | Revision Date | Documentor | Notes | 4 | | ---------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 5 | | 24 Feb 2025 | Sean Jenkin | 25.2 SDK Release - AEGP_GetLayerObjectType can now return AEGP_ObjectType_3D_MODEL if the object type is a 3D model | 6 | | 5 May 2023 | Jason Bartell | Update Color Settings suite to AEGP_ColorSettingsSuite5 with new OCIO calls, and added URL property to the PiPL. See [AEGP_ColorSettingsSuite5](aegps/aegp-suites.md#aegp_colorsettingssuite5) and [PiPL Resources](intro/pipl-resources.md) respectively for more details. | 7 | | 18 October 2022 | Field Kuang | Update layer suite to AEGP_LayerSuite9 with 3 new Track Matte methods. See [AEGP_LayerSuite9](aegps/aegp-suites.md#aegp_layersuite9) for more details | 8 | | 26 October 2021 | Sean Jenkin | After Effects 2022 (22.0) release. Updates the maxiumum threads for PF_Iterate. | 9 | | 31 March 2021 | Sean Jenkin | Updated Multi-Frame Rendering documentation for sequence_data changes and Compute Cache system. Added information for supporting Universal Mac binaries for Apple Silicon effect plugins. | 10 | | 1 June 2020 | Field Kuang | Multi-Frame Rendering is now supported in AE Beta builds. See [Multi-Frame Rendering in AE](effect-details/multi-frame-rendering-in-ae.md) for more details. | 11 | | 1 November 2018 | Bruce Bullis | 16.0 release | 12 | | 10 November 2017 | Zac Lam | 15.0 release | 13 | | 12 May 2017 | Zac Lam | CC 2017.1 (14.2) release | 14 | | 2 November 2016 | Zac Lam | CC 2017 (14.0) release. | 15 | | 21 July 2015 | Zac Lam | CC 2015 (13.5) release. | 16 | | 12 June 2014 | Zac Lam | CC 2014 (13.0) release. Corrections for accuracy. Removed old version references. | 17 | | 15 July 2013 | Zac Lam | CC (12.0) release. API version changes, misc small clarifications, more details in [AEIOs](aeios/aeios.md). | 18 | | 26 April 2012 | Zac Lam | CS6 (11.0) release. Big reorganization of the [AEGPs](aegps/aegps.md) and [Artisans](artisans/artisans.md). Many additions throughout. | 19 | | 2 May 2011 | Zac Lam | CS5.5 (10.5) release. | 20 | | 28 April 2010 | Zac Lam | CS5 (10.0) release. 64-bit porting info. Drawbot. | 21 | | 4 May 2009 | Zac Lam | CS4 (9.0) release. Complete reorganization of first three chapters. Fleshed out documentation on Premiere Pro. | 22 | | 1 July 2007 | Bruce Bullis | CS3 (8.0) release. | 23 | | 4 April 2006 | Bruce Bullis | Updated to reference new development system requirements and Xcode-specific issues. Some editing. | 24 | | 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. | 25 | | 4 April 2004 | Bruce Bullis | Updated for 6.5. Expanded and corrected all documentation. Added documentation of all new AEGP functions. | 26 | | 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. | 27 | | 4 March 2002 | Bruce Bullis | Updated Mac OS X details, expanded AEIO and AEGP documentation. | 28 | | 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. | 29 | | 2 February 2001 | Bruce Bullis | 5.0 release. Entire document edited and reformatted. Sections on 16 bit-per-channel color and parameter supervision, as well as the entire AEGP chapter, have all substantially expanded. | 30 | | 9 September 1999 | Bruce Bullis | Revised for 4.1; added General plug-ins and AEGP information. Added information on new selectors, resize handle. | 31 | | 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. | 32 | | 1 May 1998 | Bruce Bullis | Version 3.1 SDK Release 6 - Editorial changes only | 33 | | 17 April 1997 | Brian Andrews | Version 3.1 SDK Release 3 - First public release (really a pre-release) of the SDK for Windows development. | 34 | | 13 Nov. 1996 | Brian Andrews | Version 3.1 SDK Release 2 - Minor updates. | 35 | | 21 June 1996 | Brian Andrews | Version 3.1 - Final 3.x release. | 36 | | 5 March 1996 | Brian Andrews | Version 3.0 - Preliminary release for the After Effects developer kitchen. | 37 | | August 1994 | Dave Herbstman Dan Wilk | Version 2.0.1 - Added support for PowerPC. | 38 | | January 1994 | Dan Wilk | Version 2.0 - Updates. | 39 | | January 1993 | Russell Belfer | Version 1.0 - Initial SDK release. | 40 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Welcome to the Adobe® After Effects® Software Development Kit! 4 | 5 | This is a living document and is constantly being updated and edited. The latest public version of the SDK is available at: [https://www.adobe.io/after-effects/](https://www.adobe.io/after-effects/) 6 | 7 | If you need more information, your question may already be answered on the After Effects SDK forum: [After Effects SDK Forum](https://community.adobe.com/t5/after-effects/bd-p/after-effects?page=1&sort=latest_replies&filter=all&topics=label-sdk) 8 | 9 | Use the search box there, and post a new question if your question hasn’t already been answered. 10 | 11 | --- 12 | 13 | ## About 14 | 15 | 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. 16 | 17 | 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. 18 | 19 | As opportunity allows, we'll try to include more diagrams, illustrations, and purdy pickshurs explaining API intricacies. 20 | 21 | As always, your input is valued and appreciated. 22 | 23 | --- 24 | 25 | ## Organization 26 | 27 | The [What Can I Do With This SDK?](intro/what-can-i-do.md) 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. 28 | 29 | The basics of effect plug-ins are discussed in [Effect Basics](effect-basics/effect-basics.md). 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. 30 | 31 | [Effect Details](effect-details/effect-details.md) 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. 32 | 33 | [SmartFX](smartfx/smartfx.md) is the extension to the effect plug-in API to support 32-bit floating point images. 34 | 35 | [Effect UI & Events](effect-ui-events/effect-ui-events.md) 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. 36 | 37 | [Audio](audio/audio.md) effects are covered in... [Audio](audio/audio.md). 38 | 39 | [AEGPs](aegps/aegps.md) 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. 40 | 41 | [Artisans](artisans/artisans.md) covers specialized plug-in 3D renderer AEGPs. 42 | 43 | [AEIOs](aeios/aeios.md), specialized AEGPs which handle file input and output. 44 | 45 | [Premiere Pro & Other Hosts](ppro/ppro.md) discusses issues related to compatibility with Premiere Pro and other applications that support a subset of After Effects plug-ins. 46 | 47 | --- 48 | 49 | ## Documentation Conventions 50 | 51 | Functions, structure names and general C/C++ code are in Courier; MyStruct and MyFunction(); 52 | 53 | Text in blue is hyperlinked. 54 | 55 | Command selectors are italicized; *PF_Cmd_RENDER*. 56 | 57 | --- 58 | 59 | ## A Note About Coding Style 60 | 61 | 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. 62 | 63 | ### Coding Conventions 64 | 65 | | Type | Suffix | Example | 66 | | ------------------------------------------------ | -------- | ---------------- | 67 | | Handle | `H` | `fooH` | 68 | | pointer (to) | `P` | `fooP` | 69 | | Boolean | `B` | `visibleB` | 70 | | Float | `F` | `degreesF` | 71 | | Long | `L` | `offsetL` | 72 | | unsigned long | `Lu` | `countLu` | 73 | | short | `S` | `indexS` | 74 | | char | `C` | `digitC` | 75 | | unsigned char | `Cu` | `redCu` | 76 | | function pointer | `\_func` | `sample_func` | 77 | | time value | `T` | `durationT` | 78 | | `char*` (NULL-terminated C string) | `Z` | `nameZ` | 79 | | rectangle | `R` | `boundsR` | 80 | | fixed rectangle | `FiR` | `boundsFiR` | 81 | | float rectangle | `FR` | `boundsFR` | 82 | | ratio | `Rt` | `scale_factorRt` | 83 | | `void*` | `PV` | `refconPV` | 84 | | optional parameter (must be passed, can be NULL) | `0` | `extra_flags0` | 85 | -------------------------------------------------------------------------------- /docs/intro/apple-silicon-support.md: -------------------------------------------------------------------------------- 1 | # Apple Silicon Support 2 | 3 | Adobe now supports Apple Silicon effect plugins in some products running natively on Apple Silicon. For instance, After Effects effect plugins are also available in Adobe Premiere Pro and Adobe Media Encoder. 4 | 5 | Not all Adobe products have native Apple Silicon versions yet, but in those that do, only effect plugins with Apple Silicon implementations will be available. We recommend adding the Apple Silicon target soon in anticipation of rapid adoption of these new M1 machines. 6 | 7 | !!! note 8 | In order to build a Mac Universal binary, you will need Xcode 12.2 or greater. 9 | 10 | To learn more about Universal binaries, please visit [https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary](https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary) 11 | 12 | Loading plugins on macOS 15+ for debugging also requires an additional signing step. See [here](debugging-plug-ins.md#signing-requirments-and-loading-unsigned-plug-ins) for details. 13 | 14 | --- 15 | 16 | ## How to add Universal Binary Support for your Plugins 17 | 18 | 1. Open your plugins Xcode project in 12.2 or above and Xcode will automatically add an Apple Silicon target for you. 19 | 20 | ![Mac Universal Build](../_static/mac_universal_build.png "Mac Universal Build") 21 | *Mac Universal Build* 22 | 23 | 1. Tell After Effects what the main entry point is for Apple Silicon builds. 24 | 25 | > * Find the .r resource file for your plugin. 26 | > * Add `CodeMacARM64 {"EffectMain"}` next to your existing Intel Mac entry point definition. 27 | > ```cpp 28 | > #if defined(AE_OS_MAC) 29 | > CodeMacARM64 {"EffectMain"}, 30 | > CodeMacIntel64 {"EffectMain"}, 31 | > #endif 32 | > ``` 33 | > * If for some reason you need different entry points on x64 and ARM just provide a different entry point name and string. 34 | 35 | 3. Compile the Universal binary by building for the Any Mac (Apple Silicon, Intel) Target, or by using Product -> Archive. 36 | 37 | Assuming there are no compile time issues with the Apple Silicon build, you can now use the single Universal binary for both Intel and Apple Silicon applications. 38 | 39 | --- 40 | 41 | ## Exception Behavior with Apple Silicon Across "C" Functions 42 | 43 | Extra care should be taken when using exceptions on Apple Silicon. In many environments throwing exceptions that propagate through traditional "C" functions worked fine. It was bad practice, with undefined behavior, but generally "worked". 44 | 45 | On Apple Silicon, rather than undefined behavior the ABI has changed so terminate() is called when this occurs. 46 | 47 | Since the main entry point of a plugin is always an extern "C" calling convention, this code should be wrapped in a try/catch block to prevent program termination. For example: 48 | 49 | ```cpp 50 | PF_Err EffectMain ( PF_Cmd cmd, 51 | PF_InData *in_data, 52 | PF_OutData *out_data, 53 | PF_ParamDef *params[], 54 | PF_LayerDef *output ) 55 | { 56 | try 57 | { 58 | /* Your code here */ 59 | } 60 | catch 61 | { 62 | /* return most appropriate PF_Err */ 63 | } 64 | } 65 | ``` 66 | -------------------------------------------------------------------------------- /docs/intro/compatibility-across-multiple-versions.md: -------------------------------------------------------------------------------- 1 | # Compatibility Across Multiple Versions? 2 | 3 | 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. 4 | 5 | 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](../effect-basics/PF_InData.md).version for effects, or in the major and minor_versionL passed into your AEGP in the [Entry Point](../aegps/implementation.md#entry-point). 6 | 7 | For even more precise version checking, a plug-in can run a script using `AEGP_ExecuteScript` ([AEGP_UtilitySuite6](../aegps/aegp-suites.md#aegp_utilitysuite6)), querying one of the following attributes: 8 | 9 | ```cpp 10 | app.version - e.g. 11.0.1x12 11 | app.buildNumber - e.g. 12. 12 | ``` 13 | 14 | --- 15 | 16 | ## API Versions 17 | 18 | | Release | Effect API Version | AEGP API Version | 19 | | ---------------------- | ------------------------------------------------------------------------------------------------------------ | ---------------- | 20 | | 22.0 | 13.27 | | 21 | | 18.2 | 13.25 | | 22 | | 18.0 | 13.24 | | 23 | | 17.7 | 13.23 | | 24 | | 17.6 | 13.22 | | 25 | | 17.5 | 13.21 | | 26 | | 17.3 | 13.20 | | 27 | | 17.1 | 13.19 | | 28 | | 17.0 | 13.18 | | 29 | | 16.1 | 13.17 | | 30 | | 16.0 | 13.16 | | 31 | | 15.0 | 13.15 | | 32 | | CC 2017.1 (14.2) | 13.14 | | 33 | | CC 2017 (14.0) | 13.13 | 114.0 | 34 | | CC 2015.3 (13.8) | 13.11 | 113.8 | 35 | | CC 2015 (13.7) | 13.10 | 113.7 | 36 | | CC 2015 (13.6) | 13.10 | | 37 | | CC 2015 (13.5, 13.5.1) | 13.9 | 113.5 | 38 | | CC 2014 (13.0-13.2) | 13.7 | 113 | 39 | | CC (12.2) | 13.6 | 112.2 | 40 | | CC (12.1) | 13.5 | 112.1 | 41 | | CC (12.0) | 13.4 | 112.0 | 42 | | CS6.0.1 (11.0.1) | 13.3 | 111.0 | 43 | | CS6 (11.0) | 13.2 | 111.0 | 44 | | CS5.5 (10.5) | 13.1 | 17.0 | 45 | | CS5 (10.0) | 13.0 | 17.0 | 46 | | CS4 (9.0) | 12.14 | 16.24 | 47 | | CS3 (8.0) | 12.13 | 16.24 | 48 | | 7.0 | 12.12 | | 49 | | 6.5, 6.0 | 12.10 (Check for the presence of updated AEGP suites, should you need to differentiate between 6.0 and 6.5.) | | 50 | | 5.0 | 12.5 | | 51 | | 4.1 | 12.2 | | 52 | | 3.1 | 11.6 | | 53 | -------------------------------------------------------------------------------- /docs/intro/debugging-plug-ins.md: -------------------------------------------------------------------------------- 1 | # Debugging Plug-ins 2 | 3 | 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. 4 | 5 | Once you've got the plug-in building directly into the plug-ins folder as explained above, here's how to specify After Effects as the application to run during debug sessions: 6 | 7 | ### Windows 8 | 9 | 1. In the Visual Studio solution, in the Solution Explorer panel, choose the project you want to debug 10 | 2. Right-click it and choose Set as StartUp Project 11 | 3. Right-click it again and choose Properties 12 | 4. In Configuration Properties > Debugging > Command, provide the path to the executable file of the host application the plug-ins will be running in (this may be After Effects or Premiere Pro) 13 | 5. From there you can either hit the Play button, or you can launch the application and later at any point choose Debug > Attach to Process... 14 | 15 | ### macOS 16 | 17 | 1. In Xcode, in the Project Navigator, choose the xcodeproj you want to debug 18 | 2. Choose Product > Scheme > Edit Scheme... 19 | 3. Under Run, in the Info tab, for Executable, choose the host application the plug-ins will be running in (this may be After Effects or Premiere Pro) 20 | 4. From there you can either hit the Play button to build and run the current scheme, or you can launch the application and later at any point choose Debug > Attach to Process. 21 | 22 | #### Signing requirments and loading unsigned plug-ins 23 | 24 | macOS versions 15+ prevent the loading of unsigned plugins. During development, you can avoid this difficulty by adding ad-hoc signing as a custom build step. 25 | 26 | `codesign --force --deep --sign - /path/to/plugin.dylib` 27 | 28 | Note: Yes, that trailing '-' after '--sign' is important. 29 | 30 | When you are ready to release, ensure that you do _not_ make changes to the plug-in package after signing, as this will invalidate said signing and prevent the plug-in from loading. 31 | 32 | --- 33 | 34 | ## Deleting Preferences 35 | 36 | 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. 37 | 38 | You may delete the preferences and restart After Effects with a clean slate by holding down Ctrl-Alt-Shift / Cmd-Opt-Shift during launch. 39 | 40 | On Windows, the preferences are stored here: `[user folder]\AppData\Roaming\Adobe\After Effects\[version]\Adobe After Effects [version]-x64 Prefs.txt` 41 | 42 | On macOS, they are stored here: `~/Library/Preferences/Adobe/After Effects/[version]/Adobe After Effects [version]-x64 Prefs` 43 | -------------------------------------------------------------------------------- /docs/intro/exceptions.md: -------------------------------------------------------------------------------- 1 | # Exceptions 2 | 3 | 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. 4 | 5 | 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. 6 | 7 | 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. 8 | -------------------------------------------------------------------------------- /docs/intro/how-to-start-creating-plug-ins.md: -------------------------------------------------------------------------------- 1 | # How To Start Creating Plug-ins 2 | 3 | ## Play! 4 | 5 | Before you write a line of code, Spend some significant time playing with After Effects, and with the [Sample Projects](sample-projects.md). Build the plug-ins into the right folder. Set lots of breakpoints, read the amusing and informative comments. 6 | 7 | See a quickstart video on building an effect (on macOS): [quickstart video](https://assets.adobe.com/public/08c43fb7-4633-4007-5201-b3b77405d770?scid=social_20180227_75678337) 8 | 9 | --- 10 | 11 | ## Plan! 12 | 13 | Be clear on what your plug-in will attempt to do. 14 | 15 | --- 16 | 17 | ## Hack! 18 | 19 | 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. 20 | 21 | --- 22 | 23 | ## Steal! 24 | 25 | 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. 26 | 27 | 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? 28 | 29 | 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. 30 | 31 | --- 32 | 33 | ## Test! 34 | 35 | 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. 36 | 37 | --- 38 | 39 | ## Blame! 40 | 41 | 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. 42 | 43 | --- 44 | 45 | ## Developers Matter 46 | 47 | 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! 48 | 49 | We work hard on the SDK, and welcome your comments and feedback. Almost every change we make to the API is suggested by developers like you. [Give us feedback](https://community.adobe.com/t5/after-effects/bd-p/after-effects?page=1&sort=latest_replies&filter=all&topics=label-sdkcom) 50 | -------------------------------------------------------------------------------- /docs/intro/localization.md: -------------------------------------------------------------------------------- 1 | # Localization 2 | 3 | Starting in CC, PF App Suite ([Useful Utility Functions](../effect-details/useful-utility-functions.md)) adds `PF_AppGetLanguage()` to query the current language so that a plug-in can use the correct language string. 4 | 5 | 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_PARAM_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 macOS, use the encoding returned by `GetApplicationTextEncoding()`. 6 | 7 | Testing with different languages in AE doesn't require an OS reinstallation, but it does require a reinstallation of AE: 8 | 9 | ### Windows 10 | 11 | - Change the system locale to the targeted language (control panel > region and language > administrative tab > change system locale) 12 | - Restart machine 13 | - Install AE in the according language. 14 | 15 | ### MacOS 16 | 17 | - Set targeted language to the primary language in the preferred language list 18 | - Install AE in the according language. 19 | -------------------------------------------------------------------------------- /docs/intro/next-steps.md: -------------------------------------------------------------------------------- 1 | # Next Steps 2 | 3 | You now have an understanding of what plug-ins are, what they can do, and how After Effects communicates with them. 4 | 5 | Next, we will cover the [basics of effects plug-ins](../effect-basics/effect-basics.md). 6 | -------------------------------------------------------------------------------- /docs/intro/other-integration-possibilities.md: -------------------------------------------------------------------------------- 1 | # Other Integration Possibilities 2 | 3 | Although this SDK describes the majority of integration possibilities with After Effects, there are other possibilities not to be overlooked. 4 | 5 | --- 6 | 7 | ## Scripting 8 | 9 | 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](#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. 10 | 11 | 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. 12 | 13 | You can access the After Effects Scripting Guide, and find a link to the scripting forums, on the Adobe I/O website at: [https://www.adobe.io/apis/creativecloud/aftereffects.html](https://www.adobe.io/apis/creativecloud/aftereffects.html) 14 | 15 | 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: 16 | 17 | ```sh 18 | AfterFX -s "app.quit()" 19 | ``` 20 | 21 | Or you can execute this statement to run a .jsx script that includes a quit at the end: 22 | 23 | ```sh 24 | AfterFX -r path_to_jsx_script 25 | ``` 26 | 27 | On Windows, AfterFX.com is the way to get feedback to the console, because AfterFX.com is a command line application. 28 | 29 | --- 30 | 31 | ## HTML5 Panels 32 | 33 | 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 I/O website at: [https://www.adobe.io/apis/creativecloud/aftereffects.html](https://www.adobe.io/apis/creativecloud/aftereffects.html) 34 | 35 | --- 36 | 37 | ## AERender 38 | 39 | 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: [https://helpx.adobe.com/after-effects/using/automated-rendering-network-rendering.html](https://helpx.adobe.com/after-effects/using/automated-rendering-network-rendering.html) 40 | 41 | --- 42 | 43 | ## Premiere Pro Importers 44 | 45 | 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: [https://www.adobe.io/apis/creativecloud/premierepro.html](https://www.adobe.io/apis/creativecloud/premierepro.html) 46 | 47 | 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. 48 | 49 | --- 50 | 51 | ## Mercury Transmit 52 | 53 | Mercury Transmit plug-ins are used for sending video to output hardware for broadcast-quality monitoring. Transmitters are supported across most applications in the Adobe Creative Cloud, including Premiere Pro, After Effects, Prelude, and Character Animator. The Mercury Transmit API is documented in the Premiere Pro SDK, available at: [https://www.adobe.io/apis/creativecloud/premierepro.html](https://www.adobe.io/apis/creativecloud/premierepro.html) 54 | -------------------------------------------------------------------------------- /docs/intro/sdk-audience.md: -------------------------------------------------------------------------------- 1 | # SDK Audience 2 | 3 | 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. 4 | 5 | This SDK guide assumes you understand After Effects from a user's perspective, and basic motion graphics terminology. If you don't, get the [Adobe After Effects Classroom in a Book](http://www.adobepress.com/store/adobe-after-effects-cc-classroom-in-a-book-2017-release-9780134665320), or any of the other fine instructional books on the market. It will help you understand necessary 6 | 7 | topics such as alpha channels, pixel aspect ratio, interlacing, color spaces, and more for After Effects. 8 | 9 | --- 10 | 11 | ## Development Requirements 12 | 13 | The system requirements for After Effects are here: [https://helpx.adobe.com/after-effects/system-requirements.html](https://helpx.adobe.com/after-effects/system-requirements.html) 14 | 15 | The SDK samples have been tested on Xcode 11.3.1 and Xcode 12.4 (for universal binary support with Apple Silicon) on macOS 10.15/11.0, and Microsoft Visual Studio 2019 on Windows 10. 16 | -------------------------------------------------------------------------------- /docs/intro/symbol-export.md: -------------------------------------------------------------------------------- 1 | # Exporting Symbols in Effects 2 | 3 | The After Effects team recently became aware of an issue with conflicting symbols that violate the C++ language One Definition Rule (ODR). 4 | 5 | In early 2021, the version of the Boost library used by After Effects was upgraded to 1.74. Over the last few months we've identified a number of plugins that are also using Boost but are exporting symbols in such a way that After Effects or the plugin may end up calling the incorrect version of Boost leading to hangs and crashes for users. We also identified a number of the AE SDK samples were setup to export all symbols by default which may have been contributing to the problem, assuming they were used as the starting point for other plugins. These have been fixed as part of the March 2021 SDK. 6 | 7 | **The only symbol that After Effects requires to be exported is the entry point of the plugin.** 8 | 9 | An example can be found in the SDK samples in entry.h: 10 | 11 | ```cpp 12 | #ifdef AE_OS_WIN 13 | #define DllExport __declspec( dllexport ) 14 | #elif defined AE_OS_MAC 15 | #define DllExport __attribute__ ((visibility ("default"))) 16 | #endif 17 | ``` 18 | 19 | and then this is applied to the entry point function, for example: 20 | 21 | ```cpp 22 | extern "C" DllExport 23 | PF_Err PluginDataEntryFunction( 24 | PF_PluginDataPtr inPtr, 25 | PF_PluginDataCB inPluginDataCallBackPtr, 26 | SPBasicSuite* inSPBasicSuitePtr, 27 | const char* inHostName, 28 | const char* inHostVersion) 29 | { 30 | PF_Err result = PF_Err_INVALID_CALLBACK; 31 | 32 | result = PF_REGISTER_EFFECT( 33 | inPtr, 34 | inPluginDataCallBackPtr, 35 | "ColorGrid", // Name 36 | "ADBE ColorGrid", // Match Name 37 | "Sample Plug-ins", // Category 38 | AE_RESERVED_INFO); // Reserved Info 39 | 40 | return result; 41 | } 42 | ``` 43 | 44 | --- 45 | 46 | ## Disabling Xcode Symbol Export 47 | 48 | To disable symbol export in Xcode: 49 | 50 | 1. Find the **Apple Clang - Code Generation** section in the **Build** settings for your project. 51 | 2. Set the **Symbols Hidden By Default** to **YES** 52 | 53 | ![Apple Clang Symbols](../_static/appleclang-symbols.png "Apple Clang Symbols") 54 | *Apple Clang Symbols* 55 | 56 | For any specific symbols that must be made public, use the `__attribute__((visibility("default")))` in code. 57 | 58 | More information can be found in Apple's Xcode documentation [https://help.apple.com/xcode/mac/11.4/#/itcaec37c2a6](https://help.apple.com/xcode/mac/11.4/#/itcaec37c2a6) (excerpt below): 59 | 60 | > Symbols Hidden by Default (GCC_SYMBOLS_PRIVATE_EXTERN) 61 | > 62 | > When enabled, all symbols are declared private extern unless explicitly marked to be exported using __attribute__((visibility("default"))) in code. If not enabled, all symbols are exported unless explicitly marked as private extern. 63 | 64 | --- 65 | 66 | ## Disabling Visual Studio Export 67 | 68 | By default, builds from Visual Studio automatically disable symbol exports. To export symbols, you must either supply a module definition file or set the \_\_declspec(dllexport) keyword in the functions definition. 69 | 70 | More information can be found in Microsoft's Visual Studio documentation [https://docs.microsoft.com/en-us/cpp/build/exporting-from-a-dll?view=msvc-160](https://docs.microsoft.com/en-us/cpp/build/exporting-from-a-dll?view=msvc-160) (excerpt below): 71 | 72 | > You can export functions from a DLL using two methods: 73 | > 74 | > 1. Create a module definition (.def) file and use the .def file when building the DLL. Use this approach if you want to export functions from your DLL by ordinal rather than by name. 75 | > 2. Use the keyword __declspec(dllexport) in the function's definition. 76 | > 77 | > When exporting functions with either method, make sure to use the __stdcall calling convention. 78 | -------------------------------------------------------------------------------- /docs/intro/third-party-plug-in-hosts.md: -------------------------------------------------------------------------------- 1 | # Third-party Plug-in Hosts? 2 | 3 | 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](../effect-basics/PF_InData.md)>appl_id. After Effects uses the appl_id 'FXTC'. 4 | 5 | Premiere Pro uses 'PrMr'. As of this writing, no third party hosts support SmartFX, or our AEGP functions. 6 | 7 | Also, see the [Premiere Pro & Other Hosts](../ppro/ppro.md) section. 8 | -------------------------------------------------------------------------------- /docs/intro/what-can-i-do.md: -------------------------------------------------------------------------------- 1 | # What Can I Do With This SDK? 2 | 3 | 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. 4 | 5 | --- 6 | 7 | ## What Plug-Ins Can I Build With This SDK? 8 | 9 | *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. It's often thought that all plug-ins are effects. But effects are just one type of plug-in used by After Effects. 10 | 11 | See a quickstart video on building an effect (on macOS): [adobe.ly/2sjMDwM](https://adobe.ly/2sjMDwM) 12 | 13 | *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 resize within the After Effects UI. They can work with markers and keyframes, and manage the render queue. They can even run scripts. Some examples of built-in AEGPs are the AAF importer, and the SWF exporter. Automatic Duck Pro Import AE is another well-known AEGP. 14 | 15 | *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 Importers](other-integration-possibilities.md#premiere-pro-importers) 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. 16 | 17 | *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](other-integration-possibilities.md#mercury-transmit) is the recommended API. 18 | 19 | *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. 20 | 21 | 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. See: [Other Integration Possibilities](other-integration-possibilities.md). 22 | 23 | --- 24 | 25 | ## Where Do Plug-ins Appear In After Effects? 26 | 27 | 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). 28 | 29 | 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. 30 | 31 | [AEIOs](../aeios/aeios.md) 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. 32 | 33 | 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. 34 | 35 | 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()`. 36 | 37 | Artisans appear in the *Rendering Plug-in* drop-down in the *Advanced* tab of the *Composition Settings* dialog. 38 | 39 | --- 40 | 41 | ## How Does After Effects Interact With Plug-ins? 42 | 43 | Plug-ins, written in C or C++, are bundle packages on macOS and DLLs on Windows. They must contain a Plug-in Property List ([PiPL Resources](pipl-resources.md)) 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. 44 | 45 | For effects plug-ins, After Effects sends command selectors (and relevant information) to the plug-in [Entry Point](../effect-basics/entry-point.md) designated in the effects' [PiPL Resources](pipl-resources.md) 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. 46 | 47 | 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. 48 | 49 | 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. 50 | 51 | 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. 52 | 53 | --- 54 | 55 | ## SDK Contents 56 | 57 | The SDK contains headers defining the After Effects APIs, sample projects demonstrating integration features, and this SDK Guide. 58 | 59 | They are compiled with the SDK header files, which expose various After Effects functionality to be used by the plug-in. 60 | -------------------------------------------------------------------------------- /docs/intro/where-installers-should-put-plug-ins.md: -------------------------------------------------------------------------------- 1 | # Where Installers Should Put Plug-ins 2 | 3 | Installing your plug-ins in the common location will allow them to be loaded by Premiere Pro, if installed. 4 | 5 | On Windows, the common plug-ins folder can be found (as an explicit path) in the following registry entry: `HKLM\SOFTWARE\Adobe\After Effects\[version]\CommonPluginInstallPath` 6 | 7 | On Mac, the common plug-ins folder is at: `/Library/Application Support/Adobe/Common/Plug-ins/[version]/MediaCore` 8 | 9 | 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/` 10 | 11 | Do not use macOS aliases or Windows shortcuts, as these are not traversed by Premiere Pro. 12 | 13 | --- 14 | 15 | ## Do I Have To Install The Plug-ins To The Common Folder? 16 | 17 | 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. 18 | 19 | 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` 20 | 21 | On macOS, the app-specific plug-ins folder is at: `/Applications/Adobe After Effects [version]/Plug-ins/` 22 | 23 | When launched, After Effects recursively descends 10 levels deep into subdirectories of its path. macOS aliases are traversed, but Windows shortcuts are not. Directories terminated by parentheses or preceded by the symbols ¬ (macOS) or ~ (Windows) are not scanned. 24 | 25 | 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. 26 | -------------------------------------------------------------------------------- /docs/ppro/basic-host-differences.md: -------------------------------------------------------------------------------- 1 | # Basic Host Differences 2 | 3 | We've tried to provide robust compatibility for After Effects effect plug-ins in Premiere Pro. 4 | 5 | There are underlying differences in the render pipeline that lead to differences, and we realize the API implementation may not be perfect. 6 | 7 | Below is an overview of some differences the plug-in will encounter when running in Premiere Pro. 8 | 9 | --- 10 | 11 | ## Time Values 12 | 13 | Premiere Pro uses slightly different time values in PF_InData. For example in CS4: 14 | 15 | Rendering in NTSC, time_scale is 60000, time_step is 1001, field gives field order (in After Effects, for field rendering, scale is 2997, step is 50, or for progressive rendering, scale is 2997, step is 100). 16 | 17 | 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). 18 | 19 | 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. 20 | 21 | --- 22 | 23 | ## Rendering Frames 24 | 25 | Premiere is optimized for responsive editing. When scrubbing in the timeline, and changing effect parameters, Premiere will immediately request a low-quality render for immediate display, followed by a high-quality render. So the effect may receive two requests for the same effective time, one at a low resolution, low bit-depth, followed by one at full-resolution, full bit-depth. The resolution requested for each render with take into account the Playback and Paused Resolution set in the Source and Program Monitors: The first request will be at the Playback Resolution, and the second request will be at the Paused Resolution. 26 | 27 | Premiere will also perform speculative rendering, to render a set of frames ahead in the timeline, so that if/when the editor starts playback, the initial frames will be ready. This means that when repositioning the time needle, or when changing effect parameters, Premiere will ask the effect to render a set of frames ahead of the current time. If the frames have previously been rendered and cached, the effect will not see these render requests because the cached frames will be used. 28 | 29 | When rendering frames in Premiere-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. 30 | 31 | --- 32 | 33 | ## Render Order 34 | 35 | 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. 36 | 37 | Multithreaded rendering in Premiere applies to AE effects too. When rendering an AE effect, the request from Premiere passes through a critical section which is used for all commands, except those relating to arbitrary data. The critical section prevents two threads from calling the same instance of the effect at the same time. However, Premiere creates multiple instances of the effect, which can be called concurrently from separate threads. 38 | 39 | 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. 40 | 41 | --- 42 | 43 | ## Frame Dimensions 44 | 45 | Differences between source footage and the project/composition are handled differently. 46 | 47 | 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)`. 48 | 49 | In AE, `width,height` are `(720,480)` and `pixel_aspect_ratio` is `(10,11)`. 50 | 51 | --- 52 | 53 | ## PF_InData 54 | 55 | 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. 56 | 57 | In Premiere Pro, effects receive the quality setting of the monitor window in [PF_InData>quality](../effect-basics/PF_InData.md#pf_indata-members). This differs from After Effects, where the source layer's quality setting is provided here. 58 | 59 | --- 60 | 61 | ## Parameter UI 62 | 63 | Premiere Pro does not honor the [PF_ParamFlag_START_COLLAPSED](../effect-basics/PF_ParamDef.md#parameter-flags) flag. Parameters are always initialized with their twirlies collapsed, and cannot be automatically twirled open by parameter supervision. 64 | 65 | Premiere Pro supports the macro `PF_ADD_FLOAT_EXPONENTIAL_SLIDER()`, which lets you define an exponent. Although this macro is newly added for the CC 2015 release 2 SDK, Premiere Pro has used this for some time in the Fast Color Corrector, in the Input Grey Level parameter. The exponent is used so that although the range is from 0.10 to 10, 1.0 is about in the middle of the slider. The exponent we used was 2.5. Typical values would be from 0.01 to 100. 66 | 67 | Starting in CC 2015, effects will not be sent `PF_Cmd_UPDATE_PARAMS_UI` or `PF_Event_DRAW` when the time needle is moved and there are no keyframes, unless the effect sets `PF_OutFlag_NON_PARAM_VARY`. Effects such as those that draw histograms in the Effect Controls panel will need to be aware of this optimization. 68 | 69 | --- 70 | 71 | ## Missing Suites 72 | 73 | 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: 74 | 75 | | After Effects suite call | Premiere Pro equivalent function | 76 | | --------------------------------------- | -------------------------------- | 77 | | `WorldTransformSuite1()->copy()` | `PF_COPY()` | 78 | | `WorldTransformSuite1()->convolve()` | `in_data->utils->convolve()` | 79 | | `FillMatteSuite2()->fill()` | `PF_FILL()` | 80 | | `PF_PixelDataSuite1->get_pixel_data8()` | `PF_GET_PIXEL_DATA8()` | 81 | 82 | 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. 83 | 84 | --- 85 | 86 | ## A Special Suite for AE Effects Running in Premiere Pro 87 | 88 | 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. 89 | 90 | Note that other suites from the Premiere Pro SDK cannot be used in AE effects. 91 | -------------------------------------------------------------------------------- /docs/ppro/bigger-differences.md: -------------------------------------------------------------------------------- 1 | # Bigger Differences 2 | 3 | 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. 4 | 5 | --- 6 | 7 | ## Pixel Formats 8 | 9 | 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 ["Pixel Formats and Colorspaces" from the Premiere Pro SDK Guide](http://ppro-plugin-sdk.aenhancers.com/universals/pixel-formats-and-color-spaces.html). 10 | 11 | Use the PF Pixel Format Suite (defined in PrAESDKSupport.h) to register for [PF_EffectWorld / PF_LayerDef](../effect-basics/PF_EffectWorld.md) in other pixel formats. Use the Premiere Pixel Format Suite (defined in the aptly-named PrSDKPixelFormatSuite.h) to get black and white values in those pixel formats. 12 | 13 | After Effects functions such as `PF_BLEND()` have not been enhanced to work with pixel formats beyond 8-bit RGB. 14 | 15 | --- 16 | 17 | ## 32-Bit Float Support 18 | 19 | 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. 20 | 21 | 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. 22 | 23 | --- 24 | 25 | ## PF_CHECKOUT_PARAM and Pixel Formats 26 | 27 | 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. 28 | 29 | 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()`. 30 | -------------------------------------------------------------------------------- /docs/ppro/multithreading.md: -------------------------------------------------------------------------------- 1 | # Multithreading 2 | 3 | You may have noticed this flag: `PF_OutFlag2_PPRO_DO_NOT_CLONE_SEQUENCE_DATA_FOR_RENDER`. We advise against setting this flag, as it has been found to cause parameter UI problems. 4 | -------------------------------------------------------------------------------- /docs/ppro/other-hosts.md: -------------------------------------------------------------------------------- 1 | # Other Hosts 2 | 3 | For third-party hosts, the Adobe policy remains: 4 | 5 | !!! quote 6 | 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. 7 | 8 | --- 9 | 10 | ## Reality Sandwich 11 | 12 | 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. 13 | 14 | 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. 15 | 16 | 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. 17 | -------------------------------------------------------------------------------- /docs/ppro/plug-in-installation.md: -------------------------------------------------------------------------------- 1 | # Plug-in Installation 2 | 3 | Use the common plug-in folder as described here: [Where Installers Should Put Plug-ins](../intro/where-installers-should-put-plug-ins.md). 4 | 5 | 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. 6 | 7 | Oh, and you'll also miss out on project interchange and copy / paste between Premiere Pro and After Effects. 8 | -------------------------------------------------------------------------------- /docs/ppro/plug-ins-reloaded.md: -------------------------------------------------------------------------------- 1 | # Plug-Ins... Reloaded 2 | 3 | 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 macOS). The next time the application is launched, the cached information is used wherever possible, rather than loading the plug-ins. 4 | 5 | When debugging, you can always force a reload of all the plug-ins by holding down the Shift key when launching Premiere Pro. 6 | 7 | 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](http://ppro-plugin-sdk.aenhancers.com/) 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. 8 | 9 | --- 10 | 11 | # Effects Presets 12 | 13 | Premiere Pro uses a different preset scheme than After Effects. 14 | 15 | From the Premiere Pro SDK Guide: 16 | 17 | 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: 18 | 19 | 1. Apply a filter to a clip 20 | 2. Set the parameters of the filter, adding keyframes if desired 21 | 3. Right-click on the filter name in the Effect Controls panel, and select "Save Preset..." 22 | 4. Create preset bins if desired by right-clicking in the Effects panel and choosing "New Presets Bin" 23 | 5. Organize the presets in the preset folders 24 | 6. Select the bins and/or presets you wish to export, right-click, and choose "Export Preset" 25 | 26 | Presets should be installed in the Plug-ins directory. Once they are installed in that directory, they will be read-only, and the user will not be able to move them to a different folder or change their names. User-created presets will be modifiable. 27 | 28 | On Windows Vista, these are in the user's hidden AppData folder (e.g. `C:/Users/[user name]/AppData/Roaming/AdobePremiere Pro/[version]/Effect Presets and Custom Items.prfpset`). 29 | 30 | On macOS, they are in the user folder, at `~/Library/Application Support/Adobe/Premiere Pro/[version]/Effect Presets and Custom Items.prfpset`. 31 | 32 | --- 33 | 34 | # Custom ECW UI Over A Standard Data Type 35 | 36 | 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. 37 | -------------------------------------------------------------------------------- /docs/ppro/ppro.md: -------------------------------------------------------------------------------- 1 | # Premiere Pro & Other Hosts 2 | 3 | Adobe Premiere Pro and Adobe Premiere Elements both support the After Effects effect API as described in chapters 2, 3, and 5. 4 | 5 | They offer a thorough host implementation, some the key omissions being 3D-related calls (auxiliary channel information, cameras and lights), 16-bit and SmartFX support, and other utility functions provided by After Effects' AEGP API. 6 | 7 | Both Premiere Pro and Premiere Elements set `PF_InData>appl_id` to 'PrMr'. 8 | 9 | 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. 10 | 11 | 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](http://ppro-plugin-sdk.aenhancers.com) headers. 12 | 13 | | Application Versions | PF_InData> version.major | PF_InData> version.minor | 14 | | -------------------------------------------- | ------------------------ | ------------------------ | 15 | | Premiere Pro CC through Premiere Pro CC 2019 | 13 | 4 | 16 | | Premiere Pro CS6 | 13 | 2 | 17 | | Premiere Pro CS5.5 | 13 | 1 | 18 | | Premiere Pro CS5, Premiere Elements 9 | 13 | 0 | 19 | | Premiere Pro CS4, Premiere Elements 8 | 12 | 5 | 20 | | Premiere Pro CS3, Premiere Elements 4 and 7 | 12 | 4 | 21 | | Premiere Pro 2.0, Premiere Elements 3 | 12 | 3 | 22 | | Premiere Pro 1.5, Premiere Elements 2 | 12 | 2 | 23 | | Premiere Pro 1.0, Premiere Elements 1 | 12 | 1 | 24 | 25 | 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. 26 | -------------------------------------------------------------------------------- /docs/ppro/premiere-elements.md: -------------------------------------------------------------------------------- 1 | # Premiere Elements 2 | 3 | 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. 4 | 5 | The icons are 60x45 PNG files, and are placed here: 6 | 7 | `/[Program Files]/Adobe/Adobe Premiere Elements [version]/Plug-in/Common/Effect/Previews/` 8 | 9 | The filename should be the match name of the effect, which you specify in the [PiPL Resources](../intro/pipl-resources.md), prefixed with "AE." So if the match name was "MatchName", then the filename should be "AE.MatchName.png" 10 | -------------------------------------------------------------------------------- /docs/ppro/unsupported-features.md: -------------------------------------------------------------------------------- 1 | # Unsupported Features 2 | 3 | Premiere Pro is currently known to not support the following features of the After Effects API: 4 | 5 | (If you would like a feature with a "-" bullet, please email [Premiere Pro API Engineering](mailto:bbb@adobe.com) with the feature request. Numbers preceded by an 'F' are feature request numbers, and the others are bug numbers) 6 | 7 | - F7233 - extent_hint support 8 | - F7835 - Multiple PiPLs in a single plug-in 9 | - F7836 - AEGP support 10 | - F7517 - Audio support - if a plug-in sets PF_OutFlag_I_USE_AUDIO in PF_Cmd_GLOBAL_SETUP, it will not be loaded at all 11 | - F9355 - Support PF_ParamFlag_COLLAPSE_TWIRLY 12 | - PF World Transform Suite 13 | - PF AE Channel Suite 14 | - AE's implementation of high bit color depth support 15 | - SmartFX 16 | - 3D support 17 | - PF_SUBPIXEL_SAMPLE(), PF_GET_PIXEL_DATA16() 18 | 19 | --- 20 | 21 | ## But... Why'd You LOAD It If You Can't RUN It?! 22 | 23 | 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. 24 | 25 | If the suite isn't present, return an error. The plug-in will be placed on Premiere Pro's "don't load these" list. 26 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | # Do not modify below line! Inherits common components. 2 | INHERIT: ./docs/_global/mkdocs.yml 3 | 4 | #### Site metadata & nav - update these! 5 | 6 | site_name: After Effects C++ SDK Guide 7 | site_url: https://ae-plugins.docsforadobe.dev/ 8 | repo_url: https://github.com/docsforadobe/after-effects-plugin-guide/ 9 | repo_name: "after-effects-plugin-guide" 10 | 11 | nav: 12 | - Home: index.md 13 | - Version History: history.md 14 | - Introduction: 15 | - What Can I Do With This SDK?: intro/what-can-i-do.md 16 | - Other Integration Possibilities: intro/other-integration-possibilities.md 17 | - SDK Audience: intro/sdk-audience.md 18 | - What's New: intro/whats-new.md 19 | - How To Start Creating Plug-ins: intro/how-to-start-creating-plug-ins.md 20 | - Sample Projects: intro/sample-projects.md 21 | - Debugging Plug-ins: intro/debugging-plug-ins.md 22 | - Compatibility Across Multiple Versions?: intro/compatibility-across-multiple-versions.md 23 | - Third-party Plug-in Hosts?: intro/third-party-plug-in-hosts.md 24 | - PiPL Resources: intro/pipl-resources.md 25 | - Exceptions: intro/exceptions.md 26 | - Where Installers Should Put Plug-ins: intro/where-installers-should-put-plug-ins.md 27 | - Localization: intro/localization.md 28 | - Apple Silicon Support: intro/apple-silicon-support.md 29 | - Exporting Symbols in Effects: intro/symbol-export.md 30 | - Next Steps: intro/next-steps.md 31 | - Effect Basics: 32 | - Effect Basics: effect-basics/effect-basics.md 33 | - Entry Point: effect-basics/entry-point.md 34 | - Command Selectors: effect-basics/command-selectors.md 35 | - PF_InData: effect-basics/PF_InData.md 36 | - PF_OutData: effect-basics/PF_OutData.md 37 | - Parameters: effect-basics/parameters.md 38 | - PF_ParamDef: effect-basics/PF_ParamDef.md 39 | - PF_EffectWorld / PF_LayerDef: effect-basics/PF_EffectWorld.md 40 | - Errors: effect-basics/errors.md 41 | - Effect Details: 42 | - Multi-Frame Rendering in AE: effect-details/multi-frame-rendering-in-ae.md 43 | - Effect Details: effect-details/effect-details.md 44 | - Accessing the After Effects Function Suites: effect-details/accessing-function-suites.md 45 | - Memory Allocation: effect-details/memory-allocation.md 46 | - Image Buffer Management Functions: effect-details/image-buffer-management-functions.md 47 | - Iteration Suites: effect-details/iteration-suites.md 48 | - Graphics Utility Suites: effect-details/graphics-utility-suites.md 49 | - Interaction Callback Functions: effect-details/interaction-callback-functions.md 50 | - Pixel Aspect Ratio: effect-details/pixel-aspect-ratio.md 51 | - Parameters & Floating Point Values: effect-details/parameters-floating-point-values.md 52 | - Parameter Supervision: effect-details/parameter-supervision.md 53 | - Global, Sequence, & Frame Data: effect-details/global-sequence-frame-data.md 54 | - Arbitrary Data Parameters: effect-details/arbitrary-data-parameters.md 55 | - Useful Utility Functions: effect-details/useful-utility-functions.md 56 | - Motion Blur: effect-details/motion-blur.md 57 | - Working With Paths: effect-details/working-with-paths.md 58 | - Accessing Camera & Light Information: effect-details/accessing-camera-light-information.md 59 | - Color Space Conversion: effect-details/color-space-conversion.md 60 | - Changing Parameter Orders, the Nice Way: effect-details/changing-parameter-orders.md 61 | - Tips & Tricks: effect-details/tips-tricks.md 62 | - Compute Cache API: effect-details/compute-cache-api.md 63 | - SmartFX: 64 | - SmartFX: smartfx/smartfx.md 65 | - Effect UI & Events: 66 | - Effect UI & Events: effect-ui-events/effect-ui-events.md 67 | - PF_EventExtra: effect-ui-events/PF_EventExtra.md 68 | - PF_EventUnion: effect-ui-events/PF_EventUnion.md 69 | - Custom UI & Drawbot: effect-ui-events/custom-ui-and-drawbot.md 70 | - UI Callbacks: effect-ui-events/ui-callbacks.md 71 | - Tips & Tricks: effect-ui-events/tips-and-tricks.md 72 | - Audio: 73 | - Audio: audio/audio.md 74 | - Global Outflags: audio/global-outflags.md 75 | - Audio Data Structures: audio/audio-data-structures.md 76 | - Audio-Specific Float Slider Variables: audio/audio-specific-float-slider-variables.md 77 | - Accessing Audio Data: audio/accessing-audio-data.md 78 | - Audio Considerations: audio/audio-considerations.md 79 | - AEGPs: 80 | - AEGPs: aegps/aegps.md 81 | - Overview: aegps/overview.md 82 | - Data Types: aegps/data-types.md 83 | - Implementation: aegps/implementation.md 84 | - AEGP Suites: aegps/aegp-suites.md 85 | - Cheating Effect Usage of AEGP Suites: aegps/cheating-effect-usage-of-aegp-suites.md 86 | - AEGP Details: aegps/aegp-details.md 87 | - Artisans: 88 | - Artisans: artisans/artisans.md 89 | - Artisan Data Types: artisans/artisan-data-types.md 90 | - AEIOs: 91 | - AEIOs: aeios/aeios.md 92 | - Calling Sequence: aeios/calling-sequence.md 93 | - AEIO_ModuleInfo: aeios/AEIO_ModuleInfo.md 94 | - New Kids On The Function Block: aeios/new-kids-on-the-function-block.md 95 | - Implementation Details: aeios/implementation-details.md 96 | - Premiere Pro: 97 | - Premiere Pro & Other Hosts: ppro/ppro.md 98 | - Plug-in Installation: ppro/plug-in-installation.md 99 | - Basic Host Differences: ppro/basic-host-differences.md 100 | - Multithreading: ppro/multithreading.md 101 | - Bigger Differences: ppro/bigger-differences.md 102 | - Plug-Ins... Reloaded: ppro/plug-ins-reloaded.md 103 | - Premiere Elements: ppro/premiere-elements.md 104 | - Unsupported Features: ppro/unsupported-features.md 105 | - Other Hosts: ppro/other-hosts.md 106 | 107 | #### Additional config below - modify sparingly! 108 | 109 | extra: 110 | # Custom guide-specific overrides 111 | # 112 | # Valid keys are: 113 | # custom_dir: str 114 | # hooks: 115 | # - path/to/hook.py 116 | # not_in_nav: 117 | # - gitignore_style/path/to/exclude 118 | # theme_features: 119 | # - theme.feature 120 | overrides: {} 121 | 122 | # CSS for this guide 123 | extra_css: 124 | - _static/extra.css 125 | 126 | # JS for this guide 127 | extra_javascript: 128 | - _static/extra.js 129 | 130 | markdown_extensions: {} 131 | 132 | plugins: {} 133 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # After Effects C++ Plugin SDK Guide 2 | 3 | This repo hosts the After Effects C++ Plugin SDK Guide community docs. 4 | 5 | --- 6 | 7 | ## Contributing 8 | 9 | This endeavour is primarily community-supported & run; contributors are welcome and encouraged to suggest fixes, adjustments, notes/warnings, and anything else that may help the project. 10 | 11 | For specific information on how to contribute & best practices, see the [Documentation Contribution Guide](https://docsforadobe.dev/contributing/contribution-guide/). 12 | 13 | --- 14 | 15 | ## Licensing & Ownership 16 | 17 | This project exists for educational purposes only. 18 | 19 | All content is copyright Adobe Systems Incorporated. 20 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | -r docs/_global/requirements.txt 2 | --------------------------------------------------------------------------------