afterpresets 0.1.0 → 0.3.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/README.md +6 -4
- package/native-runtime/CMakeLists.txt +82 -0
- package/native-runtime/README.md +40 -0
- package/native-runtime/THIRD_PARTY_NOTICES.md +14 -0
- package/native-runtime/include/ap_native.h +223 -0
- package/native-runtime/src/apply.cpp +199 -0
- package/native-runtime/src/crypto.cpp +225 -0
- package/native-runtime/src/crypto.hpp +51 -0
- package/native-runtime/src/dialog.cpp +62 -0
- package/native-runtime/src/dialog.hpp +35 -0
- package/native-runtime/src/engine.cpp +909 -0
- package/native-runtime/src/engine.hpp +232 -0
- package/native-runtime/src/fsutil.cpp +291 -0
- package/native-runtime/src/fsutil.hpp +57 -0
- package/native-runtime/src/json.cpp +326 -0
- package/native-runtime/src/json.hpp +70 -0
- package/native-runtime/src/platform.hpp +83 -0
- package/native-runtime/src/platform_common.cpp +60 -0
- package/native-runtime/src/platform_mac.mm +314 -0
- package/native-runtime/src/platform_win.cpp +277 -0
- package/native-runtime/src/runtime.cpp +473 -0
- package/native-runtime/src/util.cpp +169 -0
- package/native-runtime/src/util.hpp +32 -0
- package/native-runtime/src/zip.cpp +243 -0
- package/native-runtime/src/zip.hpp +58 -0
- package/native-runtime/third_party/monocypher/LICENCE.md +167 -0
- package/native-runtime/third_party/monocypher/monocypher-ed25519.c +500 -0
- package/native-runtime/third_party/monocypher/monocypher-ed25519.h +140 -0
- package/native-runtime/third_party/monocypher/monocypher.c +2956 -0
- package/native-runtime/third_party/monocypher/monocypher.h +321 -0
- package/native-runtime/third_party/tinf/LICENSE +22 -0
- package/native-runtime/third_party/tinf/crc32.c +57 -0
- package/native-runtime/third_party/tinf/tinf.h +140 -0
- package/native-runtime/third_party/tinf/tinflate.c +636 -0
- package/native-runtime/vendor-files.json +39 -0
- package/package.json +6 -3
- package/runtime/docs/cep/host-after-effects.md +57 -0
- package/runtime/docs/cep/host-premiere.md +84 -0
- package/runtime/docs/{host.md → cep/host.md} +42 -16
- package/runtime/docs/{README.md → common/README.md} +10 -8
- package/runtime/docs/{assets.md → common/assets.md} +16 -2
- package/runtime/docs/{licensing.md → common/licensing.md} +1 -1
- package/runtime/docs/{panels.md → common/panels.md} +5 -5
- package/runtime/docs/{storage.md → common/storage.md} +5 -5
- package/runtime/docs/{updates.md → common/updates.md} +1 -1
- package/runtime/docs/native/README.md +44 -0
- package/runtime/docs/native/debugging.md +140 -0
- package/runtime/docs/native/rules.md +402 -0
- package/runtime/docs/native/testing.md +154 -0
- package/runtime/package.json +1 -1
- package/runtime/scripts/ae-sdk-docs/config.js +102 -0
- package/runtime/scripts/ae-sdk-docs/convert.js +430 -0
- package/runtime/scripts/ae-sdk-docs/index.js +314 -0
- package/runtime/scripts/ae-sdk-docs/source.js +205 -0
- package/runtime/scripts/ae-sdk-docs/split.js +170 -0
- package/runtime/scripts/ae-sdk-docs.js +72 -0
- package/runtime/src/host.js +1 -1
- package/runtime/src/updates.js +1 -1
- package/src/api/error-messages.js +1 -1
- package/src/build/build.js +7 -7
- package/src/build/html.js +1 -1
- package/src/build/jsx.js +2 -2
- package/src/build/runtime.js +3 -3
- package/src/check/check.js +3 -3
- package/src/check/native.js +14 -0
- package/src/check/pricing.js +1 -1
- package/src/check/types.js +2 -2
- package/src/cli.js +5 -5
- package/src/commands/add.js +8 -3
- package/src/commands/build.js +8 -2
- package/src/commands/check.js +11 -3
- package/src/commands/dev.js +9 -2
- package/src/commands/docs.js +5 -1
- package/src/commands/init.js +15 -3
- package/src/commands/push.js +5 -2
- package/src/commands/sdk.js +14 -0
- package/src/commands/testers.js +1 -1
- package/src/commands/upgrade.js +2 -2
- package/src/commands/whoami.js +1 -1
- package/src/config.js +1 -1
- package/src/dev/bridge.js +8 -0
- package/src/dev/cep-link.js +1 -1
- package/src/dev/debug-file.js +5 -5
- package/src/dev/native.js +3 -0
- package/src/dev/session.js +4 -3
- package/src/mcp/extendscript.js +10 -7
- package/src/mcp/host-target.js +1 -0
- package/src/mcp/panels.js +1 -1
- package/src/mcp/png.js +1 -0
- package/src/mcp/server.js +2 -2
- package/src/mcp/tools/capture.js +3 -0
- package/src/mcp/tools/host.js +1 -1
- package/src/mcp/tools/native.js +6 -0
- package/src/mcp/tools/panel.js +4 -4
- package/src/mcp/tools/project.js +47 -31
- package/src/mcp/tools/releases.js +23 -20
- package/src/native/build.js +27 -0
- package/src/native/cmake/CMakeLists.txt +88 -0
- package/src/native/cmake/zig-windows.cmake +19 -0
- package/src/native/effect.js +3 -0
- package/src/native/install.js +8 -0
- package/src/native/installers.js +4 -0
- package/src/native/pipl.js +20 -0
- package/src/native/restart.js +2 -0
- package/src/native/sdk.js +8 -0
- package/src/project/add-panel.js +1 -1
- package/src/project/docs.js +3 -1
- package/src/project/manifest.js +3 -2
- package/src/project/project.js +2 -2
- package/src/project/template.js +5 -1
- package/src/prompt.js +1 -1
- package/src/release/installers.js +4 -4
- package/src/release/native.js +3 -0
- package/src/release/package.js +1 -1
- package/src/release/publish.js +1 -1
- package/src/system/run-command.js +1 -1
- package/src/targets.js +1 -0
- package/src/user-config.js +2 -2
- package/template/cep/AGENTS.md +104 -0
- package/template/{README.md → cep/README.md} +16 -11
- package/template/cep/docs/code_guide.md +67 -0
- package/template/cep/docs/initial_setup.md +115 -0
- package/template/cep/docs/release_checklist.md +24 -0
- package/template/{src → cep/src}/features/home/home.html +4 -4
- package/template/{src → cep/src}/features/home/home.js +10 -11
- package/template/{src → cep/src}/shared/lib/host-theme.js +3 -3
- package/template/{src → cep/src}/shared/lib/view.js +1 -1
- package/template/{src → cep/src}/shared/ui/tokens.css +1 -1
- package/template/hosts/AGENTS.two-apps.md +12 -0
- package/template/hosts/aeft/AGENTS.host.md +10 -0
- package/template/hosts/aeft/jsx/aeft/home.jsx +16 -0
- package/template/hosts/ppro/AGENTS.host.md +15 -0
- package/template/hosts/ppro/jsx/ppro/home.jsx +20 -0
- package/template/native/.mcp.json +8 -0
- package/template/native/AGENTS.md +105 -0
- package/template/native/README.md +71 -0
- package/template/native/docs/code_guide.md +72 -0
- package/template/native/docs/initial_setup.md +179 -0
- package/template/native/docs/release_checklist.md +24 -0
- package/template/native/effect.json +16 -0
- package/template/native/gitignore +8 -0
- package/template/native/package.json +14 -0
- package/template/native/src/Effect.cpp +224 -0
- package/template/native/src/License.cpp +95 -0
- package/template/native/src/License.h +29 -0
- package/template/native/src/Render.h +68 -0
- package/vendor/afterpresets-additions/AfterEffects.d.ts +291 -0
- package/vendor/afterpresets-additions/Premiere.d.ts +179 -0
- package/vendor/types-for-adobe/Premiere/24.0/index.d.ts +2567 -0
- package/vendor/types-for-adobe/README.md +8 -4
- package/template/AGENTS.md +0 -168
- package/template/docs/initial_setup.md +0 -69
- package/template/jsx/home.jsx +0 -17
- /package/runtime/docs/{boot.md → common/boot.md} +0 -0
- /package/template/{.mcp.json → cep/.mcp.json} +0 -0
- /package/template/{gitignore → cep/gitignore} +0 -0
- /package/template/{package.json → cep/package.json} +0 -0
- /package/template/{src → cep/src}/features/home/home.css +0 -0
- /package/template/{src → cep/src}/features/license-screen/license-screen.css +0 -0
- /package/template/{src → cep/src}/features/license-screen/license-screen.html +0 -0
- /package/template/{src → cep/src}/features/license-screen/license-screen.js +0 -0
- /package/template/{src → cep/src}/features/update-screen/update-screen.css +0 -0
- /package/template/{src → cep/src}/features/update-screen/update-screen.html +0 -0
- /package/template/{src → cep/src}/features/update-screen/update-screen.js +0 -0
- /package/template/{src → cep/src}/panels/main/index.html +0 -0
- /package/template/{src → cep/src}/panels/main/main.js +0 -0
- /package/template/{src → cep/src}/shared/lib/dom.js +0 -0
- /package/template/{src → cep/src}/shared/lib/markdown.js +0 -0
- /package/template/{src → cep/src}/shared/ui/base.css +0 -0
- /package/template/{src → cep/src}/shared/ui/button.css +0 -0
- /package/template/{src → cep/src}/shared/ui/card.css +0 -0
- /package/template/{src → cep/src}/shared/ui/field.css +0 -0
- /package/template/{src → cep/src}/shared/ui/index.css +0 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: After Effects ExtendScript
|
|
3
|
+
description: "Rules for ExtendScript in After Effects (jsx/aeft/): undo groups, the active composition, 1-based collections, and the version range."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# After Effects ExtendScript
|
|
7
|
+
|
|
8
|
+
Read [host.md](host.md) first: it explains `AP.host.eval` and how `jsx/` is
|
|
9
|
+
loaded. This page is about code that runs in After Effects. Put code that only
|
|
10
|
+
makes sense in After Effects in `jsx/aeft/`.
|
|
11
|
+
|
|
12
|
+
## Undo
|
|
13
|
+
|
|
14
|
+
Wrap every change in one undo group so the user undoes the whole action with
|
|
15
|
+
one Ctrl/Cmd+Z, and close it in `finally`:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
app.beginUndoGroup("Rename layers");
|
|
19
|
+
try {
|
|
20
|
+
/* changes */
|
|
21
|
+
} finally {
|
|
22
|
+
app.endUndoGroup();
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The MCP `host_eval` tool already wraps each call in an undo group named
|
|
27
|
+
"AfterPresets MCP".
|
|
28
|
+
|
|
29
|
+
## The active composition
|
|
30
|
+
|
|
31
|
+
`app.project.activeItem` is often null or not a composition (a footage item, a
|
|
32
|
+
folder, or nothing selected). Check before using it:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
var comp = app.project.activeItem;
|
|
36
|
+
if (!comp || !(comp instanceof CompItem)) {
|
|
37
|
+
return JSON.stringify({ ok: false, message: "Open or select a composition first." });
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Collections and times
|
|
42
|
+
|
|
43
|
+
- Collections are 1-based: `comp.layer(1)`, `app.project.item(1)`,
|
|
44
|
+
`comp.selectedLayers[0]` (a plain array, 0-based).
|
|
45
|
+
- Times are seconds (floating point). `comp.frameDuration` is one frame.
|
|
46
|
+
|
|
47
|
+
## Versions
|
|
48
|
+
|
|
49
|
+
The extension's range is `hosts[].minVersion` in afterpresets.json (default
|
|
50
|
+
17.0, After Effects 2020). Check `parseFloat(app.version)` before using newer
|
|
51
|
+
APIs and return `{ ok: false, message }` when they are missing.
|
|
52
|
+
|
|
53
|
+
## Type hints
|
|
54
|
+
|
|
55
|
+
`ap check --types` checks `jsx/` against the After Effects 26.0 declarations
|
|
56
|
+
from types-for-adobe and lists likely mistakes. Hints can be wrong; confirm
|
|
57
|
+
with the MCP `host_eval` tool before changing working code.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Premiere Pro ExtendScript
|
|
3
|
+
description: "Rules for ExtendScript in Premiere Pro (jsx/ppro/): no undo groups, times in ticks, 0-based track and clip collections, no QE DOM, and the version range."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Premiere Pro ExtendScript
|
|
7
|
+
|
|
8
|
+
Read [host.md](host.md) first: it explains `AP.host.eval` and how `jsx/` is
|
|
9
|
+
loaded. This page is about code that runs in Premiere Pro. Put code that only
|
|
10
|
+
makes sense in Premiere Pro in `jsx/ppro/`.
|
|
11
|
+
|
|
12
|
+
## No undo groups
|
|
13
|
+
|
|
14
|
+
Premiere Pro's ExtendScript has no `beginUndoGroup`. Every change a script
|
|
15
|
+
makes (a clip moved, a marker added, a property set) is its own step in
|
|
16
|
+
Edit → Undo. Keep scripted edits small, do the checks before the first change,
|
|
17
|
+
and tell the user how many undo steps an action adds. The MCP `host_eval`
|
|
18
|
+
tool cannot group them either.
|
|
19
|
+
|
|
20
|
+
## The active sequence
|
|
21
|
+
|
|
22
|
+
`app.project.activeSequence` is null when no sequence is open. Check it:
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
function myTool_sequenceInfo() {
|
|
26
|
+
var sequence = app.project.activeSequence;
|
|
27
|
+
if (!sequence) return JSON.stringify({ ok: false, message: "Open a sequence first." });
|
|
28
|
+
var clips = 0;
|
|
29
|
+
for (var i = 0; i < sequence.videoTracks.numTracks; i++) {
|
|
30
|
+
clips += sequence.videoTracks[i].clips.numItems;
|
|
31
|
+
}
|
|
32
|
+
return JSON.stringify({ ok: true, name: sequence.name, videoClips: clips });
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Collections
|
|
37
|
+
|
|
38
|
+
Tracks, clips, sequences and project items are 0-based collections with a
|
|
39
|
+
count property: `sequence.videoTracks[0]` with `numTracks`,
|
|
40
|
+
`track.clips[0]` with `numItems`, `app.project.sequences[0]` with
|
|
41
|
+
`numSequences`, `app.project.rootItem.children[0]` with `numItems`. Use a
|
|
42
|
+
`for` loop; they are not arrays.
|
|
43
|
+
|
|
44
|
+
## Times are ticks
|
|
45
|
+
|
|
46
|
+
Premiere measures time in ticks: **254016000000 ticks per second**. A `Time`
|
|
47
|
+
object has `.seconds` (a number) and `.ticks` (a string). Create one with
|
|
48
|
+
`new Time()` and set either:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
var t = new Time();
|
|
52
|
+
t.seconds = 2.5;
|
|
53
|
+
app.project.activeSequence.setPlayerPosition(t.ticks); // move the playhead to 2.5 s
|
|
54
|
+
var startSeconds = clip.start.seconds; // read a clip's start
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Frame-accurate maths: convert with the sequence's timebase
|
|
58
|
+
(`sequence.timebase`, ticks per frame, a string) instead of rounding seconds.
|
|
59
|
+
|
|
60
|
+
## Things not to use
|
|
61
|
+
|
|
62
|
+
- **The QE DOM** (`app.enableQE()`, `qe.*`): undocumented, unsupported, and
|
|
63
|
+
it changes between versions. Do not ship code that needs it.
|
|
64
|
+
- Dialogs (`alert`, `confirm`, `File.openDialog`) block Premiere Pro while
|
|
65
|
+
open; the panel can show its own UI instead.
|
|
66
|
+
|
|
67
|
+
## Projects
|
|
68
|
+
|
|
69
|
+
- `app.project` is the active project. Premiere Pro can have several projects
|
|
70
|
+
open (`app.projects`, `numProjects`).
|
|
71
|
+
- Save with `app.project.save()`. The MCP `host_scratch_project` tool creates a
|
|
72
|
+
new project in the temp folder and leaves the user's project open.
|
|
73
|
+
|
|
74
|
+
## Versions
|
|
75
|
+
|
|
76
|
+
The extension's range is `hosts[].minVersion` in afterpresets.json (default
|
|
77
|
+
14.0, Premiere Pro 2020). Check `app.version` before using newer APIs and
|
|
78
|
+
return `{ ok: false, message }` when they are missing.
|
|
79
|
+
|
|
80
|
+
## Type hints
|
|
81
|
+
|
|
82
|
+
`ap check --types` checks `jsx/` against the Premiere Pro 24.0 declarations
|
|
83
|
+
from types-for-adobe (the newest set; newer APIs may be missing) and lists
|
|
84
|
+
likely mistakes. Hints can be wrong; confirm with the MCP `host_eval` tool.
|
|
@@ -1,21 +1,46 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Calling
|
|
3
|
-
description: Call ExtendScript functions from a panel with AP.host.eval, write jsx/ functions in ES3 that return JSON, and handle host errors.
|
|
2
|
+
title: Calling the app (ExtendScript)
|
|
3
|
+
description: Call ExtendScript functions in After Effects or Premiere Pro from a panel with AP.host.eval, write jsx/ functions in ES3 that return JSON, keep app-only code in jsx/aeft/ and jsx/ppro/, and handle host errors.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Calling
|
|
6
|
+
# Calling the app (ExtendScript)
|
|
7
7
|
|
|
8
|
-
Panel code runs in a browser. Anything that touches
|
|
9
|
-
|
|
10
|
-
`jsx/`. `AP.host.eval` connects the two.
|
|
8
|
+
Panel code runs in a browser. Anything that touches the app (the project, its
|
|
9
|
+
compositions or sequences, layers or clips, files through `File`/`Folder`) runs
|
|
10
|
+
in ExtendScript, in `jsx/`. `AP.host.eval` connects the two. It works the same
|
|
11
|
+
in After Effects and Premiere Pro. What you can do in each app:
|
|
12
|
+
|
|
13
|
+
- [host-after-effects.md](host-after-effects.md): After Effects
|
|
14
|
+
- [host-premiere.md](host-premiere.md): Premiere Pro
|
|
11
15
|
|
|
12
16
|
## Where JSX lives
|
|
13
17
|
|
|
14
18
|
Put ExtendScript in `jsx/`, one file per feature (for example
|
|
15
19
|
`jsx/layers.jsx`; subfolders are fine). Every `.jsx` file there is loaded into
|
|
16
|
-
|
|
20
|
+
the app once, before your app starts, and its functions are shared by
|
|
17
21
|
all panels. Call one from panel code with `ctx.host.eval("fnName", [args], cb)`.
|
|
18
22
|
|
|
23
|
+
Two folders are special (afterpresets.json `hosts` lists the apps):
|
|
24
|
+
|
|
25
|
+
| Folder | Loaded in |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `jsx/aeft/` | After Effects only |
|
|
28
|
+
| `jsx/ppro/` | Premiere Pro only |
|
|
29
|
+
| everything else in `jsx/` | every app the extension targets |
|
|
30
|
+
|
|
31
|
+
An extension for both apps can define the same function in `jsx/aeft/` and
|
|
32
|
+
`jsx/ppro/` (for example `myTool_activeItemName`) and call it from shared panel
|
|
33
|
+
code; each app loads its own version. `ap check` warns about a folder for an
|
|
34
|
+
app the project does not target.
|
|
35
|
+
|
|
36
|
+
`AP.host.app` (also `ctx.host.app`) is the app running the panel: `"AEFT"`
|
|
37
|
+
(After Effects) or `"PPRO"` (Premiere Pro). Use it for wording that differs
|
|
38
|
+
between the apps, or to hide a feature that only one app has:
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
var noun = ctx.host.app === "PPRO" ? "sequence" : "composition";
|
|
42
|
+
```
|
|
43
|
+
|
|
19
44
|
- There is no list to keep: the CLI joins every `.jsx` file in alphabetical
|
|
20
45
|
path order, with JSON support (json2) first, embeds the result in every
|
|
21
46
|
panel's `main.js` (readable in `ap dev`, compiled to JSXBIN for releases),
|
|
@@ -38,11 +63,11 @@ Rules:
|
|
|
38
63
|
objects).
|
|
39
64
|
3. Return `JSON.stringify(...)`. Return a result object such as `{ ok: true, ... }`
|
|
40
65
|
or `{ ok: false, message: "..." }` for expected problems.
|
|
41
|
-
4.
|
|
42
|
-
|
|
66
|
+
4. Undo: in After Effects wrap changes in one undo group; Premiere Pro has
|
|
67
|
+
none (every change is its own undo step). See the app pages.
|
|
43
68
|
|
|
44
69
|
```js
|
|
45
|
-
/* jsx/layers.jsx */
|
|
70
|
+
/* jsx/aeft/layers.jsx (After Effects) */
|
|
46
71
|
function myTool_addNull(name) {
|
|
47
72
|
var comp = app.project.activeItem;
|
|
48
73
|
if (!comp || !(comp instanceof CompItem)) {
|
|
@@ -64,7 +89,7 @@ function myTool_addNull(name) {
|
|
|
64
89
|
```js
|
|
65
90
|
AP.host.eval("myTool_addNull", ["Controller"], function (result) {
|
|
66
91
|
if (!result || result.error) {
|
|
67
|
-
showError(result ? result.error : "No answer from
|
|
92
|
+
showError(result ? result.error : "No answer from the app.");
|
|
68
93
|
return;
|
|
69
94
|
}
|
|
70
95
|
if (!result.ok) {
|
|
@@ -92,19 +117,20 @@ values through `args`.
|
|
|
92
117
|
| `result` | Cause |
|
|
93
118
|
|---|---|
|
|
94
119
|
| `{ 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,
|
|
120
|
+
| `{ error: "...is undefined" }` or similar | The function does not exist: check the name, that its file is in `jsx/` and ends in `.jsx`, and that it is not in another app's folder (`jsx/aeft/`, `jsx/ppro/`). |
|
|
96
121
|
| `{ error: "The host returned a non-JSON result.", raw }` | Your function returned a plain string. Return `JSON.stringify(...)`. |
|
|
97
122
|
| `{ 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. |
|
|
123
|
+
| `{ error: "Could not load host script: ..." }` | The embedded JSX failed to load. Read the message; usually a syntax error. "This extension has no host script for X" means the build has no code for the running app (afterpresets.json `hosts`). |
|
|
99
124
|
|
|
100
125
|
The JSX loads once per page. During `ap dev` every save rebuilds and reloads
|
|
101
126
|
the open panels, which loads the new JSX too; after an update,
|
|
102
127
|
`AP.updates.reload()` does the same. The new functions replace the old ones.
|
|
103
|
-
Functions removed from the new code stay defined in
|
|
128
|
+
Functions removed from the new code stay defined in the app until it
|
|
104
129
|
restarts, so never rely on a function being absent.
|
|
105
130
|
|
|
106
131
|
## Testing
|
|
107
132
|
|
|
108
133
|
Call the function from the live panel and check the result and the project
|
|
109
|
-
state. Use a disposable project
|
|
110
|
-
changes
|
|
134
|
+
state. Use a disposable project (the MCP `host_scratch_project` tool) for
|
|
135
|
+
anything that changes the project. With the MCP tools, `host_eval` runs in the
|
|
136
|
+
app that runs the connected panel.
|
|
@@ -5,8 +5,8 @@ description: What the AfterPresets runtime does, and which reference file to rea
|
|
|
5
5
|
|
|
6
6
|
# AfterPresets runtime reference
|
|
7
7
|
|
|
8
|
-
These files are for the AI coding agent that builds an After Effects
|
|
9
|
-
with AfterPresets. They describe the `AP.*` API that every panel gets.
|
|
8
|
+
These files are for the AI coding agent that builds an After Effects or Premiere
|
|
9
|
+
Pro extension with AfterPresets. They describe the `AP.*` API that every panel gets.
|
|
10
10
|
|
|
11
11
|
## What the runtime does
|
|
12
12
|
|
|
@@ -17,9 +17,9 @@ screen, style, and word the user sees.
|
|
|
17
17
|
It gives you:
|
|
18
18
|
|
|
19
19
|
- `AP.boot` to start the panel.
|
|
20
|
-
- Licensing, off by default. Paid extensions must
|
|
20
|
+
- Licensing, off in `AP.boot` by default (the starter project turns it on). Paid extensions must keep it on.
|
|
21
21
|
- Signed updates with changelogs.
|
|
22
|
-
- `AP.host.eval` to call After Effects
|
|
22
|
+
- `AP.host.eval` to call ExtendScript functions in the app (After Effects or Premiere Pro).
|
|
23
23
|
- `AP.panels` and `AP.events` for extensions with more than one panel.
|
|
24
24
|
- `AP.paths` to find the images, videos and other files you ship.
|
|
25
25
|
- `AP.storage` to save settings and other small data on this computer.
|
|
@@ -40,15 +40,17 @@ and your memory disagree, the file wins.
|
|
|
40
40
|
| [boot.md](boot.md) | call `AP.boot`, use `ctx`, or change when the app starts |
|
|
41
41
|
| [licensing.md](licensing.md) | turn licensing on, write `renderLicense`, or change the license screen |
|
|
42
42
|
| [updates.md](updates.md) | change update options or the update screen, or show a changelog |
|
|
43
|
-
| [host.md](host.md) | call
|
|
43
|
+
| [host.md](host.md) | call the app from the panel or write `jsx/` code |
|
|
44
|
+
| [host-after-effects.md](host-after-effects.md) | write ExtendScript for After Effects (`jsx/aeft/`) |
|
|
45
|
+
| [host-premiere.md](host-premiere.md) | write ExtendScript for Premiere Pro (`jsx/ppro/`) |
|
|
44
46
|
| [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
|
|
47
|
+
| [assets.md](assets.md) | add images, fonts, videos or other files, or import a file into the app |
|
|
46
48
|
| [storage.md](storage.md) | save settings, recent items or any other data between launches |
|
|
47
49
|
|
|
48
50
|
## Commands you will use
|
|
49
51
|
|
|
50
52
|
```sh
|
|
51
|
-
ap dev # build, link into
|
|
53
|
+
ap dev # build, link into the app, rebuild on change
|
|
52
54
|
ap check # static checks; also run by ap dev and ap push
|
|
53
55
|
ap add panel settings --type modal
|
|
54
56
|
ap push # publish a release (asks for version bump and changelog)
|
|
@@ -57,7 +59,7 @@ ap docs # refresh docs/afterpresets/ from the runtime
|
|
|
57
59
|
|
|
58
60
|
## Compatibility
|
|
59
61
|
|
|
60
|
-
Panels run in Adobe CEP 10 or later (After Effects 2020+). Its browser is old
|
|
62
|
+
Panels run in Adobe CEP 10 or later (After Effects 2020+, Premiere Pro 2020+). Its browser is old
|
|
61
63
|
(Chromium 74 in CEP 10). Write plain ES5 in panel code: `var`, `function`, no
|
|
62
64
|
arrow functions, no `let`/`const`, no `class`, no template strings, no
|
|
63
65
|
`fetch`-only features. ExtendScript in `jsx/` is ES3 (see [host.md](host.md)).
|
|
@@ -51,7 +51,7 @@ Use `AP.paths`; never build paths by hand.
|
|
|
51
51
|
| `AP.paths.extension()` | Absolute path of the installed extension folder. |
|
|
52
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
53
|
|
|
54
|
-
## From ExtendScript (importing into
|
|
54
|
+
## From ExtendScript (importing into the app)
|
|
55
55
|
|
|
56
56
|
ExtendScript cannot see the panel's folders by itself. Pass the absolute path
|
|
57
57
|
from the panel:
|
|
@@ -64,7 +64,7 @@ ctx.host.eval("importClip", [AP.paths.asset("media/intro.mp4")], function (resul
|
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
```js
|
|
67
|
-
// jsx/media.jsx (loaded automatically, like every .jsx file in jsx/)
|
|
67
|
+
// After Effects: jsx/aeft/media.jsx (loaded automatically, like every .jsx file in jsx/)
|
|
68
68
|
function importClip(path) {
|
|
69
69
|
var file = new File(path);
|
|
70
70
|
if (!file.exists) return JSON.stringify({ error: "Missing file: " + path });
|
|
@@ -72,3 +72,17 @@ function importClip(path) {
|
|
|
72
72
|
return JSON.stringify({ ok: true, name: item.name });
|
|
73
73
|
}
|
|
74
74
|
```
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
// Premiere Pro: jsx/ppro/media.jsx
|
|
78
|
+
function importClip(path) {
|
|
79
|
+
var file = new File(path);
|
|
80
|
+
if (!file.exists) return JSON.stringify({ error: "Missing file: " + path });
|
|
81
|
+
// importFiles(paths, suppressUI, targetBin, importAsNumberedStills)
|
|
82
|
+
var ok = app.project.importFiles([file.fsName], true, app.project.getInsertionBin(), false);
|
|
83
|
+
return JSON.stringify({ ok: ok === true, name: file.name });
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Both files define the same function name: an extension for both apps calls
|
|
88
|
+
`importClip` and each app loads its own version.
|
|
@@ -35,7 +35,7 @@ once.
|
|
|
35
35
|
|
|
36
36
|
After a successful online check the API returns a signed record of it, valid
|
|
37
37
|
for 12 hours, and the runtime saves it with the token. Until it runs out,
|
|
38
|
-
launching
|
|
38
|
+
launching the app, reloading a panel (including `ap dev` reloads) or
|
|
39
39
|
opening another panel unlocks straight away, with no network call and no
|
|
40
40
|
`checking` screen. After 12 hours the license is checked online again, without blocking the
|
|
41
41
|
buyer:
|
|
@@ -12,9 +12,9 @@ HTML, and JavaScript. They share `js/`, `css/`, `jsx/`, and the license.
|
|
|
12
12
|
|
|
13
13
|
| `type` | What it is | Use it for |
|
|
14
14
|
|---|---|---|
|
|
15
|
-
| `panel` | A dockable
|
|
16
|
-
| `modal` | A dialog that blocks
|
|
17
|
-
| `invisible` | No window; starts with
|
|
15
|
+
| `panel` | A dockable panel, listed in **Window → Extensions** when `menu` is true | The main UI |
|
|
16
|
+
| `modal` | A dialog that blocks the app until closed | Settings, confirmations, one-off forms |
|
|
17
|
+
| `invisible` | No window; starts with the app and runs in the background | Listening for events, background work |
|
|
18
18
|
|
|
19
19
|
Panels are declared in `afterpresets.json`:
|
|
20
20
|
|
|
@@ -37,7 +37,7 @@ This creates `src/panels/<id>/index.html` and `src/panels/<id>/main.js`, and
|
|
|
37
37
|
adds the entry to `afterpresets.json`. Each panel calls `AP.boot` in its own
|
|
38
38
|
`main.js` and imports the screens and helpers it uses from `src/features/`
|
|
39
39
|
and `src/shared/`. After adding a panel, restart
|
|
40
|
-
`ap dev` and then
|
|
40
|
+
`ap dev` and then the app: CEP reads the manifest only at launch.
|
|
41
41
|
|
|
42
42
|
## AP.panels
|
|
43
43
|
|
|
@@ -49,7 +49,7 @@ AP.panels.close("settings"); // ask another open panel to close itself
|
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
- Ids are the ones in `afterpresets.json`. An invalid id throws.
|
|
52
|
-
- `open` asks
|
|
52
|
+
- `open` asks the app to open the extension `<bundleId>.<id>`. It returns
|
|
53
53
|
`true` when the request was sent; it does not wait for the panel to load.
|
|
54
54
|
- Data cannot be passed to `open`. Send it with `AP.events` once the other
|
|
55
55
|
panel is ready (see "Handshake" below).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Saving data
|
|
3
|
-
description: Where an extension keeps settings and other local state with AP.storage and AP.paths.data(), what goes inside the
|
|
3
|
+
description: Where an extension keeps settings and other local state with AP.storage and AP.paths.data(), what goes inside the app's project file instead, and what never to store.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Saving data
|
|
@@ -11,7 +11,7 @@ description: Where an extension keeps settings and other local state with AP.sto
|
|
|
11
11
|
|---|---|
|
|
12
12
|
| Settings, preferences, recent items, small caches | `AP.storage` (below) |
|
|
13
13
|
| Bigger files you create or download (images, media, generated presets) | A file in `AP.paths.data()` |
|
|
14
|
-
| Data that belongs to one After Effects project | Inside the `.aep`, from `jsx/` (it travels with the project file) |
|
|
14
|
+
| Data that belongs to one After Effects or Premiere Pro project | Inside the `.aep` / `.prproj`, from `jsx/` (it travels with the project file) |
|
|
15
15
|
| Secrets (passwords, API keys, tokens) | Nowhere. Everything above is a plain file the user can open. |
|
|
16
16
|
|
|
17
17
|
Do **not** use `localStorage`, `sessionStorage` or IndexedDB: in CEP each panel
|
|
@@ -71,12 +71,12 @@ var path = require("path");
|
|
|
71
71
|
var file = path.join(AP.paths.data(), "thumbnails", "intro.png");
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
Pass such paths to ExtendScript as arguments when
|
|
74
|
+
Pass such paths to ExtendScript as arguments when the app needs them
|
|
75
75
|
(see [assets.md](assets.md)).
|
|
76
76
|
|
|
77
|
-
## Inside the
|
|
77
|
+
## Inside the project file
|
|
78
78
|
|
|
79
79
|
Data about one project (which presets it uses, a layout you applied) belongs in
|
|
80
|
-
the project, not on the computer: it should follow the `.aep` to another
|
|
80
|
+
the project, not on the computer: it should follow the `.aep` or `.prproj` to another
|
|
81
81
|
machine. Read and write it from a `jsx/` function, for example in a project
|
|
82
82
|
XMP field or on a layer or comp comment, and call it with `ctx.host.eval`.
|
|
@@ -230,7 +230,7 @@ callback only.
|
|
|
230
230
|
| `dev_build` | `ap dev` builds never install updates | Expected during development. Do not show the failure popup. |
|
|
231
231
|
| `busy` | Another install is running | Try again later. |
|
|
232
232
|
| `bad_signature`, `bad_checksum`, `bad_zip`, `bad_update_info` | The download failed verification; nothing was installed | Show the failure popup. Do not retry in a loop. |
|
|
233
|
-
| `verify_unsupported` |
|
|
233
|
+
| `verify_unsupported` | The app is too old to verify signatures | Show the failure popup (reinstall from the product page). |
|
|
234
234
|
| `download_failed`, `install_failed` | Download or copy failed (the previous version is restored) | Show the failure popup. |
|
|
235
235
|
|
|
236
236
|
## Channels
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: AfterPresets native effect reference
|
|
3
|
+
description: Which file to read before writing or changing a C++ After Effects effect plugin built with AfterPresets.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# AfterPresets native effect reference
|
|
7
|
+
|
|
8
|
+
These files are for the AI coding agent that builds an After Effects effect
|
|
9
|
+
plugin (C++, Adobe's effect SDK) with AfterPresets. An effect is a new entry
|
|
10
|
+
in the Effect menu that renders pixels, like a glow or a blur.
|
|
11
|
+
|
|
12
|
+
## The rule
|
|
13
|
+
|
|
14
|
+
**Read [rules.md](rules.md) before you write or change any effect code, and
|
|
15
|
+
follow [testing.md](testing.md) before you say a change is done.** Then read
|
|
16
|
+
the SDK topic files for your task (index: [sdk/README.md](sdk/README.md)). Do
|
|
17
|
+
not guess struct fields, flag names, selectors or call order. If a file and
|
|
18
|
+
your memory disagree, the file wins. If the SDK guide and the SDK headers in
|
|
19
|
+
the project disagree, the headers win.
|
|
20
|
+
|
|
21
|
+
## Files
|
|
22
|
+
|
|
23
|
+
| File | Read it before you |
|
|
24
|
+
|---|---|
|
|
25
|
+
| [rules.md](rules.md) | write or change any effect code: the hard rules, each with why and an example |
|
|
26
|
+
| [testing.md](testing.md) | say "done": build, apply the effect in After Effects, render frames and look at them |
|
|
27
|
+
| [debugging.md](debugging.md) | chase a crash, an effect that does not load, wrong pixels, or a slow render |
|
|
28
|
+
| [sdk/README.md](sdk/README.md) | use any part of the After Effects SDK: tasks mapped to small topic files |
|
|
29
|
+
|
|
30
|
+
## About sdk/
|
|
31
|
+
|
|
32
|
+
`sdk/` is Adobe's After Effects C++ SDK guide, cut into small topic files. It
|
|
33
|
+
is generated on this computer from a pinned version of the community copy at
|
|
34
|
+
https://github.com/docsforadobe/after-effects-plugin-guide. AfterPresets does
|
|
35
|
+
not ship it: the guide is copyright Adobe. Never copy its text into the
|
|
36
|
+
product, its listing or its source files. Search it with:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
grep -rn "PF_OutFlag2_SUPPORTS_THREADED_RENDERING" docs/afterpresets/sdk/
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Adobe's SDK itself (headers, samples, `Util/` helpers) is not redistributed
|
|
43
|
+
either. The project gets it from Adobe; never commit it to a public
|
|
44
|
+
repository.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Debugging a native effect
|
|
3
|
+
description: Find out why an effect does not load, crashes, renders wrong pixels or is slow, without an IDE - scripting checks, binary checks, crash reports, logs and debugger limits.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Debugging a native effect
|
|
7
|
+
|
|
8
|
+
You have no IDE and usually no debugger attached. Work from evidence you can
|
|
9
|
+
collect yourself: scripting queries through `host_eval`, frames from
|
|
10
|
+
`comp_capture`, the built binary, crash reports and logs. Change one thing at
|
|
11
|
+
a time and test again ([testing.md](testing.md)).
|
|
12
|
+
|
|
13
|
+
## The effect does not appear or does not apply
|
|
14
|
+
|
|
15
|
+
1. **Is it loaded?** Ask After Effects for its effect list:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
var out = [];
|
|
19
|
+
for (var i = 0; i < app.effects.length; i++) {
|
|
20
|
+
var e = app.effects[i];
|
|
21
|
+
if (/ACME/.test(e.matchName)) out.push(e.matchName + " | " + e.displayName + " | " + e.category);
|
|
22
|
+
}
|
|
23
|
+
return out.join("\n") || "not loaded";
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Listed, but `addProperty` fails: you are using a different match name.
|
|
27
|
+
Not listed: After Effects did not load the binary; go on.
|
|
28
|
+
2. **Was After Effects restarted** after the binary was installed? Plugins
|
|
29
|
+
load at launch only.
|
|
30
|
+
3. **Is it where After Effects looks?** See
|
|
31
|
+
[sdk/where-installers-should-put-plug-ins.md](sdk/where-installers-should-put-plug-ins.md).
|
|
32
|
+
Folders whose names end in parentheses, or start with `¬` (macOS) or `~`
|
|
33
|
+
(Windows), are not scanned. `ap dev` installs into
|
|
34
|
+
`/Library/Application Support/Adobe/Common/Plug-ins/7.0/MediaCore/AfterPresets Dev/<bundleId>/`,
|
|
35
|
+
a folder made once with administrator rights and then owned by the user;
|
|
36
|
+
buyers' copies go to `MediaCore/AfterPresets/<bundleId>/`. Any other
|
|
37
|
+
write to the shared MediaCore folder or the After Effects `Plug-ins`
|
|
38
|
+
folder needs administrator rights: ask the user, never use `sudo`
|
|
39
|
+
yourself.
|
|
40
|
+
4. **Check the binary** (macOS):
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
lipo -info Effect.plugin/Contents/MacOS/Effect # arm64 and x86_64 for a universal build
|
|
44
|
+
nm -gU Effect.plugin/Contents/MacOS/Effect # the entry point must be exported
|
|
45
|
+
codesign -dv Effect.plugin # must be signed (ad-hoc is enough to develop)
|
|
46
|
+
xattr -l Effect.plugin # com.apple.quarantine set by downloads
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
macOS 15 and later refuse unsigned plugins; sign development builds
|
|
50
|
+
ad-hoc with `codesign --force --deep --sign - Effect.plugin`, and do not
|
|
51
|
+
touch the bundle after signing. The PiPL needs an entry point for every
|
|
52
|
+
architecture you build (`CodeMacARM64`, `CodeMacIntel64`, `CodeWin64X86`).
|
|
53
|
+
5. **Check the PiPL against GlobalSetup**: flags (rule 2 in
|
|
54
|
+
[rules.md](rules.md)), match name, version. A mismatch warning appears when
|
|
55
|
+
the effect is applied; ask the user to read you any dialog.
|
|
56
|
+
6. **Read After Effects' plugin loading log.** It is rewritten at every
|
|
57
|
+
launch: `~/Library/Preferences/Adobe/After Effects/<version>/Plugin Loading.log`
|
|
58
|
+
(for example `26.2`). Search it for your bundle name:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
grep -n -i "MyEffect" ~/Library/Preferences/Adobe/After\ Effects/*/Plugin\ Loading.log
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The line "No loaders recognized this plugin … Ignore" is normal for After
|
|
65
|
+
Effects effects (it comes from the shared MediaCore loader). A missing
|
|
66
|
+
line means After Effects never saw the file (wrong folder, not
|
|
67
|
+
restarted); a load error points at the binary (step 4) or the PiPL
|
|
68
|
+
(step 5).
|
|
69
|
+
|
|
70
|
+
Whether a plugin loads also depends on how After Effects itself is signed
|
|
71
|
+
(hardened runtime, library validation). A result on one computer, for
|
|
72
|
+
example one with a re-signed or developer copy of After Effects, may not
|
|
73
|
+
match a customer's computer.
|
|
74
|
+
|
|
75
|
+
## After Effects crashes
|
|
76
|
+
|
|
77
|
+
- macOS writes a crash report to `~/Library/Logs/DiagnosticReports/`
|
|
78
|
+
(`Adobe After Effects*.ips`). Find the crashed thread and look for frames in
|
|
79
|
+
your binary. Build development versions with debug symbols (`-g`) and keep
|
|
80
|
+
the `.dSYM`, so addresses map to functions and lines (`atos -o
|
|
81
|
+
Effect.plugin.dSYM/Contents/Resources/DWARF/Effect -arch arm64 -l <load
|
|
82
|
+
address> <address>`).
|
|
83
|
+
- Usual causes: reading past a row (`rowbytes`, wrong pixel type for the
|
|
84
|
+
depth), an exception leaving the entry point (rule 15), a world used after
|
|
85
|
+
`PF_DisposeWorld`, writing shared state from several render threads
|
|
86
|
+
(rule 11), unbalanced parameter checkouts (rule 10).
|
|
87
|
+
- After a crash, After Effects may show a recovery dialog at the next launch.
|
|
88
|
+
Ask the user to answer it; do not script around it.
|
|
89
|
+
|
|
90
|
+
## Wrong pixels
|
|
91
|
+
|
|
92
|
+
- Capture the same frame at 8, 16 and 32 bpc. Wrong in one depth only: that
|
|
93
|
+
depth's code path or its maximum channel value (32768 for 16 bpc).
|
|
94
|
+
- Bright random colours, rainbows, black blotches: integer overflow; clamp
|
|
95
|
+
before converting.
|
|
96
|
+
- Wrong only at half resolution or with an effect before yours: downsample
|
|
97
|
+
factors or buffer origin ([rules.md](rules.md), rule 9).
|
|
98
|
+
- To see an internal value, temporarily write it into the output (for example
|
|
99
|
+
a red channel proportional to the value) and capture the frame. Remove it
|
|
100
|
+
afterwards.
|
|
101
|
+
- Unchanged after a rebuild: After Effects still runs the old binary
|
|
102
|
+
(restart), or you looked at a cached frame (`comp_capture` clears caches by
|
|
103
|
+
default; keep it that way).
|
|
104
|
+
|
|
105
|
+
## Slow renders
|
|
106
|
+
|
|
107
|
+
`comp_capture` reports a render time per frame, measured after clearing the
|
|
108
|
+
caches. Compare before and after a change on the same frames. Typical fixes:
|
|
109
|
+
precompute tables once (GlobalSetup or SequenceSetup), avoid `pow`/`sqrt`/
|
|
110
|
+
division per pixel, fuse passes, process only the requested area, and enable
|
|
111
|
+
multi-frame rendering when the effect is thread-safe (rule 11).
|
|
112
|
+
|
|
113
|
+
## Logs
|
|
114
|
+
|
|
115
|
+
The AfterPresets native runtime (`ap_native`) writes a small log for each
|
|
116
|
+
plugin: `~/Library/Logs/AfterPresets/<bundleId>.log` on macOS (rotated at
|
|
117
|
+
1 MB; `ap_log_path()` returns the exact path). Each After Effects start adds
|
|
118
|
+
a `start <bundleId> <version> build=...` line, then licence and update
|
|
119
|
+
events. Read it with `tail -n 50`. It is safe to read: tokens and URL query
|
|
120
|
+
strings are scrubbed.
|
|
121
|
+
|
|
122
|
+
To log from effect code, call `ap_log(rt, level, "message")`: it never
|
|
123
|
+
blocks and does no file I/O on the calling thread, so it is allowed in
|
|
124
|
+
render code, but never log from inside the per-pixel loop. Never log licence
|
|
125
|
+
tokens, account data or user paths, and remove temporary logging before
|
|
126
|
+
release.
|
|
127
|
+
|
|
128
|
+
## Debuggers
|
|
129
|
+
|
|
130
|
+
Attaching `lldb` to a release build of After Effects 26.5 or later on macOS is
|
|
131
|
+
refused because of how the application is signed. Adobe's workaround (a
|
|
132
|
+
re-signed copy, or developer mode for beta builds) needs the user and
|
|
133
|
+
administrator rights: see [sdk/debugging-ae-macos.md](sdk/debugging-ae-macos.md).
|
|
134
|
+
Prefer the evidence above; propose a debugger session to the user only when
|
|
135
|
+
it is the only way forward.
|
|
136
|
+
|
|
137
|
+
Holding Cmd+Opt+Shift (macOS) or Ctrl+Alt+Shift (Windows) while After Effects
|
|
138
|
+
starts resets its preferences, which clears settings a plugin may have
|
|
139
|
+
stored. Only the user should do this, after being told it resets all their
|
|
140
|
+
preferences.
|