Reconcile main 991904888a and preserve the reviewed lifecycle, IME, rendering and lockfile changes.
Formatting, strict lint, layers, assets and WASM passed. Full CI retained 3,961 passes, 14 baseline-matching GPU failures and 31 ignored executions. The local review commit has explicit approval to retain these documented failures; native/browser acceptance and paired app performance remain open.
As in After Effects, the Preset menu in Composition Settings / New Composition gets a Save
button (asks for the name in a Choose Name window; an existing name of yours is replaced) and a
Delete button for the selected preset of yours. Your presets keep frame size, pixel aspect and
frame rate, are listed above the built-in ones and live in the settings (`compPresets`), so they
survive restarts and Reset All. Commands: `comp.savePreset`, `comp.deletePreset`, `comp.presets`.
A hand-edited settings file loses only its invalid presets.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The second pass over the interface below the menu bar: the strings that are technical terms or
proper nouns - `Mercury GPU Acceleration (…)`, `8/16/32 bits per channel`, `OCIO (built-in ACES
config)`, `sRGB IEC61966-2.1 (default)`, `Import Photoshop File`, `Current Settings`, the viewer's
channel and Fast Previews items. Each wording was checked against the installed After Effects
26.5.0 Simplified Chinese, the way the menu bar was in #353. Terms Adobe keeps in English
(`Display P3`, `HDTV (Rec. 709)`, `RGB`, `Alpha`, `H.264`, `ProRes`) need no row: a missing row
falls back to the English source, which is the decision.
The text reaches the catalog through the funnels that draw it, so one change each covers every
call site:
- `forms.rs`: field labels, notes, choice items and info bodies, plus `dialogs::modal`'s title -
the modal id stays keyed on the untranslated source, so changing the language cannot move it;
- `settings.rs`: page titles, sections, notes, buttons, setting labels and choice items (the page
table itself is engine data and cannot reach the catalog);
- `comp_settings.rs` (3D renderer), `key_dialogs.rs::combo` (Current Settings and the roving
items), `properties.rs` + `timeline.rs` (the text animator menu), `dialogs.rs` (About links);
- `render_queue.rs`: the Opus bitrate goes through `tr_args`, so the value is substituted after
the lookup - worth calling out, because building the string with `format!` and translating the
result looks up the assembled text and silently stays English (the same trap as the project
settings' GPU label, which this commit also fixes).
30 rows join the Simplified catalog. The same keys join the Traditional one with the English
source as their value: the tests require the two lists to match, and the Traditional wording is
the translator's call.
Tests: `CONVERTED` gains the three engine files whose strings the interface draws
(`prefs.rs`, `viewer.rs`, `commands/viewer_cmds.rs`); each holds no drawn literals, so the literal
scan stays green and the new rows have a source to be "used" from. `cargo test -p
effectcraft-ui-egui --lib i18n`: 16 passed.
Render queue settings, templates and progress, the effect and preset panels, Essential Graphics,
precomposing, the tutorials, the credits and the info/scope readouts now go through `crate::i18n`.
Units (`px`, `%`, `mm`, `s`) and the automation ids and labels stay English on purpose: they are
read by scripts and tests, not by people.
Composition Settings ▸ Advanced has both options (they were missing from the model, the
renderer and the dialog):
- Preserve frame rate: nested in another comp, the comp shows only its own frames
(`EvalCtx::nested_time` floors the precomp layer's source time to the nested comp's frame
rate; used for the nested frame, its proxy, aux channels, collapsed transformations and the
viewer's internal wireframes), and the Render Queue renders it at its own rate whatever the
Frame Rate override (`RenderSettings::rate`).
- Preserve resolution: nested in a comp rendered at Half / Third / Quarter, it renders at full
size and the buffer's scale places it.
- `comp.settings {preserveFrameRate, preserveResolution}`, `comp.info` reports them, scripts
read and set `CompItem.preserveNestedFrameRate` / `preserveNestedResolution`, Pre-compose
copies them, and the dialog registers `dialog.comp.preserveFrameRate` /
`dialog.comp.preserveResolution`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Layer ▸ Layer Settings on a solid or adjustment layer opens Solid Settings on the layer's
solid (it ran an empty command before): name (renames the layer and the solid), size, Pixel
Aspect Ratio, colour, and "Affect all layers that use this solid". It starts off, as in After
Effects, so changing a solid other layers share gives this layer its own copy.
`layer.settings {pixelAspect?, affectAll?}` → `{layer, solid?}`; `layer.newSolid {pixelAspect?}`.
- Nulls ask for their name; text and shape layers have no settings (the entry is disabled).
- Composition Settings / New Composition and Solid Settings register an automation id for
every control (`dialog.comp.*`, `dialog.solid.*`). Composition Settings takes any typed frame
rate besides the list, and New Composition starts from the last settings used.
- Colour buttons in both dialogs show the stored sRGB colour (`widgets::srgb_color_button`);
egui's linear picker showed it lighter.
- Docs: agents, parity.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shapes (SHP-2): Stroke Taper (pixels/percent start/end length, width, ease) and
Wave (amount, pixels/cycles, wavelength, phase) rendered as a variable-width
outline; Dash 2/Gap 2/Dash 3/Gap 3 (shape.dashes.add/remove, timeline +/-
buttons); radial gradient Highlight Length/Angle as a focal gradient.
Masks (MSK-1): mask feather points on the Mask Path (mask.featherPoint.*,
Mask Feather tool add/drag), per-point signed radius and tension, rendered
from the signed distance to the path; carried through vertex edits.
Motion blur (LYR-10): Adaptive Sample Limit comp setting; 2D layers take one
sample per pixel of shutter travel between Samples Per Frame and the limit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
engine comp.settings/comp.new: anchor (shifts unparented layers and their
position keys on resize), startTime/startTimecode, renderer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>