afterpresets 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +25 -0
- package/README.md +20 -2
- package/bin/ap.js +2 -0
- package/package.json +39 -4
- package/runtime/docs/README.md +63 -0
- package/runtime/docs/assets.md +74 -0
- package/runtime/docs/boot.md +103 -0
- package/runtime/docs/host.md +110 -0
- package/runtime/docs/licensing.md +261 -0
- package/runtime/docs/panels.md +114 -0
- package/runtime/docs/storage.md +82 -0
- package/runtime/docs/updates.md +251 -0
- package/runtime/package.json +5 -0
- package/runtime/runtime-files.json +14 -0
- package/runtime/src/boot.js +1 -0
- package/runtime/src/computer-id.js +1 -0
- package/runtime/src/core.js +1 -0
- package/runtime/src/events.js +1 -0
- package/runtime/src/host.js +1 -0
- package/runtime/src/license.js +1 -0
- package/runtime/src/panels.js +1 -0
- package/runtime/src/storage.js +1 -0
- package/runtime/src/updates.js +1 -0
- package/runtime/src/vendor/CSInterface.js +1 -0
- package/runtime/src/vendor/json2.jsx +506 -0
- package/runtime/src/zip.js +1 -0
- package/src/api/client.js +1 -0
- package/src/api/error-messages.js +1 -0
- package/src/api/session.js +1 -0
- package/src/args.js +1 -0
- package/src/auth/credentials.js +2 -0
- package/src/auth/logout.js +1 -0
- package/src/build/assets.js +1 -0
- package/src/build/build.js +9 -0
- package/src/build/bundle.js +5 -0
- package/src/build/html.js +4 -0
- package/src/build/jsx.js +3 -0
- package/src/build/jsxbin.js +1 -0
- package/src/build/runtime.js +4 -0
- package/src/check/check.js +3 -0
- package/src/check/extendscript-globals.d.ts +6 -0
- package/src/check/pricing.js +1 -0
- package/src/check/types.js +3 -0
- package/src/cli.js +5 -0
- package/src/commands/add.js +6 -0
- package/src/commands/build.js +6 -0
- package/src/commands/check.js +13 -0
- package/src/commands/config.js +7 -0
- package/src/commands/dev.js +6 -0
- package/src/commands/docs.js +1 -0
- package/src/commands/init.js +3 -0
- package/src/commands/login.js +3 -0
- package/src/commands/logout.js +1 -0
- package/src/commands/mcp.js +7 -0
- package/src/commands/push.js +7 -0
- package/src/commands/releases.js +5 -0
- package/src/commands/testers.js +1 -0
- package/src/commands/upgrade.js +2 -0
- package/src/commands/whoami.js +1 -0
- package/src/config.js +1 -0
- package/src/context.js +1 -0
- package/src/dev/cep-link.js +1 -0
- package/src/dev/debug-file.js +10 -0
- package/src/dev/debug-mode.js +1 -0
- package/src/dev/session.js +4 -0
- package/src/errors.js +1 -0
- package/src/mcp/capture.js +1 -0
- package/src/mcp/extendscript.js +7 -0
- package/src/mcp/panels.js +1 -0
- package/src/mcp/protocol.js +4 -0
- package/src/mcp/redact.js +1 -0
- package/src/mcp/server.js +2 -0
- package/src/mcp/snapshot.js +2 -0
- package/src/mcp/tools/account.js +3 -0
- package/src/mcp/tools/host.js +1 -0
- package/src/mcp/tools/panel.js +7 -0
- package/src/mcp/tools/project.js +40 -0
- package/src/mcp/tools/releases.js +29 -0
- package/src/output.js +6 -0
- package/src/project/add-panel.js +11 -0
- package/src/project/docs.js +1 -0
- package/src/project/manifest.js +5 -0
- package/src/project/panels.js +1 -0
- package/src/project/project.js +2 -0
- package/src/project/semver.js +1 -0
- package/src/project/template.js +1 -0
- package/src/prompt.js +1 -0
- package/src/release/installers.js +4 -0
- package/src/release/package.js +1 -0
- package/src/release/publish.js +1 -0
- package/src/system/run-command.js +1 -0
- package/src/system/update-check.js +2 -0
- package/src/user-config.js +2 -0
- package/template/.mcp.json +8 -0
- package/template/AGENTS.md +168 -0
- package/template/README.md +78 -0
- package/template/docs/initial_setup.md +69 -0
- package/template/gitignore +12 -0
- package/template/jsx/home.jsx +17 -0
- package/template/package.json +14 -0
- package/template/src/features/home/home.css +67 -0
- package/template/src/features/home/home.html +23 -0
- package/template/src/features/home/home.js +41 -0
- package/template/src/features/license-screen/license-screen.css +80 -0
- package/template/src/features/license-screen/license-screen.html +72 -0
- package/template/src/features/license-screen/license-screen.js +60 -0
- package/template/src/features/update-screen/update-screen.css +173 -0
- package/template/src/features/update-screen/update-screen.html +57 -0
- package/template/src/features/update-screen/update-screen.js +196 -0
- package/template/src/panels/main/index.html +21 -0
- package/template/src/panels/main/main.js +39 -0
- package/template/src/shared/lib/dom.js +29 -0
- package/template/src/shared/lib/host-theme.js +17 -0
- package/template/src/shared/lib/markdown.js +109 -0
- package/template/src/shared/lib/view.js +82 -0
- package/template/src/shared/ui/base.css +60 -0
- package/template/src/shared/ui/button.css +61 -0
- package/template/src/shared/ui/card.css +22 -0
- package/template/src/shared/ui/field.css +25 -0
- package/template/src/shared/ui/index.css +7 -0
- package/template/src/shared/ui/tokens.css +21 -0
- package/vendor/types-for-adobe/AfterEffects/26.0/index.d.ts +3403 -0
- package/vendor/types-for-adobe/LICENSE.md +21 -0
- package/vendor/types-for-adobe/README.md +9 -0
- package/vendor/types-for-adobe/shared/JavaScript.d.ts +2761 -0
- package/vendor/types-for-adobe/shared/PlugPlugExternalObject.d.ts +91 -0
- package/vendor/types-for-adobe/shared/ScriptUI.d.ts +3012 -0
- package/vendor/types-for-adobe/shared/XMPScript.d.ts +72 -0
- package/vendor/types-for-adobe/shared/global.d.ts +152 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
AfterPresets CLI and Runtime License
|
|
2
|
+
|
|
3
|
+
Copyright (c) AfterPresets. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This package ("the Software") contains the AfterPresets command-line tool and
|
|
6
|
+
the AfterPresets runtime.
|
|
7
|
+
|
|
8
|
+
You may install and use the Software only to create, test, build and publish
|
|
9
|
+
Adobe After Effects extensions that are distributed through AfterPresets
|
|
10
|
+
(afterpresets.com), and you may include the runtime in those extensions as
|
|
11
|
+
the Software's build process does.
|
|
12
|
+
|
|
13
|
+
You may not, except as the law expressly allows:
|
|
14
|
+
- modify, decompile, deobfuscate or reverse engineer the runtime, or remove,
|
|
15
|
+
disable or work around its licensing, signing or update checks;
|
|
16
|
+
- copy or redistribute the Software, or the runtime outside an extension
|
|
17
|
+
built with the Software;
|
|
18
|
+
- use the Software to build or distribute extensions outside AfterPresets.
|
|
19
|
+
|
|
20
|
+
Use of AfterPresets services is also governed by the AfterPresets Terms of
|
|
21
|
+
Service at https://afterpresets.com.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED. IN NO EVENT SHALL AFTERPRESETS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
25
|
+
OTHER LIABILITY ARISING FROM THE SOFTWARE OR ITS USE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AfterPresets CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Make Adobe After Effects extensions with an AI agent, and sell them on
|
|
4
|
+
[AfterPresets](https://afterpresets.com) with licensing, signed auto-updates
|
|
5
|
+
and checkout handled.
|
|
6
|
+
|
|
7
|
+
You do not need to write code. Open an empty folder in your agent (the Code
|
|
8
|
+
tab of the Claude desktop app, Claude Code, Codex, Cursor...) and follow the
|
|
9
|
+
**[Quickstart](https://docs.afterpresets.com/get-started/quickstart/)**.
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npx afterpresets login
|
|
13
|
+
npx afterpresets init my-extension
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Inside a project, `ap dev` puts the extension into After Effects and reloads
|
|
17
|
+
it on every save, `ap push` publishes a release, and `ap upgrade` updates
|
|
18
|
+
this package. Every project includes `AGENTS.md` and an MCP server
|
|
19
|
+
(`ap mcp`) so your agent can see, click and test the live panel.
|
|
20
|
+
|
|
21
|
+
Docs: https://docs.afterpresets.com
|
package/bin/ap.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "afterpresets",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Create, develop, and publish Adobe CEP extensions on AfterPresets.",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"homepage": "https://docs.afterpresets.com",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"after effects",
|
|
9
|
+
"adobe",
|
|
10
|
+
"cep",
|
|
11
|
+
"extension",
|
|
12
|
+
"afterpresets",
|
|
13
|
+
"mcp"
|
|
14
|
+
],
|
|
15
|
+
"bin": {
|
|
16
|
+
"ap": "bin/ap.js",
|
|
17
|
+
"afterpresets": "bin/ap.js"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"bin",
|
|
21
|
+
"src",
|
|
22
|
+
"runtime",
|
|
23
|
+
"template",
|
|
24
|
+
"vendor",
|
|
25
|
+
"LICENSE"
|
|
26
|
+
],
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=20"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"adm-zip": "0.5.16",
|
|
32
|
+
"chokidar": "3.6.0",
|
|
33
|
+
"esbuild": "0.25.12",
|
|
34
|
+
"jsxbin": "2.3.0",
|
|
35
|
+
"playwright-core": "1.64.1",
|
|
36
|
+
"typescript": "5.9.3"
|
|
37
|
+
},
|
|
38
|
+
"afterpresets": {
|
|
39
|
+
"runtimeVersion": "0.3.0"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: AfterPresets runtime reference
|
|
3
|
+
description: What the AfterPresets runtime does, and which reference file to read before you use any AP.* API.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# AfterPresets runtime reference
|
|
7
|
+
|
|
8
|
+
These files are for the AI coding agent that builds an After Effects extension
|
|
9
|
+
with AfterPresets. They describe the `AP.*` API that every panel gets.
|
|
10
|
+
|
|
11
|
+
## What the runtime does
|
|
12
|
+
|
|
13
|
+
The runtime is a small script that the AfterPresets CLI puts in front of each
|
|
14
|
+
panel's JavaScript. It is logic only. It draws nothing: your project owns every
|
|
15
|
+
screen, style, and word the user sees.
|
|
16
|
+
|
|
17
|
+
It gives you:
|
|
18
|
+
|
|
19
|
+
- `AP.boot` to start the panel.
|
|
20
|
+
- Licensing, off by default. Paid extensions must turn it on.
|
|
21
|
+
- Signed updates with changelogs.
|
|
22
|
+
- `AP.host.eval` to call After Effects (ExtendScript) functions.
|
|
23
|
+
- `AP.panels` and `AP.events` for extensions with more than one panel.
|
|
24
|
+
- `AP.paths` to find the images, videos and other files you ship.
|
|
25
|
+
- `AP.storage` to save settings and other small data on this computer.
|
|
26
|
+
|
|
27
|
+
Do not edit the runtime and do not copy it into your source files. The CLI
|
|
28
|
+
adds it for you. `ap docs` refreshes this folder from the installed runtime.
|
|
29
|
+
|
|
30
|
+
## The rule
|
|
31
|
+
|
|
32
|
+
**Read the relevant file below before you write or change code that uses
|
|
33
|
+
`AP.*`.** Do not guess option names, statuses, or callback shapes. If a file
|
|
34
|
+
and your memory disagree, the file wins.
|
|
35
|
+
|
|
36
|
+
## Files
|
|
37
|
+
|
|
38
|
+
| File | Read it before you |
|
|
39
|
+
|---|---|
|
|
40
|
+
| [boot.md](boot.md) | call `AP.boot`, use `ctx`, or change when the app starts |
|
|
41
|
+
| [licensing.md](licensing.md) | turn licensing on, write `renderLicense`, or change the license screen |
|
|
42
|
+
| [updates.md](updates.md) | change update options or the update screen, or show a changelog |
|
|
43
|
+
| [host.md](host.md) | call After Effects from the panel or write `jsx/` code |
|
|
44
|
+
| [panels.md](panels.md) | add a panel or modal, open/close panels, or send data between panels |
|
|
45
|
+
| [assets.md](assets.md) | add images, fonts, videos or other files, or import a file into After Effects |
|
|
46
|
+
| [storage.md](storage.md) | save settings, recent items or any other data between launches |
|
|
47
|
+
|
|
48
|
+
## Commands you will use
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
ap dev # build, link into After Effects, rebuild on change
|
|
52
|
+
ap check # static checks; also run by ap dev and ap push
|
|
53
|
+
ap add panel settings --type modal
|
|
54
|
+
ap push # publish a release (asks for version bump and changelog)
|
|
55
|
+
ap docs # refresh docs/afterpresets/ from the runtime
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Compatibility
|
|
59
|
+
|
|
60
|
+
Panels run in Adobe CEP 10 or later (After Effects 2020+). Its browser is old
|
|
61
|
+
(Chromium 74 in CEP 10). Write plain ES5 in panel code: `var`, `function`, no
|
|
62
|
+
arrow functions, no `let`/`const`, no `class`, no template strings, no
|
|
63
|
+
`fetch`-only features. ExtendScript in `jsx/` is ES3 (see [host.md](host.md)).
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Media and other files
|
|
3
|
+
description: Where to put images, fonts, videos, presets and other files your extension ships, and how to use them from HTML, CSS, JavaScript and ExtendScript.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Media and other files
|
|
7
|
+
|
|
8
|
+
Put files your extension ships in these folders at the **project root**
|
|
9
|
+
(next to `afterpresets.json`):
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
assets/ fonts/ icons/ images/ media/
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
They are copied into the build unchanged, at the same place: `media/intro.mp4`
|
|
16
|
+
in the project is `media/intro.mp4` inside the installed extension. Other
|
|
17
|
+
folders are not shipped. To choose your own list, set it in
|
|
18
|
+
`afterpresets.json` (this replaces the defaults):
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
"assets": ["media", "presets", "fonts"]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
These files are **not** obfuscated or hidden. Anything the buyer installs, they
|
|
25
|
+
can open. Keep secrets out of them. The whole release must stay under 200 MB.
|
|
26
|
+
|
|
27
|
+
## From HTML and CSS
|
|
28
|
+
|
|
29
|
+
Write paths relative to the file you are in, as usual. They must point into
|
|
30
|
+
an asset folder; the build rewrites them for the installed extension and fails
|
|
31
|
+
on a missing file.
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<!-- src/panels/main/index.html -->
|
|
35
|
+
<img src="../../../images/logo.png" alt="">
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```css
|
|
39
|
+
/* src/features/home/home.css */
|
|
40
|
+
.hero { background-image: url(../../../images/hero.jpg); }
|
|
41
|
+
@font-face { font-family: "Brand"; src: url(../../../fonts/Brand.woff2); }
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## From JavaScript
|
|
45
|
+
|
|
46
|
+
Use `AP.paths`; never build paths by hand.
|
|
47
|
+
|
|
48
|
+
| Call | Returns |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `AP.paths.asset("media/intro.mp4")` | Absolute path of a shipped file. Relative path with `/`; `..` and absolute paths throw. |
|
|
51
|
+
| `AP.paths.extension()` | Absolute path of the installed extension folder. |
|
|
52
|
+
| `AP.paths.data()` | A writable folder for your own files. It survives updates. Never write into the extension folder: updates replace it. For settings use `AP.storage`; see [storage.md](storage.md). |
|
|
53
|
+
|
|
54
|
+
## From ExtendScript (importing into After Effects)
|
|
55
|
+
|
|
56
|
+
ExtendScript cannot see the panel's folders by itself. Pass the absolute path
|
|
57
|
+
from the panel:
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
// panel
|
|
61
|
+
ctx.host.eval("importClip", [AP.paths.asset("media/intro.mp4")], function (result) {
|
|
62
|
+
if (result && result.error) { /* show result.error */ }
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
// jsx/media.jsx (loaded automatically, like every .jsx file in jsx/)
|
|
68
|
+
function importClip(path) {
|
|
69
|
+
var file = new File(path);
|
|
70
|
+
if (!file.exists) return JSON.stringify({ error: "Missing file: " + path });
|
|
71
|
+
var item = app.project.importFile(new ImportOptions(file));
|
|
72
|
+
return JSON.stringify({ ok: true, name: item.name });
|
|
73
|
+
}
|
|
74
|
+
```
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: AP.boot
|
|
3
|
+
description: Start a panel with AP.boot. Options, the ctx object passed to start, and the boot lifecycle.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# AP.boot
|
|
7
|
+
|
|
8
|
+
Every panel calls `AP.boot` exactly once, from its `src/panels/<id>/main.js`
|
|
9
|
+
code. `ap check` fails when a panel never calls it.
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
AP.boot({
|
|
13
|
+
start: function (ctx) {
|
|
14
|
+
// Build your UI here.
|
|
15
|
+
},
|
|
16
|
+
license: false, // default. true, or { offlineGraceDays, checkInBackground }
|
|
17
|
+
renderLicense: function (api, root) {}, // required when license is on
|
|
18
|
+
updates: { check: "auto", mode: "background" } // defaults
|
|
19
|
+
});
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Options
|
|
23
|
+
|
|
24
|
+
| Option | Type | Default | Meaning |
|
|
25
|
+
|---|---|---|---|
|
|
26
|
+
| `start` | `function (ctx)` | required | Your app. Called once, when the panel may run. |
|
|
27
|
+
| `license` | `false`, `true`, or `{ offlineGraceDays, checkInBackground }` | `false` | Turns licensing on. See [licensing.md](licensing.md). |
|
|
28
|
+
| `renderLicense` | `function (api, root)` | none | Draws the license screen. Required when `license` is on. |
|
|
29
|
+
| `updates.check` | `"auto"` or `"manual"` | `"auto"` | `"auto"` checks at start and every 6 hours. See [updates.md](updates.md). |
|
|
30
|
+
| `updates.mode` | `"background"`, `"prompt"` or `"silent"` | `"background"` | What happens when an update is found. `"background"` installs it without asking, then your update screen offers **Reload now** (`AP.updates.reload()`). `"prompt"` waits for your Install button. `"silent"` installs and shows nothing. See [updates.md](updates.md). |
|
|
31
|
+
|
|
32
|
+
Unknown values are replaced by the default with a console warning. If
|
|
33
|
+
`license` is on and `renderLicense` is missing, `AP.boot` logs an error and
|
|
34
|
+
throws; the panel stays empty.
|
|
35
|
+
|
|
36
|
+
## ctx
|
|
37
|
+
|
|
38
|
+
`start(ctx)` receives:
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
ctx = {
|
|
42
|
+
product: { bundleId: "com.afterpresets.seller.tool", version: "1.2.0" },
|
|
43
|
+
panel: { id: "main" }, // this panel's id from afterpresets.json
|
|
44
|
+
license: AP.license, // license api; status is "disabled" when licensing is off
|
|
45
|
+
updates: AP.updates, // see updates.md
|
|
46
|
+
host: AP.host // see host.md
|
|
47
|
+
};
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The same objects are also available as globals (`AP.license`, `AP.updates`,
|
|
51
|
+
`AP.host`, `AP.panels`, `AP.events`) for code that runs outside `start`.
|
|
52
|
+
|
|
53
|
+
## Lifecycle
|
|
54
|
+
|
|
55
|
+
1. The page loads. The runtime is already defined; nothing has run yet.
|
|
56
|
+
2. Your entry code calls `AP.boot(options)`.
|
|
57
|
+
3. When the DOM is ready:
|
|
58
|
+
- **License off:** `AP.license.state.status` is `"disabled"` and `start(ctx)`
|
|
59
|
+
runs immediately.
|
|
60
|
+
- **License on:** the runtime adds an empty `<div id="ap-license-root">` to
|
|
61
|
+
`<body>`, calls `renderLicense(api, root)`, and validates the license.
|
|
62
|
+
`start(ctx)` runs once the status becomes `active` or `offline_grace`.
|
|
63
|
+
It never runs for any other status.
|
|
64
|
+
4. After `start`, if `updates.check` is `"auto"`, the runtime checks for updates
|
|
65
|
+
now and every 6 hours. In the default `"background"` mode a found update is
|
|
66
|
+
installed right away and `AP.updates.onInstalled` fires; the panel keeps
|
|
67
|
+
running the old version until `AP.updates.reload()` or the next launch.
|
|
68
|
+
|
|
69
|
+
`start` runs at most once per panel load. If the license later becomes invalid
|
|
70
|
+
(for example the buyer signs out), the license root is shown again over your
|
|
71
|
+
app; `start` is not called a second time.
|
|
72
|
+
|
|
73
|
+
## Example: a free extension
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
AP.boot({
|
|
77
|
+
start: function (ctx) {
|
|
78
|
+
var app = document.getElementById("app");
|
|
79
|
+
app.textContent = "Hello from " + ctx.product.bundleId + " (" + ctx.panel.id + ")";
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Example: a paid extension
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
AP.boot({
|
|
88
|
+
start: function (ctx) {
|
|
89
|
+
renderHome(document.getElementById("app"), ctx); // imported from src/features/home/home.js
|
|
90
|
+
},
|
|
91
|
+
license: true,
|
|
92
|
+
renderLicense: renderLicense, // imported; see licensing.md
|
|
93
|
+
updates: { check: "auto", mode: "background" }
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Mistakes to avoid
|
|
98
|
+
|
|
99
|
+
- Do not build app UI before `start` runs. Put it inside `start`.
|
|
100
|
+
- Do not call `start` yourself, and do not call `AP.boot` twice (the second call
|
|
101
|
+
is ignored with a warning).
|
|
102
|
+
- Do not wrap `AP.boot` in `try/catch` to hide the missing-`renderLicense`
|
|
103
|
+
error. Fix the options instead.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Calling After Effects
|
|
3
|
+
description: Call ExtendScript functions from a panel with AP.host.eval, write jsx/ functions in ES3 that return JSON, and handle host errors.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Calling After Effects
|
|
7
|
+
|
|
8
|
+
Panel code runs in a browser. Anything that touches After Effects (project,
|
|
9
|
+
comps, layers, effects, files through `File`/`Folder`) runs in ExtendScript, in
|
|
10
|
+
`jsx/`. `AP.host.eval` connects the two.
|
|
11
|
+
|
|
12
|
+
## Where JSX lives
|
|
13
|
+
|
|
14
|
+
Put ExtendScript in `jsx/`, one file per feature (for example
|
|
15
|
+
`jsx/layers.jsx`; subfolders are fine). Every `.jsx` file there is loaded into
|
|
16
|
+
After Effects once, before your app starts, and its functions are shared by
|
|
17
|
+
all panels. Call one from panel code with `ctx.host.eval("fnName", [args], cb)`.
|
|
18
|
+
|
|
19
|
+
- There is no list to keep: the CLI joins every `.jsx` file in alphabetical
|
|
20
|
+
path order, with JSON support (json2) first, embeds the result in every
|
|
21
|
+
panel's `main.js` (readable in `ap dev`, compiled to JSXBIN for releases),
|
|
22
|
+
and the runtime evaluates it as soon as `AP.boot` runs, before `start`.
|
|
23
|
+
Every `AP.host.eval` waits for that load.
|
|
24
|
+
- Order only matters for code that runs at the top level of a file while it
|
|
25
|
+
loads (not inside a function). Keep files to function declarations.
|
|
26
|
+
|
|
27
|
+
## Writing a JSX function
|
|
28
|
+
|
|
29
|
+
ExtendScript is **ES3**: `var` only, no `let`/`const`, no arrow functions, no
|
|
30
|
+
`Array.prototype.forEach`/`map`/`indexOf`, no `trim()`, no template strings.
|
|
31
|
+
`JSON` is always available (the CLI adds json2).
|
|
32
|
+
|
|
33
|
+
Rules:
|
|
34
|
+
|
|
35
|
+
1. Declare a named top-level function. Avoid generic names; prefix them
|
|
36
|
+
(`myTool_addNull`), because every extension shares one ExtendScript engine.
|
|
37
|
+
2. Take JSON-compatible arguments (strings, numbers, booleans, arrays, plain
|
|
38
|
+
objects).
|
|
39
|
+
3. Return `JSON.stringify(...)`. Return a result object such as `{ ok: true, ... }`
|
|
40
|
+
or `{ ok: false, message: "..." }` for expected problems.
|
|
41
|
+
4. Wrap changes to the project in `app.beginUndoGroup("Name")` /
|
|
42
|
+
`app.endUndoGroup()`.
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
/* jsx/layers.jsx */
|
|
46
|
+
function myTool_addNull(name) {
|
|
47
|
+
var comp = app.project.activeItem;
|
|
48
|
+
if (!comp || !(comp instanceof CompItem)) {
|
|
49
|
+
return JSON.stringify({ ok: false, message: "Select a composition first." });
|
|
50
|
+
}
|
|
51
|
+
app.beginUndoGroup("Add null");
|
|
52
|
+
try {
|
|
53
|
+
var layer = comp.layers.addNull();
|
|
54
|
+
layer.name = name;
|
|
55
|
+
return JSON.stringify({ ok: true, index: layer.index });
|
|
56
|
+
} finally {
|
|
57
|
+
app.endUndoGroup();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Calling it from the panel
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
AP.host.eval("myTool_addNull", ["Controller"], function (result) {
|
|
66
|
+
if (!result || result.error) {
|
|
67
|
+
showError(result ? result.error : "No answer from After Effects.");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (!result.ok) {
|
|
71
|
+
showMessage(result.message);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
showMessage("Added layer " + result.index);
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`AP.host.eval(fnName, args, cb)`:
|
|
79
|
+
|
|
80
|
+
- `fnName` is a function name or dotted path (`"myTool.addNull"`). Anything else
|
|
81
|
+
is refused with `{ error }`.
|
|
82
|
+
- `args` is an array. Each value is passed as a JSON literal, so quotes,
|
|
83
|
+
newlines, and code in strings are safe. `undefined` becomes `null`.
|
|
84
|
+
- `cb(result)` receives the parsed JSON your function returned, `null` when it
|
|
85
|
+
returned nothing, or `{ error: "message" }` when anything failed.
|
|
86
|
+
|
|
87
|
+
Never build ExtendScript source by joining strings with user input. Always pass
|
|
88
|
+
values through `args`.
|
|
89
|
+
|
|
90
|
+
## Errors
|
|
91
|
+
|
|
92
|
+
| `result` | Cause |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `{ error: "<message>" }` | Your function threw; the message is the thrown error's message. |
|
|
95
|
+
| `{ error: "...is undefined" }` or similar | The function does not exist: check the name, and that its file is in `jsx/` and ends in `.jsx`. |
|
|
96
|
+
| `{ error: "The host returned a non-JSON result.", raw }` | Your function returned a plain string. Return `JSON.stringify(...)`. |
|
|
97
|
+
| `{ error: "The host script failed to run." }` | ExtendScript syntax error or an ES5+ feature in `jsx/`. |
|
|
98
|
+
| `{ error: "Could not load host script: ..." }` | The embedded JSX failed to load. Read the message; usually a syntax error. |
|
|
99
|
+
|
|
100
|
+
The JSX loads once per page. During `ap dev` every save rebuilds and reloads
|
|
101
|
+
the open panels, which loads the new JSX too; after an update,
|
|
102
|
+
`AP.updates.reload()` does the same. The new functions replace the old ones.
|
|
103
|
+
Functions removed from the new code stay defined in After Effects until it
|
|
104
|
+
restarts, so never rely on a function being absent.
|
|
105
|
+
|
|
106
|
+
## Testing
|
|
107
|
+
|
|
108
|
+
Call the function from the live panel and check the result and the project
|
|
109
|
+
state. Use a disposable project or a duplicate composition for anything that
|
|
110
|
+
changes layers, effects, files, or project data.
|