Merge remote-tracking branch 'origin/main' into jp/ja-dialogs

# Conflicts:
#	ROADMAP.md
#	crates/ui-egui/src/dock_ui.rs
#	crates/ui-egui/src/i18n/ui.rs
#	docs/gaps.md
#	docs/localization-parity.md
This commit is contained in:
midasdf
2026-10-24 10:03:09 +09:00
263 changed files with 6582 additions and 1503 deletions
+7 -1
View File
@@ -216,7 +216,7 @@ Things that tripped up a long agent-driven session (a multi-scene 3D piece built
### Cookbook (from end-to-end QA)
The scenarios in `crates/automation/tests/qa/` and `apps/effectcraft-cli/tests/qa_template.rs`
The scenarios in `crates/automation/tests/qa/` and `apps/effectcraft-cli/tests/it/qa_template.rs`
build real projects through these interfaces; they are worked examples of everything below.
* **Name things when you create them**: `layer.newText`, `layer.newShape`, `layer.newSolid`,
@@ -595,6 +595,12 @@ Extension points and the bundled extensions: [plugins.md](plugins.md).
properties, FF missing effects, EE Expressions, LL Waveform, UU everything changed from its
default. Shift+key adds or removes a set; the same key again hides it; Ctrl/Cmd+` twirls the
selected layers open or closed. With no layer selected they apply to every layer.
* A row control clicked on one of several selected layers applies to every selected layer, as in
After Effects: the A/V switches (video, audio, solo, lock), the Switches column (shy, collapse,
quality, fx, frame blending, motion blur, adjustment, 3D), the label swatch and the Modes column
(blending mode, Preserve Transparency), one undo step, with the layers the switch doesn't apply
to left out. A control on an unselected row changes that layer alone; Alt-clicking an A/V feature
still sets the selected layers apart from the rest.
* `keys.toggleTransform {"layers"?: [...], "prop": "position"}` (Alt+Shift+A/P/S/R/T) adds or
removes a keyframe at the current time on that Transform property of each layer, in one undo
step (separated X/Y/Z Position; Orientation and X/Y/Z Rotation on 3D layers).
+1 -1
View File
@@ -51,7 +51,7 @@ export formats, parity summary), `jobs.list` (Progress panel jobs, e.g. the back
`footage.check` after File ▸ Open).
Every engine command is reachable through `engine.execute`, and every interactive widget of every
panel registers an element id; both are enforced by `crates/ui-egui/tests/ui_agent_audit.rs`.
panel registers an element id; both are enforced by `crates/ui-egui/tests/it/ui_agent_audit.rs`.
## UI state
+1 -1
View File
@@ -4,7 +4,7 @@ These checks use original compositions and public interaction behavior. No Adobe
implementation code are included. Adobe's [selection documentation](https://helpx.adobe.com/after-effects/desktop/work-with-layers/select-and-arrange-layers/selecting-arranging-layers.html)
describes Timeline range selection and Composition Shift-click/Shift-marquee selection.
`crates/ui-egui/tests/ui_workflow_selection.rs` exercises actual pointer and keyboard events:
`crates/ui-egui/tests/it/ui_workflow_selection.rs` exercises actual pointer and keyboard events:
- Timeline Shift-click selects the visible range, skipping locked layers; Ctrl/Command-click toggles a layer.
- A drag beginning in the empty Timeline outline selects the intersected layer rows without reordering them.
+19
View File
@@ -70,6 +70,16 @@ next to it.
Agents: `file.importProject {"path": "/projects/titles.ecproj"}` returns the comps, the root comps,
`primaryComp` (the only root comp, if there is one) and any missing media.
## Finding a layer's source in the Project panel
Right-click a layer in the Timeline or Composition panel and choose **Reveal Layer Source in
Project** (also Layer ▸ Reveal ▸ Reveal Layer Source in Project). The Project panel opens, its
search is cleared, the folders holding the source open, and the source item is selected.
Layers whose image is generated inside the composition — text, shape, null, camera, light and
3D primitive layers — have no Project item, so the command is not offered for them. Adjustment
layers do have one: the solid that backs them.
## Interpret Footage
Select a footage item in the Project panel and choose **File ▸ Interpret Footage ▸ Main…**
@@ -110,6 +120,15 @@ vectors, positions and IDs are never the picture. EXtractoR reads every other la
Importing a layered file as a composition refreshes the decoded sources used by its layers,
including files overwritten at the same path and byte size.
- **Replace a layer's source** without rebuilding the layer: Alt-drag (Option-drag on macOS) a
footage item, composition or solid from the Project panel onto a layer in the Timeline. The
layer keeps its name, timing, transforms, keyframes, expressions, effects, masks, switches,
parenting and track matte; only its source changes. A source with audio adds Audio properties
when the layer has none. To replace several selected layers with the selected Project item, press
Ctrl+Alt+/ (Cmd+Opt+/). Compositions, footage and solids are interchangeable; folders, data files
and 3D models are not sources, and a composition can't be nested in itself. Alt-dragging onto a
layer is one layer at a time, as in After Effects.
Agents: `layer.replaceSource {"item": id, "layers": [ids]}`.
- **File ▸ Replace Footage ▸ File…** (Ctrl+H) points the item at another file. Pick a numbered
file to replace it with that file's whole sequence (`file.replaceFootage {"path": …,
"sequence": false}` for one frame).
+3 -3
View File
@@ -72,7 +72,7 @@ are grouped by area; the issue tracker has the rest.
| 13 | **3D model formats and materials** | After Effects 26 imports FBX, USD/USDZ, STL besides glTF and OBJ (`usd_plugins`), and Substance 3D materials with mesh displacement (26.0–26.2); we read glTF, OBJ, STL (binary and ASCII, with facet colours) and FBX 7.x (binary and ASCII: meshes, hierarchy, Lambert/Phong materials and textures; no FBX animation or skinning yet) | Product shots and 3D scenes come as FBX/USDZ | 25–45 h | — · [file-format-parity.md](file-format-parity.md) |
| 14 | **Object Matte** (26.2, disk cache in 26.5) | First slice (#783): the Object Matte effect (Effect ▸ Matte) and `objectMatte.apply` turn a point (and optional box) on a reference frame into a matte and follow the object up to 600 frames each way, or segment every frame on its own; Roto Brush's engine, cache and model (MobileSAM from Settings ▸ Roto Brush, classical graph cut without it). Since then: the Object Matte tool in the viewer (click / drag a box, hover crosshair), the box as the model's box prompt, background tracking with progress and cancel, Freeze, and segmentations kept in the disk cache (26.5). Missing: a comparison with After Effects ([plan](fidelity/object-matte.md)) | The new one-click roto | 10–20 h | G7 · [target-app-parity.md](target-app-parity.md) |
| 15 | **Hardware video decode and encode** | No VideoToolbox, NVENC, Quick Sync or VA-API; #498 asks for it (answered: CUDA / NVENC need Nvidia's proprietary SDK through FFI, which the no-`unsafe` rule forbids); open PR #819 adds hardware decoding via `filmcraft-platform`; FilmCraft has VideoToolbox / NVENC / VA-API paths to borrow | 4K playback and export speed | 25–45 h | G5/G6 · [hardware-parity.md](hardware-parity.md) |
| 16 | **Localization depth** | Menus in 10 languages (ja, zh-hans, zh-hant, uk, es, pt-br, ru, fr, de, cs: 628 rows each); panels in 6 (ja 996 rows, zh-hans and zh-hant 998 each, uk 524, pt-br 417, cs 518); effect names translated in Simplified Chinese (306, plus the generated Effect menu), their ~1,650 parameter names untranslated; Korean and Italian (After Effects ships them) absent; Hangul probe added (#599 closed) | After Effects is used heavily in Japan, China, Korea, Brazil, Europe | 60–110 h + native review | G9 · [localization-parity.md](localization-parity.md) |
| 16 | **Localization depth** | Menus in 11 languages (ja, zh-hans, zh-hant, uk, es, pt-br, ru, fr, de, cs, ka: 628 rows each); panels in 7 (ja 996 rows, zh-hans and zh-hant 998 each, uk 524, pt-br 417, cs 518, ka 886); effect names translated in Simplified Chinese (306) and Georgian (307, plus the generated Effect menu), their ~1,650 parameter names untranslated; Korean and Italian (After Effects ships them) absent; Hangul probe added (#599 closed) | After Effects is used heavily in Japan, China, Korea, Brazil, Europe | 60–110 h + native review | G9 · [localization-parity.md](localization-parity.md) |
| 17 | **Media Browser lists files import refuses** | `media_browser.rs` lists AVI; `media::is_importable` has none of them (Targa and Radiance HDR import since #745; DPX and Cineon since #756, log shown as stored: no Cineon Settings conversion yet; MXF OP1a / OP-Atom since #767; FilmCraft has no AVI demuxer); #431 and #324 closed | Confusing failures on common VFX formats | 15–30 h | G6 · [file-format-parity.md](file-format-parity.md) |
| 18 | **Relative paths and relinking** | Projects store absolute footage paths; no relink when a project moves | Moving or sharing a project breaks it | 6–12 h | G4 · [file-format-parity.md](file-format-parity.md) |
| 19 | **Plug-in ecosystem** | No After Effects SDK hosting (#600, #327 OpenFX, #334, #376 plug-in manager); our WebAssembly API has no third-party plug-ins | Many pro projects depend on Trapcode, Element, Saber… | 40–80 h for API growth; SDK hosting needs an owner decision | G8 · [scripting-parity.md](scripting-parity.md) |
@@ -313,8 +313,8 @@ Issues #41–#47 (all from the Linux AppImage 0.1.1, 5 October): panning the vie
- Localisation of the interface ([localization-parity.md](localization-parity.md)): since 6–12
October the menus are translated into Japanese, Simplified and Traditional Chinese, Ukrainian,
Spanish, Brazilian Portuguese, Russian, French, German and Czech, and the panel catalog covers
Japanese, both Chinese, Ukrainian, Brazilian Portuguese and Czech. Next: effect and parameter
Spanish, Brazilian Portuguese, Russian, French, German, Czech and Georgian, and the panel catalog covers
Japanese, both Chinese, Ukrainian, Brazilian Portuguese, Czech and Georgian. Next: effect and parameter
names, the remaining panel strings (Spanish, Russian, French, German), Korean and Italian, and
native-speaker review of all of them.
- Accessibility (keyboard navigation, screen readers, contrast), user documentation and
+19 -9
View File
@@ -1,6 +1,6 @@
# Localization parity
> **Last reviewed:** 2026-10-22 · **Last updated:** 2026-10-22 · **Change:** minor (the panel/dialog catalogs grow by 303 rows in Japanese, Simplified Chinese and Traditional Chinese: panel tabs, form and dialog labels, context menus, tracker/graph/text-panel labels, credits and File-panel footers; Japanese 1,624 of ≈ 4,200 interface strings (39%), Simplified and Traditional Chinese 1,626 (Simplified Chinese 1,932 with its 306 effect names, 46%); previously: minor, catalogs recounted at `upstream/main` 470ea7a3: menus in 10 languages, panels in 6, Hangul probe (#599)) · **Target:** Adobe After Effects 2026
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-23 · **Change:** minor (Georgian: menus, panels and effect names; missing strings show in English; `missing_translations_report` lists them; previously: minor, the panel/dialog catalogs grow by 303 rows in Japanese, Simplified Chinese and Traditional Chinese: panel tabs, form and dialog labels, context menus, tracker/graph/text-panel labels, credits and File-panel footers; Japanese 1,624 of ≈ 4,200 interface strings (39%), Simplified and Traditional Chinese 1,626 (Simplified Chinese 1,932 with its 306 effect names, 46%); previously: minor, catalogs recounted at `upstream/main` 470ea7a3: menus in 10 languages, panels in 6, Hangul probe (#599)) · **Target:** Adobe After Effects 2026
How much of EffectCraft's interface is translated, language by language, compared with After
Effects. [gaps.md](gaps.md) gap 16 and workstream G9 hold the work;
@@ -17,16 +17,18 @@ interface; Arabic and Hebrew text *in layers* is supported through its Middle Ea
## How EffectCraft translates
- **Menus:** `crates/ui-egui/src/i18n.rs`, one catalog per language keyed by
`(command, English label)`. A test (`every_translation_key_exists_in_the_actual_menu_tree`)
fails if any fixed menu entry is untranslated or a row is stale, so every catalog covers all
fixed entries (628 catalog rows each at `ad8b6acb`, counted). The generated Effect menu is not part of that fixed tree: its entries
and category submenus take their labels from the effect catalog below.
`(command, English label)`. A test (`menu_catalogs_have_no_stale_or_duplicate_rows`) fails on a
row whose entry left the menu tree or on a repeated row, so every catalog covers all fixed
entries (628 catalog rows each at `ad8b6acb`, counted). The generated Effect menu is not part of
that fixed tree: its entries and category submenus take their labels from the effect catalog
below.
- **Panels, dialogs, buttons, tooltips:** `crates/ui-egui/src/i18n/ui.rs`, keyed by the English
source string, with English fallback. Catalogs exist for Japanese (996 rows), Simplified and
Traditional Chinese (998 each), Ukrainian (524), Brazilian Portuguese (417), Czech (518) and
Spanish (513); counted at `ad8b6acb`.
Spanish (513); counted at `ad8b6acb`. Georgian has the 695 rows the Chinese catalogs held at
`470ea7a3`, plus 191 for panels converted to the catalog since (886 in all).
- **Effect names:** `crates/ui-egui/src/i18n/effects.rs`, keyed by **effect id**, in Simplified
Chinese (306 rows, one per effect in the registry, plus its 21 categories). The registry's
Chinese and Georgian (307 rows, one per effect in the registry, plus its 21 categories). The registry's
English name stays the effect's identity: `effect.list`, `effect.apply {"effect": …}`, scripts
and expressions match on it, and the property tree stores it as the effect group's name. Only
the drawing — the Effect menu, Effect Controls, the Timeline and Effects & Presets — goes
@@ -38,6 +40,12 @@ interface; Arabic and Hebrew text *in layers* is supported through its Middle Ea
slot is for). Each language decides for itself which names stay English — Adobe's Japanese
interface leaves the `CC`, `VR` and `OCIO` sets in English while its Chinese one translates
them — so a row repeating the English name is a choice, not a missing row.
- **Missing strings:** a string with no row in the interface language shows in English, and no
test, build or release fails on a missing translation. The `missing_translations_report` test
(`crates/ui-egui/src/i18n.rs`) prints, per language, the fixed menu entries, panel strings, effect
names and effect categories that have no row. It always passes; `cargo xtask ci` runs it with
`--nocapture`, so the list is in the gate log. Locally:
`cargo test -p effectcraft-ui-egui --lib missing_translations_report -- --nocapture`.
- **Not translated anywhere yet:** effect *parameter* names (≈ 1,650, `crates/effects`),
engine-generated text (property names, errors, undo labels), the Home screen's unwrapped
literals (#574), Learn tutorials and documentation.
@@ -77,13 +85,14 @@ so the true percentages are slightly lower.
| Korean | `ko` | 0 | — | Hangul fallback probe added (#599, closed); not checked on macOS here | no | none | 9–13 h + review |
| Vietnamese | `vi` | 0 | — | Latin with stacked diacritics; untested | no | none (After Effects: none) | 8–12 h + review |
Other languages EffectCraft ships (3):
Other languages EffectCraft ships (4):
| Language | Code | UI strings translated | Status | To `full` |
|---|---|---|---|---|
| Traditional Chinese | `zh-hant` | 1,626 (≈ 39%): menus 628 rows, panels 998 | partial | 6–9 h + review |
| Ukrainian | `uk` | 1,152 (≈ 27%): menus 628 rows, panels 524 | partial | 6–9 h + review |
| Czech | `cs` | 1,146 (≈ 27%): menus 628 rows, panels 518 | Existing catalog entries covered; unwrapped UI, effects and engine text still in English; AI-assisted, not yet native-speaker proofread | Remaining strings + independent native review |
| Georgian | `ka` | 1,514 (≈ 39%): menus 628 rows, panels 886 (the Chinese catalogs' 695 at `470ea7a3` plus 191 Georgian-only rows: form dialogs, context menus, column headers), effect names 307 + 21 categories; native-speaker reviewed | partial | 5–8 h |
Russian (`ru`) has a menu catalog (628 rows, ≈ 15%); After Effects also ships Italian, which EffectCraft does not (8–12 h).
@@ -98,7 +107,7 @@ needs ≈ 2,600 more strings (≈ 5–9 h per language at the pace of #398 and #
Effects' 10 non-English languages: **≈ 60–110 h**; the four extra languages of the standard list
(Hindi, Arabic, Indonesian, Vietnamese) add ≈ 50–80 h, most of it right-to-left layout and
complex shaping in the interface. Every language needs native-speaker review, which only a human
can give; none has had it.
can give; only Georgian, contributed by a native speaker (#1843), has had it.
## Revision history
@@ -106,6 +115,7 @@ can give; none has had it.
|---|---|---|
| 2026-10-22 | minor | Panel/dialog second step: 300 more catalog rows in Japanese, Simplified Chinese and Traditional Chinese, plus the three rows the review found missing (Basic, Advanced and Play/Stop) — panel tabs, form and dialog labels, panel context menus, the tracker and graph controls, text-panel options, File-panel footers and credits; the panel tables are now 996 Japanese and 998 Chinese rows, all drawn through `tr`/`tr_args`, with the tests keeping the three catalogs listing the same sources; Simplified Chinese reaches 1,932 (46%) with its 306 effect names, and the overall share is 21% |
| 2026-10-12 | minor | Recounted: Russian, French, German and Czech menus (#873, #987), Brazilian Portuguese and Czech panels (#830, #987), Hangul probe (#599); overall ≈ 12% to ≈ 18%; Korean and Italian still absent |
| 2026-10-14 | minor | Georgian (`ka`): menus 628, panels 886 (191 Georgian-only, in `GEORGIAN_PANELS`), effect names and categories in `effects.rs` |
| 2026-10-10 | major | First localization parity document: catalog rows counted for all six languages, the twelve-language table, After Effects' 11 shipped languages from its bundle |
| 2026-10-11 | minor | Ukrainian panel catalog brought level with the Chinese ones (495 of 496 rows, counted at this commit); its share rises to ≈ 29%. The other languages' panel counts are the 10 October measurement |
| 2026-10-13 | minor | Effect names and the generated Effect menu leave English: `i18n/effects.rs` adds 306 rows keyed by effect id (Simplified Chinese, from After Effects 2026's interface and Adobe's Chinese documentation for the `CC` series) and the 21 category names. Parameter names are still English; no other language has rows |
+3 -2
View File
@@ -30,7 +30,7 @@ Commands (CLI, MCP, control channel):
### Settings that change behaviour
- `general.language`: interface language (`system` / `en` / `ja` / `zh-hans` / `zh-hant` / `uk` / `es` / `pt-br`), Settings ▸ General ▸ Language; menu labels change immediately. `system` (Match System, the default) follows the operating system's interface language where EffectCraft has a translation and is English otherwise: a Simplified Chinese locale (`zh`, `zh-CN`, `zh_CN.UTF-8`, `zh-Hans-CN`, `zh-SG`) selects `zh-hans`, a Traditional one (`zh-TW`, `zh-HK`, `zh-Hant`, `zh_MO`) selects `zh-hant`, a Ukrainian one (`uk`, `uk-UA`, `uk_UA.UTF-8`) selects `uk`, a Spanish one (`es`, `es-ES`, `es_MX.UTF-8`) selects `es`, a Portuguese one (`pt`, `pt-BR`, `pt_PT.UTF-8`) selects `pt-br`; the browser build stays in English with it. Choose **Español** or **Português (Brasil)** for Spanish or Brazilian Portuguese menus (panels stay in English for now); choose **Українська** for Ukrainian menus and cataloged panel, dialog, button and tooltip text; Ukrainian uses the bundled UI fonts. Native Japanese, Simplified and Traditional Chinese UI uses installed system fonts; the web host must supply a Japanese font. The same setting picks the CJK fallback for the interface *and* the Han preference of the text engine, so the composition's own text is drawn with the same language's glyph forms (the text engine's preference is process-global); swapping the language reinstalls the fonts, so it applies without a restart. Two catalogs back the text: the menus are keyed by `(command, English label)` (`crates/ui-egui/src/i18n.rs`), and the rest of the interface - panels, dialogs, buttons, tooltips - is keyed by its English source string (`crates/ui-egui/src/i18n/ui.rs`, with rows for Japanese, Simplified and Traditional Chinese and Ukrainian), where a panel writes `tr("Rename")`, or `tr_args("Proxy Use: {}", &[&quality])` when the row carries a value. A row that is missing falls back to English, so a new string shows up untranslated rather than empty; the tests in that module fail on an unused row and on a hard-coded string in a converted panel.
- `general.language`: interface language (`system` / `en` / `ja` / `zh-hans` / `zh-hant` / `uk` / `es` / `pt-br` / `ka`), Settings ▸ General ▸ Language; menu labels change immediately. `system` (Match System, the default) follows the operating system's interface language where EffectCraft has a translation and is English otherwise: a Simplified Chinese locale (`zh`, `zh-CN`, `zh_CN.UTF-8`, `zh-Hans-CN`, `zh-SG`) selects `zh-hans`, a Traditional one (`zh-TW`, `zh-HK`, `zh-Hant`, `zh_MO`) selects `zh-hant`, a Ukrainian one (`uk`, `uk-UA`, `uk_UA.UTF-8`) selects `uk`, a Spanish one (`es`, `es-ES`, `es_MX.UTF-8`) selects `es`, a Portuguese one (`pt`, `pt-BR`, `pt_PT.UTF-8`) selects `pt-br`, a Georgian one (`ka`, `ka-GE`, `ka_GE.UTF-8`) selects `ka`; the browser build follows `?lang=` in the address, then the browser's languages (`navigator.languages`). Choose **Español** or **Português (Brasil)** for Spanish or Brazilian Portuguese menus (panels stay in English for now); choose **Українська** for Ukrainian menus and cataloged panel, dialog, button and tooltip text; Ukrainian uses the bundled UI fonts. Native Japanese, Simplified and Traditional Chinese UI uses installed system fonts; the web host must supply a Japanese font. The same setting picks the CJK fallback for the interface *and* the Han preference of the text engine, so the composition's own text is drawn with the same language's glyph forms (the text engine's preference is process-global); swapping the language reinstalls the fonts, so it applies without a restart. Two catalogs back the text: the menus are keyed by `(command, English label)` (`crates/ui-egui/src/i18n.rs`), and the rest of the interface - panels, dialogs, buttons, tooltips - is keyed by its English source string (`crates/ui-egui/src/i18n/ui.rs`, with rows for Japanese, Simplified and Traditional Chinese and Ukrainian), where a panel writes `tr("Rename")`, or `tr_args("Proxy Use: {}", &[&quality])` when the row carries a value. A row that is missing falls back to English, so a new string shows up untranslated rather than empty; the `missing_translations_report` test lists what each language lacks, and the tests in `ui.rs` fail on an unused row.
- `general.undoLevels`: Levels of Undo
- `general.pathPointSize`: Path Point and Handle Size
- `general.recentItems`: Recent Projects Shown
@@ -91,7 +91,8 @@ Commands (CLI, MCP, control channel):
one and in the comps that nest it (through the precomp layers' timing)
- `general.expressionPickWhipCompact`: off, the pick whip writes match names
(`thisComp.layer("A")("transform")("opacity")`)
- `general.createSplitLayersAbove`: where Edit ▸ Split Layer puts the new layer
- `general.createSplitLayersAbove`: where Edit ▸ Split Layer puts the new layer (on by default,
as in After Effects)
- `startup.showHomeOnOpenProject`: the Home screen comes up after File ▸ Open / Open Recent
- `composition.motionPath`, `composition.motionPathSeconds`, `composition.motionPathKeyframes`:
how much of a position motion path the viewer draws (all, none, N seconds or N keyframes
+2 -2
View File
@@ -1068,7 +1068,7 @@ resolution, adjustment) and composited at 8 and 32 bpc:
Bucket's flood-filled region, Eyedropper Fill's sample); segments and convex polygons are
binned into 16 × 16 tiles and rasterised on the GPU with the CPU's coverage functions, glows
and compositing included. The CPU effects were refactored to draw from the same plans with
bit-identical output (`crates/effects/tests/gen_golden.rs`: 288 frame hashes pinned before
bit-identical output (`crates/effects/tests/it/gen_golden.rs`: 288 frame hashes pinned before
the refactor). Exception: CC Threads decides band membership and fibre shade per pixel, and at
round parameter values (the defaults) pixel centres sit exactly on band edges, where f32 and
the CPU's f64 can fall on either side: up to 5 % of pixels allowed (measured ≤ 3.6 % at half
@@ -1082,7 +1082,7 @@ resolution, adjustment) and composited at 8 and 32 bpc:
7 more effects run on the GPU (280 in all, with M13.28's 37), and five CPU fallbacks are gone. Each case is
checked against the CPU oracle (≤ 1/255 at 8 bpc, ≤ 1e-3 at 32 bpc) directly on a buffer (full
and half resolution) and composited at 8 and 32 bpc; the CPU refactors behind the shared plans
are pinned bit for bit by golden hashes (`crates/effects/tests/particle_golden.rs`,
are pinned bit for bit by golden hashes (`crates/effects/tests/it/particle_golden.rs`,
`timewarp_golden.rs`, `sim_golden.rs`).
- **Particle render passes** (`gpu::fx_particles`): CC Particle World and CC Particle Systems II
+10 -1
View File
@@ -5,6 +5,15 @@ cargo test --workspace # everything
cargo xtask ci # fmt, clippy -D warnings, tests, layers, assets, wasm
```
`cargo xtask ci` builds in the dev profile and runs the tests with `cargo nextest run` (plus
`cargo test --doc`) when `cargo-nextest` is installed, and with `cargo test` otherwise. It then
runs `missing_translations_report` with `--nocapture`, which prints the interface strings each
language has no translation for. Those strings show in English; the report always passes.
Each crate with several integration-test files has one test binary, `tests/it/main.rs`, whose
modules are the files in `tests/it/`. Run one file with `cargo test -p <crate> --test it <module>::`
or `cargo nextest run -p <crate> -E 'binary(it) and test(/^<module>::/)'`.
## What the tests cover
- **Engine commands** (`crates/engine/src/tests*.rs`): every command family, including undo and
@@ -16,7 +25,7 @@ cargo xtask ci # fmt, clippy -D warnings, tests, layers, assets, was
- **Effects** (`crates/effects`): each effect has a determinism test and at least one behaviour
test (identity at neutral settings, known pixel results, or simulations giving the same frame
whether you seek straight to it or play up to it). A registry-wide test checks that effects
which read the clock are declared time-dependent. `crates/effects/tests/sim_golden.rs` pins
which read the clock are declared time-dependent. `crates/effects/tests/it/sim_golden.rs` pins
exact pixel hashes of the simulation effects the GPU shares plans with (CC Rainfall … Card
Wipe) at several settings, times, bit depths and resolutions, so any change to their CPU output
fails (re-pin with `SIM_GOLDEN_PRINT=1` after an intended change; pinned for aarch64 macOS,
+1 -1
View File
@@ -17,7 +17,7 @@ feel and platform differences, and the 26.x interface changes are not in yet.
|---|---|---:|---|
| Menu bar | After Effects' menus, order, submenus and labels; native on macOS; keyboard-operable in-window bar | 95% | 587 entries in `crates/engine/src/menus.rs`; Adobe-service entries omitted by design; `ui_menus` tests (#279) |
| Panels and workspaces | Every After Effects panel; all standard workspaces; drag-to-dock, tabs, floating panels, maximise | 75% | `ui_tabs`, `ui_panels`; panels move into their own native windows on any screen (#486 open: no dragging tabs between those windows); #302, #301 and #320 (docking, stacked-panel headers, workspace persistence) are closed |
| Timeline | Switches, modes, parent & link, twirl-downs, reveal shortcuts (U, UU, P, S, R, T, A, E, M, F, Alt+Shift…), pick whips, graph editor, work area, markers | 75% | `ui_keyframes`, `ui_timeline_*`; expand precomps in place (#601); #456, #457, #569 and #355 (Graph Editor jitter and buttons, negative rotation, bulk keyframing) are closed; Proportional Scrubbing (26.2: Ctrl+Alt / Cmd+Opt scrub of hot text spreads the change over the selected layers by selection order, #770) matched for layers selected as a whole, not yet for individually selected properties; every layer has the Video switch, nulls, cameras and lights included (a null with its eye off has no box or handles in the viewer and isn't picked there) |
| Timeline | Switches, modes, parent & link, twirl-downs, reveal shortcuts (U, UU, P, S, R, T, A, E, M, F, Alt+Shift…), pick whips, graph editor, work area, markers | 75% | `ui_keyframes`, `ui_timeline_*`; expand precomps in place (#601); #456, #457, #569 and #355 (Graph Editor jitter and buttons, negative rotation, bulk keyframing) are closed; Proportional Scrubbing (26.2: Ctrl+Alt / Cmd+Opt scrub of hot text spreads the change over the selected layers by selection order, #770) matched for layers selected as a whole, not yet for individually selected properties; every layer has the Video switch, nulls, cameras and lights included (a null with its eye off has no box or handles in the viewer and isn't picked there); a row control (a switch, the label swatch, a Modes cell) clicked on one of several selected layers acts on the whole selection, with the layers the switch doesn't apply to left out (#1849) |
| Composition viewer | Selection, handles with direction-aware cursors, rulers, guides, grids, snapping, channels, exposure, region of interest, snapshots, 3D views, Spacebar hand | 70% | `ui_viewer`, `ui_viewers`; Cmd/Ctrl +/− doesn't zoom (#570); anchor point grab on Linux (#492); #352 (snapping) is closed; no 3D transform gizmos (#392, #347); percentage guides (26.5) exist as View ▸ Add Percentage Guide and Convert Guides to Percentage / Pixels (a guide stores a percent of the comp, so it follows comp-size changes; behaviour inferred from the release note, not compared with After Effects); Copy Frame to Clipboard (26.3) is in the Composition menu and the viewer's context menu |
| Tools panel | All After Effects tools; long-press flyouts; Tool Creates Shape / Mask; Fill / Stroke options | 80% | #213, #227 fixed; #553 (pen and vertex tools on motion paths) is closed |
| Nudging and modifiers | Arrow nudge (1 px, Shift 10 px), Alt/Option duplicates and slips, Shift constrains | 75% | #290 nudging fixed; #491 (Linux multi-layer edits) is closed |
+3 -3
View File
@@ -462,19 +462,19 @@ every request and reply, a render through an in-process offload; `tests_roto.rs`
propagation through an offload streaming segmentations; `tests_mask_warp.rs`: Warp Stabilizer
plans solved in the job, never by `warp.status` on the page), the frame-worker protocol
(`crates/engine/src/remote.rs`: diff / patch, a replica following edits renders the same pixels;
`crates/ui-egui/tests/ui_web_offload.rs`: the frame cache through a remote renderer, `wait: true`
`crates/ui-egui/tests/it/ui_web_offload.rs`: the frame cache through a remote renderer, `wait: true`
deferred until the offloaded job ends) and the Media Browser's virtual tree (`media_browser.rs`,
`tests_panels.rs`). M13.24: deferred readbacks on a real device (`crates/gpu/src/tests_deferred.rs`:
whole-frame GPU and CPU-composited frames in passes match the CPU, placeholders never reach the
layer cache; `deferred.rs`: keys, late readbacks of an older frame dropped), the frame server's
passes and Auto timing (`remote.rs`, a deferred stand-in accelerator), the browser's routing and
disk cache (`crates/ui-egui/tests/ui_web_gpu_storage.rs`: a GPU frame worker renders effect frames,
disk cache (`crates/ui-egui/tests/it/ui_web_gpu_storage.rs`: a GPU frame worker renders effect frames,
the page's GPU keeps frames without effects, frames stored under their disk keys come back after a
"reload" without rendering, the blue cache bar sees them; the storage manager's widgets and
commands), the disk index (`disk_cache.rs`), the store's usage by kind and clearing (`store.rs`),
`storage.*` (`storage.rs`), and every WGSL float literal fitting f32 (browsers reject the whole
module otherwise; `tests.rs`). M13.30: job workers on a deferred device
(`crates/ui-egui/tests/ui_web_job_gpu.rs`: a Render Queue job and a Warp Stabilizer analysis
(`crates/ui-egui/tests/it/ui_web_job_gpu.rs`: a Render Queue job and a Warp Stabilizer analysis
render their frames in passes on the device, with the CPU worker's pixels / result),
particles, Advanced 3D and the job pass driver in passes (`crates/gpu/src/tests_deferred_jobs.rs`),
layer buffers through the disk store and the prefetch plan (`remote.rs`