Commit Graph
543 Commits
Author SHA1 Message Date
BFlat a3b62822be Merge pull request #1331 from onlymoein/codex/fix-1303-benchmark-evidence
Reject corrupt benchmark results and incomplete regression evidence
2026-10-16 18:13:45 +07:00
BFlat 5db68bf34a Merge pull request #1302 from vbasky/fix/1194-liquify-offset
Liquify: expose Distortion Mesh Offset in Effect Controls (#1194)
2026-10-16 18:10:30 +07:00
BFlat eac13d1cf1 Merge pull request #948 from Themolx/solo-outside-active-range
Solo: exclude other layers even when the soloed layer is outside its time range
2026-10-16 18:10:06 +07:00
bflatasticandClaude Opus 5.5 bafc7e620d Docs: parity docs list Composition - Retain Layer Sizes for PDF / Illustrator (#1536)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:05:49 +07:00
BFlat f3148ee0b1 Merge pull request #1399 from arnav-hiwarkar/feat/media-browser-copy-source-path
feat(media-browser): add Copy Source Path
2026-10-16 17:03:16 +07:00
BFlat 73d483812f Merge pull request #1402 from arnav-hiwarkar/fix/presets-menu-automation-followup
fix(presets): identify copy folder action by label
2026-10-16 17:02:54 +07:00
skylar taylor-barrickandCodex c2f790b1d9 refactor(pdf): share structure parsing through a bounded adapter
Load PDF document objects through the pinned craft-pdf parser and convert them into EffectCraft's existing drawing model with bounded traversal, recovery and retained data. Preserve generation numbers, stream limits, encrypted-document refusal and reported repairs.

Retain app-owned drawing, EPS, fonts and content/image decoding. Assert early excessive-nesting rejection without partial art, and cover tolerant arrays on native and WASM.

Validated with the22-stage local matrix and exact-head FreeBSD, Windows ARM64 and packaging checks.

Co-authored-by: Codex <noreply@openai.com>
2026-10-15 16:35:49 -06:00
Moein Saharkhiz 0311bdc34d fix(automation): avoid replaying edits after lost replies
Retry only explicitly read-only control queries after connection failures. Report ambiguous edit outcomes without resending mutations, reconnect on the next explicit call, and reject request-ID exhaustion without overflow.

Add loopback regressions for lost and malformed replies, read-only retries, playback queries versus edits, and unknown methods.

Fixes #1247
2026-10-15 02:13:41 -06:00
arnav-hiwarkar bed289e2a1 fix(presets): identify copy folder action by label
Follow up on #1210: remove the fixed menu index from automation and click handling, and move the preset-folder documentation into the Effects & Presets section.
2026-10-14 12:09:48 +05:30
arnav-hiwarkar 8041329df8 feat(media-browser): add Copy Source Path 2026-10-14 11:42:13 +05:30
ThemolxandClaude Opus 5.5 03b7a958e5 Solo: exclude other layers even when the soloed layer is outside its time range
In After Effects solo is not time-dependent: while any AV layer is soloed,
non-soloed layers are excluded at every time. The renderer, nested/collapsed
3D paths, engine viewer helpers and viewer hit tests only counted solo layers
active at the current time, so outside the soloed layer's in-out range the
whole comp reappeared. Drop the time condition (audio already ignored it).

Update the #66 viewer regression test to the AE behaviour and add a render
test for it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:30:26 +02:00
Moein Saharkhiz e30c093654 #1303: reject corrupt and incomplete benchmark evidence 2026-10-13 14:13:54 -04:00
Vikram Bhaskaran d15c82b163 Liquify: expose Distortion Mesh Offset in Effect Controls (#1194)
After Effects' Liquify shows Distortion ▸ Offset (x, y), and the renderer
already applied distortionMeshOffset — sampling the mesh at layer
coordinates minus the offset — but the parameter was declared hidden, so
users could neither see nor edit it, and #1194 read as 'the effect does
not work and the Offset option is missing'.

It is now a visible 2D Point control (still defaulting to 0,0, still
scriptable by its old path). Regression test: the spec exposes it as a
Point, a [20,0] offset moves the displaced-region centroid right by the
offset (the render differs, and the left of the shifted mesh is back to
untouched pixels), docs/effects.md refreshed via UPDATE_DOCS.
2026-10-14 02:46:26 +11:00
Brandon Thomas 7a9213611e Merge pull request #1106 from eliasx45/upstream/relink-moved-footage
# Conflicts:
#	docs/footage.md
2026-10-13 05:34:14 -04:00
Brandon ThomasandClaude Opus 5.5 c5bb5f4397 docs: move #1104's project import notes from a stray parity-log.md into footage.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 04:35:32 -04:00
Brandon Thomas acb77a8c85 Merge pull request #1210 from arnav-hiwarkar/feat/copy-presets-folder-path 2026-10-13 04:35:21 -04:00
Brandon Thomas 66c08de572 Merge pull request #1039 from moecr7/codex/fix-989-effect-paste-timing
# Conflicts:
#	contributors/people.toml
#	docs/gaps.md
2026-10-13 04:35:19 -04:00
Jannik WapplerandClaude Opus 5.5 1765dc53df Tint: Swap Colors (#963) (#1060)
Squash of #1060 by @RavoxX, without the docs/images screenshots (kept out of the repo).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 04:33:43 -04:00
Brandon Thomas 32792ff172 Merge pull request #1199 from cjcwwww/i18n/effect-names
# Conflicts:
#	crates/ui-egui/src/panels/timeline.rs
#	docs/gaps.md
#	docs/localization-parity.md
2026-10-13 04:33:20 -04:00
Brandon Thomas 430c968e52 Merge pull request #933 from Themolx/replace-with-precomp
# Conflicts:
#	crates/engine/src/tests_project_items.rs
2026-10-13 04:31:42 -04:00
Brandon Thomas 4574fb62bc Merge pull request #792 from vangel76/gap-object-matte
# Conflicts:
#	crates/ui-egui/src/i18n/ui.rs
#	docs/gaps.md
#	docs/target-app-parity.md
2026-10-13 04:30:49 -04:00
Brandon Thomas 287c35dae7 Merge pull request #1109 from eliasx45/upstream/azerty-graph-zoom
# Conflicts:
#	crates/engine/src/commands/time.rs
#	crates/ui-egui/src/panels/timeline.rs
2026-10-13 04:29:47 -04:00
Brandon Thomas 6e47aa3f00 Merge pull request #1176 from tylerjenningsw/fix/report-workspace-save-errors 2026-10-13 04:29:16 -04:00
Brandon Thomas c720a1d30b Merge pull request #1005 from Nael-Nathanael/fix/desktop-args-997
# Conflicts:
#	contributors/people.toml
2026-10-13 04:29:10 -04:00
Brandon Thomas 3aac824976 Merge pull request #1175 from storybored379/fix/roto-trim-span
# Conflicts:
#	ROADMAP.md
2026-10-13 04:29:08 -04:00
Brandon Thomas a985dfb36b Merge pull request #1098 from vangel76/feat-gap21-percent-guides-effect-labels
# Conflicts:
#	crates/engine/src/tests_menu_cmds.rs
#	docs/effects-parity.md
#	docs/gaps.md
#	docs/ui-parity.md
2026-10-13 04:29:06 -04:00
Brandon Thomas 37b681ac12 Merge pull request #1104 from eliasx45/upstream/import-project 2026-10-13 04:28:59 -04:00
Brandon Thomas bd74443238 Merge pull request #1110 from eliasx45/upstream/render-bench 2026-10-13 04:28:58 -04:00
Brandon Thomas 1d8fe7a8a0 Merge pull request #1158 from nanox333/fix/551-shift-space-every-frame
# Conflicts:
#	docs/ui-parity.md
2026-10-13 04:28:55 -04:00
Brandon Thomas f0fa92ceef Merge pull request #1146 from redonion23/fix/1078-reset-keeps-keyframes 2026-10-13 04:28:54 -04:00
Brandon Thomas 4f57d5d73d Merge pull request #1144 from tylerjenningsw/enhance/quick-offset
# Conflicts:
#	crates/ui-egui/src/i18n/ui.rs
2026-10-13 04:28:43 -04:00
Brandon Thomas 7da7358504 Merge pull request #1102 from vangel76/feat-gap7-presets-backgrounds
# Conflicts:
#	crates/ui-egui/tests/ui_panels.rs
#	docs/gaps.md
#	docs/target-app-parity.md
2026-10-13 04:28:30 -04:00
Brandon Thomas 39ef24af3a Merge pull request #1093 from moecr7/codex/fix-1063-text-line-breaks 2026-10-13 04:28:28 -04:00
Brandon Thomas 0e424b45f1 Merge pull request #1050 from pravdomil/claude/bind-existing-shortcuts 2026-10-13 04:28:25 -04:00
Brandon Thomas 3484f91c3f Merge pull request #1009 from marcoarnulfo/fix/portable-mode 2026-10-13 04:28:22 -04:00
Brandon Thomas ad83f9ae1a Merge pull request #1114 from vangel76/docs-gaps-audit-2026-10-12
# Conflicts:
#	docs/ui-parity.md
2026-10-13 04:28:22 -04:00
arnav-hiwarkar c7692aa697 #971: copy the presets folder path in Effects & Presets 2026-10-13 13:27:09 +05:30
WaWu e655159382 i18n: the effect catalog takes a language's tables, with Japanese's slot reserved (#821)
The Japanese data point in #821 (zitann2020) offered to write its rows against whatever mechanism
this PR lands, so both languages share one catalog instead of inventing two. This makes adding a
language a data change and reserves `ja`:

- `Catalog` holds a language's effect rows and its category labels, and `catalog()` resolves a
  language code to one; adding a language is two tables and one arm, with no change to the lookups
  or to any panel.
- `JAPANESE_EFFECTS` and `JAPANESE_CATEGORIES` are declared, keyed by the same effect ids and by
  the registry's English category names, and `ja` resolves to them. Both are empty, so a Japanese
  interface draws exactly what it drew before — the slot changes no behaviour on its own.
- `a_pending_language_only_uses_known_ids` guards the pending tables (Japanese and Traditional
  Chinese) as rows arrive: an id Simplified Chinese does not know, a different English name for one
  of them, an empty translation or a repeated id fails. `languages_without_rows_draw_the_registry_name`
  asserts each pending language has an arm in `catalog()` (a table with no arm would leave a
  translator's rows dead) and is still row-less, so the day one gets rows the test says where its
  coverage moved.
- `only_the_brand_names_stay_in_english` now documents that it pins *Simplified Chinese's* five
  brand names and is deliberately not shared: AE's Japanese interface keeps the whole `CC`, `VR`
  and `OCIO` sets in English while its Chinese one translates them, so repeating the English name
  is a language's choice and not an unfinished row. The row check reflects that (a repeated English
  name is accepted, an empty one is not).

docs/localization-parity.md records the two empty tables and that each language decides for itself
which names stay in English.

Refs #821
2026-10-13 14:13:28 +08:00
WaWu 0aa2ea5e12 i18n: an effect's name draws in the interface language, the generated Effect menu included (#821)
The interface below the menu bar is localized (618 fixed menu entries, ~490 panel rows) but an
effect's name still rendered in English everywhere it appeared: the generated Effect menu, Effect
Controls, the Timeline and Effects & Presets.

The registry's English name is the effect's identity: `effect.list`, `effect.apply {"effect": …}`,
scripts, expressions and the property tree's group name all match on it. Only the drawing changes.

`crates/ui-egui/src/i18n/effects.rs` keys the names by effect **id** rather than by the English
string — a repeat is stored as `Gaussian Blur 2` (an English key would miss it) and upstream
renames a display name now and then, while the id is stable. It carries 306 rows for Simplified
Chinese, one per effect in the registry, taken from the installed After Effects 2026 (26.5.0.89)
Simplified Chinese interface, with the `CC` series following Adobe's Chinese documentation (which
names 68 of the 69 that its interface leaves in English). `Cryptomatte`, `EXtractoR`, `IDentifier`,
`Key Light` and `Unmult` stay in English as brand names; `Face Measurements` and `Face Track
Points` are EffectCraft's own effects. The 21 category folder names are in the same file, worded
after the effect names (channel → 通道, noise → 杂色, matte → 遮罩 …).

What draws the catalog now:

- **Effect menu:** the entries and the category submenus. The command and its `{"effect": <id>}`
  params are untouched, so the menu still applies by id.
- **Effect Controls:** the header, its Rename field, the accessible name and the About popup.
- **Timeline:** effect group rows, and the search (a Chinese interface is searchable in Chinese).
- **Effects & Presets:** the rows, the drag ghost, the folder rows and the search.

Kept as they are: the effect id, the property tree's `PropGroup.name`, every automation id and
label, `effect.list`'s `name`/`category`, and the undo label (`Apply Gaussian Blur`). A name the
user typed in Effect Controls stays verbatim, and a repeated instance keeps the index the engine
appends (`Gaussian Blur 2` → `高斯模糊 2`). No other language has rows yet, Traditional Chinese
included, so those draw the registry's English name.

Tests: nine unit tests under `cargo test -p effectcraft-ui-egui --lib i18n` cover the data (every
effect has a row, the row still carries the registry's English name, ids are unique, only the five
brand names repeat their English name, every category has a row, a row names an effect the registry
knows) and the behaviour (the instance index, user renames, English and untranslated languages,
search) plus a scan pinning the drawing sites. `crates/ui-egui/tests/ui_effect_names.rs` checks the
Effect Controls header, the generated Effect menu and that the ids, automation labels and
`effect.list` stay English.

`docs/localization-parity.md` and `docs/gaps.md` no longer record effect names as deliberately
English; effect *parameter* names are still untranslated and stay the next piece.

Refs #821
2026-10-13 13:39:16 +08:00
tylerjenningsw ecf485e375 Docs: engine.execute reports a failed workspace save through workspaceStorageError (#696) 2026-10-12 21:35:48 -04:00
tylerjenningsw dbaf559b58 Docs: workspace commands report a save that didn't reach disk (#696) 2026-10-12 21:32:24 -04:00
Kristian MyramandClaude Haiku 5.5 a26f1a3749 #551: drop the Shift+Space default from the preview parity gaps
Shift+Spacebar now plays every frame by default, so it is no longer a gap in docs/ui-parity.md.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-13 01:46:34 +02:00
redonion23andClaude Opus 5.5 a69c7d7cd2 Timeline: Reset keeps an animated property's keyframes and keys the default (#1078)
prop.reset cleared every keyframe before setting the default value. As in
After Effects (and as effect.reset already does for effect parameters), an
animated property now keeps its keyframes and gets the default as a key at
the current time; a static property just takes the default. The expression
is still removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:52:44 +02:00
storybored379andOpenAI Codex 5d9bab268d M6.7: reject Roto Brush span edits past trimmed strokes
Validate saved stroke frames against the current layer limits before clamping a span edit. Keep project and undo state intact when trimming has left strokes outside the layer.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
2026-10-12 14:40:10 -07:00
tylerjenningsw 94b4d0ca34 Timeline: Quick Offset layers and keyframes in selection order (#1012)
Ctrl/Cmd+Alt dragging a selected layer bar or a selected key now runs a
Quick Offset (layer.quickOffset / keys.quickOffset with fromStart, one
undo step). The mode is chosen when the drag starts and needs at least
two unlocked layers; the last selected layer moves by whole frames with
the pointer. A readout by the pointer shows the Total Offset and the
offset Per Layer, translated.

A plain drag still moves the selection together, Alt alone still scales
a key group in time (it now leaves Ctrl/Cmd+Alt to Quick Offset), and
Ctrl/Cmd+Alt+click still toggles Hold. The key drag's readout is drawn
by a shared drag_tip. Keys also register timeline.keyAt.<uid>.<ticks>,
exact where keys on subframes can share a frame.

Tests (ui_quick_offset): staggering layer bars in selection order and
keys per layer, one undo each; plain drags and Alt scaling unchanged; the
readout while dragging.
2026-10-12 17:37:34 -04:00
tylerjenningsw 28e9e5229e Quick Offset: layer.quickOffset and keys.quickOffset commands (#1012)
After Effects 25.4's Quick Offset staggers selected layers, or each
layer's selected keyframes, in the order they were selected: the first
stays, the last moves by the drag and the ones between by equal steps,
landing on subframes.

layer.quickOffset {delta, layers?} moves each layer's start, in and out
point by total * i / (n - 1), worked out once in ticks with integer
arithmetic, so 1 frame over 4 layers gives 0, 1/3, 2/3 and 1 frame
exactly. keys.quickOffset {delta} does the same per layer for the
selected keys, the layers in the order their first key was selected;
every selected key of a layer, across its properties, moves by that
layer's comp-time offset through its start and stretch (reversed too),
keeping values, interpolation, easing and labels. Locked layers are
skipped and at least two layers are needed. With merge and fromStart,
delta is the whole drag and each step starts again from before it, so
the drag is one undo step and a key passed over survives. A delta or a
destination out of the range of times is an error, not a clamped move.

Docs: agents.md; architecture.md notes Quick Offset as the exception to
times snapping to frames.
2026-10-12 17:37:31 -04:00
vangel76andClaude Sonnet 5.5 19e4fc7c60 docs: re-audit gaps.md and parity docs against main (2026-10-12)
Open-issue count, crash list, closed-issue references, localization
catalog counts, export formats and #include status checked against
upstream/main 470ea7a3. Rows 7, 14 and 21 of gaps.md untouched (pending
in PRs #1102, #792, #1098).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:36:26 +02:00
vangel76andClaude Sonnet 5.5 51371939ad Gap 7: Backgrounds animation presets (#1096)
Problem: the built-in animation preset library had no Backgrounds category
(gap 7: 31 presets against After Effects' 621).

Fix: 23 original Backgrounds presets in crates/engine/presets/backgrounds.json,
built from our own generator, noise, colour and stylize effects: Soft Gradient
Drift, Aurora Veil, Slow Fog, Cloud Bank, Dark Smoke, Ember Haze, Magma Flow,
Ice Flow, Pastel Plasma, Cell Drift, Crystal Facets, Hex Mosaic, Mirrored Silk,
Water Caustics, Blueprint Grid, Checker Scroll, Scrolling Stripes, Pulse Rings,
Bokeh Drift, Spotlight Floor, Dawn Sky, Sweeping Light, Grainy Wash.

The preset format gains `expr` (an expression per property, so backgrounds keep
moving for the whole layer) and point parameters written as fractions of the
layer size. Effects & Presets lists them under * Animation Presets > Backgrounds.
Tests: catalogue uniqueness and categories, apply/undo/redo of every preset
(engine), render of every preset with the expression engine: finite,
non-flat, deterministic, moving (host), panel listing and apply (ui-egui).
Sidecar, ATTRIBUTION.md, gaps.md row 7 and effects-parity.md updated.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:13:05 +02:00
vangel76andClaude Sonnet 5.5 f11792827e Gap 21: percentage guides and effect colour labels (#1095)
Guides can store a percent of the comp so they follow comp-size changes
(View > Add Percentage Guide, Convert Guides to Percentage / Pixels); an
effect instance has an optional colour label (effect.setLabel, Effect Controls
header bar and Label menu). Both are serde-defaulted, so old projects load.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:07:36 +02:00
Moein Saharkhiz a27f9f54b9 #1063: render carriage-return text as separate paragraphs 2026-10-12 14:47:58 -04:00