The batch merges grew Japanese 410 → 693, both Chinese catalogs 506 → 695,
Ukrainian 505 → 524, Czech 501 → 518 and Spanish 513 rows (its #996 landed)
without touching the doc's counts or shares; the overall figure was still the
10-October measurement. pt-br was the last count to update, so the row now
mirrors the code at this tree.
278 new rows (417 → 695), the Chinese catalogs' source list, keyed by the English
source string: panels, dialogs, tooltips and the Settings pages stop falling back
to English for every string the zh-hans catalog covers, including the six keys
the batch merges added on top. Terminology follows After Effects' Brazilian
Portuguese conventions; brand names stay English.
AI-assisted translation (OpenCode agents, GLM); not yet native-speaker proofread.
Layer > Create > Create 3D Layer Instance, as After Effects (public docs):
3D model layers take no masks or effects, so the command puts a comp-sized
solid at the top of the layer stack with CC Composite referencing the
selected model, and switches the model off (back on to keep its shadow) -
a 2D copy of its render, through the comp's camera, that 2D effects can be
applied to.
- CC Composite (ec.channel.cccomposite) gains an optional Layer parameter:
with a layer chosen it takes the original's place; In Front replaces the
solid's pixels, alpha included, the other Composite Original modes blend
with them. The GPU compositor runs such an instance on the CPU.
- FxHost serves a referenced model or primitive layer as After Effects
does - the layer rendered on its own through the comp's camera
(Renderer::solo_3d); the owner keeps no cache entry for it (it moves with
the camera and lights, without a trace in its own properties).
- layer.create {op: instance3d} skips layers that are not 3D model or
primitive layers (the ones that take no effects); one undo step, the copy
selected, the model's video off.
Tests: tests_instance3d.rs (behaviour, pixels, undo/redo, serde, 2D effects
on the copy), a CC Composite layer-parameter unit test; docs/effects.md
regenerated (3033 parameters).
- Default's right column is a short Preview frame (fixed 76 pt: tab strip and a 46 pt body)
over a Properties frame with Align, Audio and Effects & Presets as tabs. Essential Graphics'
right column is one Properties / Effects & Presets frame. No built-in workspace uses
accordions, so a frame there takes tabs and Maximize acts on one frame.
- Workspace files of version 1: a column of stacked frames becomes tab groups split top to
bottom. Each open frame keeps all its tabs and its height as a fixed size; a closed frame's
tabs join the open frame above it.
- Version 1 stored a native panel window's outer position; craft-ui places windows by their
content. The migrated rect moves by the main window's frame offset once the main window
reports it, and workspaces are not saved before.
craft-ui's native-windows feature is on for every non-wasm build. Keys and
dropped files from a floating window reach the main window's next frame, and
while a modal dialog is open the dock area blocks input in floating windows.
Move Panel to Main Window docks the panel again. The web, Wayland and embedded
viewports keep floating windows in the main window.
Edit ▸ Keyboard Shortcuts now lists the scripts File ▸ Scripts lists, under
File ▸ Scripts, and a key given to one runs it as its menu entry does. The
key is bound to the script's file name (file.runScript {"name": ...}) and is
saved with the preset. File ▸ Scripts and the macOS menu show it.
The shortcut table lists the Scripts folder again when a script is installed
or uninstalled, when the editor opens and when shortcuts.list runs.
shortcuts.set and shortcuts.reset look a script up in File ▸ Scripts' list
as it is now, and a script it doesn't list is an error instead of a key for
Run Script File....
Every craft-libs crate and the hayro-syntax and hayro-jbig2 patches are
pinned to storytold/craft-libs 2869b8cc. The workspace is a craft-ui
Workspace<PanelKind>: craft-ui draws the frames, tab strips, stacked
panels, floating windows and drop previews and owns the gestures.
EffectCraft keeps PanelKind, its built-in workspaces, the panel bodies,
the Timeline's comp tabs, viewer locks and the panel menu in each group
header, and the rule that no move or float empties the docked area.
window.dockAction applies craft-ui Actions; craft-ui's window.panel.*
commands, ui.dock and ui.dock.reset parse as DockCommand. Saved
workspaces are version 2 snapshots of craft-ui Workspaces; an earlier
file loads as the default layout and is left untouched.
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.
The footage page said the 10 Bit White Point becomes the Converted White
Point. That holds with Highlight Rolloff at 0; at the default 20 the top of
the converted range is bent into a curve, as in the Cineon Converter effect,
and the white point converts to a lower level.
Unfiltered, list_commands returns ~134 KB and list_effects ~480 KB, more
than MCP clients accept in one tool result. With `compact: true`,
list_commands (and its command_list alias) returns only each command's
id and label, and list_effects only each effect's id, name and category
(~40 KB and ~23 KB). Default output is unchanged; filter and
enabled_only still apply.
DPX and Cineon footage showed its log code values as stored, with no
way to convert them. Interpret Footage now has the Cineon Settings that
After Effects' help page describes: Logarithmic Conversion, the
Converted Black and White Points, the 10 Bit Black and White Points,
Current Gamma, Highlight Rolloff and Units. With Logarithmic
Conversion on, the code values of each decoded frame are converted
from printing density to the Current Gamma between the converted
points, before Separate Fields, Frame Blending, Interpret As Linear
Light and the working space use them. With it off (the default), the
values stay as stored.
file.interpretFootage and file.interpretProxy take the settings as
parameters and report them. They return an error for out-of-range
values, and for Cineon parameters when none of the items is a DPX or
Cineon file. Apply Interpretation copies the settings between DPX and
Cineon files.
A subfolder of a Scripts folder can be a link to another folder (an extension's own checkout).
`file.uninstallScript {"name": "Motion Kit/Animate.jsx"}` then deleted Animate.jsx in that
folder, outside the settings folder. Uninstall now refuses `Folder/File.jsx` names and removes
only scripts at the top of the Scripts folders, where Install puts them; listing and running
through a linked folder still work.
Regression test: uninstall_never_deletes_through_a_linked_subfolder (failed before the fix).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
File ▸ Scripts gets a Recent Script Files submenu with the ten scripts run
last, newest first: script files run with Run Script File… or a command, and
the installed and bundled scripts of File ▸ Scripts. ScriptUI panels are not
listed. The list is kept in the settings. Each entry runs its script again
through `file.runScript {"recent": i}`, and Cmd+Alt+Shift+D runs the most
recent one; the key can be changed in Edit ▸ Keyboard Shortcuts. An entry
records whether it ran a file or an installed script, so a file named like a
bundled script runs again as that file.
An extension that ships several panels no longer adds one Window menu entry per panel:
`Scripts/ScriptUI Panels/Motion Kit/Animate.jsx` shows as Window > Motion Kit > Animate.jsx,
and a subfolder of `Scripts/` is a submenu of File > Scripts. Top-level scripts are unchanged.
- Script names may be `Folder/File.jsx`: exactly one folder, each part a bare name (no `..`,
`\`, NUL or empty part), never `ScriptUI Panels/...` under `Scripts/`.
- window.scriptPanel, file.runScript, file.uninstallScript, file.scripts.list and
scriptui_panels.json take such names; a panel's tab is titled after its file.
- ConfigStore::list_dirs (DirConfig, MemoryConfig) lists the subfolders.
- menus::dynamic_nodes groups a folder's entries into a MenuNode::Submenu; the egui and native
menus draw it with their submenu code.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Scripts in Scripts/Startup and Scripts/Shutdown in the settings folder
were never run. The desktop and web apps now run the Startup scripts at
launch, before a project opens, and the desktop app runs the Shutdown
scripts as it quits, after the project is closed. Each folder runs in
alphabetical order with case ignored, and files larger than 16 MiB are
not run. A Startup script that fails is reported in a toast and in the
log, a Shutdown script that fails is reported in the log, and the next
one still runs.
A Startup script that waits in a modal dialog goes on when the dialog
closes, while the next scripts run. A Shutdown script's dialogs close
as if canceled. With the settings folder on disk, each script runs as
its file, so #include, $.fileName and $.evalFile resolve against the
script's own folder.
The new commands file.runStartupScripts and file.runShutdownScripts
return the scripts that ran, those still waiting in a dialog, and those
that failed. Like script.run, both are refused in confined automation
sessions, in batches and in script steps, which now read one list of
script commands (RUNS_SCRIPTS). The list also holds window.scriptPanel
and window.restoreScriptPanels, which run ScriptUI panel scripts and
were not refused on main either. The apps still call
window.restoreScriptPanels at launch. plugins.md, scripting-parity.md,
gaps.md, target-app-parity.md and agents.md describe the folders. Each script
still runs in its own global scope, so a Startup script's variables are
not available to later scripts.
* Translations: delete coverage and wording tests
A missing translation shows in English and never fails a test. Delete the
coverage and per-language parity tests, the tests that pin one language's
wording and the source scans for strings not routed through the catalog.
Keep the stale-row, duplicate-row and placeholder checks, and make the
engine tests that switch language compare against the catalog instead of a
literal. Drop the Traditional Chinese panel rows that only repeated the
English source to satisfy the parity test.
* Translations: missing-strings report in xtask ci
missing_translations_report prints, per language, the fixed menu entries,
panel strings, effect names and effect categories with no row. It always
passes. cargo xtask ci runs it with --nocapture after the test runs, so the
list shows in the gate log. The docs say a missing string shows in English
and where the list is.
* Dev profile: line tables only for workspace crates, no debug info for dependencies
* xtask ci: dev-profile gate, nextest, tests without examples, wasm --keep-going
* One integration-test binary per crate
* xtask ci: run effectcraft-gpu's shared-device tests in one cargo test process
* xtask ci: run every stage and report all failures
* xtask ci: name the stage type (clippy type_complexity)
* xtask ci: run every test pass and report all failures
* cargo fmt
Reload Footage probed every item the way File ▸ Import does by default,
so a still such as Photo_2.jpg with Photo_1.jpg beside it was grouped
into a run and measured from the run's first file. The still took
Photo_1's size. Sequence items still probe as a run; everything else
reads its one file.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Review follow-up to the panel/dialog step: the composition-settings tabs
translate "Basic" and "Advanced" through `tr(variable)` and the Preview
transport translates "Play/Stop", but none of the three had a catalog
row, so they stayed English. Add them to the Japanese, Simplified and
Traditional Chinese catalogs and pin them in
`japanese_rows_translate_the_panels`.
The shared "Type" key means "kind" in the Project column and the Camera
Settings dialog, so the Chinese rows read 类型/類型 instead of 文字
("text").
Keep the graph button bar's automation labels English: translate only
the drawn label and tooltip, and translate the stored English strings
when the hidden-button menu draws them.
Recount the docs from the catalogs: 628 menu rows, 996 Japanese and 998
Chinese panel rows; count Simplified Chinese's 306 effect names in its
numerator (46%) and average the ten After Effects languages the table
actually names (21%, not the stale 27%). Update the measurement basis,
the cross-references in gaps.md and target-app-parity.md, and ROADMAP.
The panel catalog behind the menu bar translated the dialogs and
Preferences, but much of the work area was still English: panel tabs, form
fields, panel context menus, the tracker and graph controls, text-panel
options, the File panel's footers and the credits. Add 300 rows to the
Japanese catalog — and the matching Simplified and Traditional Chinese
sources the tests keep it in step with (the other languages may lag, an
untranslated row falls back to English):
- panel tabs (dock.rs / dock_ui.rs titles), the Project panel's columns,
footer tooltips and column menu;
- form and dialog labels and choice options (the forms the panels open —
import, interpret footage, render queue, trackers, text animators…);
- panel context menus (timeline layer/property menus, graph editor);
- the tracker, graph editor, text-panel, animator and Content-Aware Fill
labels;
- the Preview panel's transport tooltips, credits table headers and sort
options, the composition-settings tabs and the About links;
- the engine's text-animator menu labels, added as a data source like the
settings pages (they are interface text the panels draw).
Strings are wrapped where they are drawn with the existing `tr`/`tr_args`
mechanism (the label helpers already ask the catalog, so the data tables
need no new ids); the catalog tests keep the three complete languages
listing the same sources, reject duplicate or empty rows and keep the
placeholder counts. A new test assertion in
`japanese_rows_translate_the_panels` pins a sample of this step.
The panel catalogs are now 993 Japanese and 995 Chinese rows (the two
Chinese catalogs are the complete source list); with the 628-row menu
catalogs Japanese is 1,621 of ≈ 4,200 interface strings (39%, up from 27%).
Still English: effect parameter names (≈ 1,650 registry names, drawn from
the model, not the catalogs), Home-screen literals, tooltips drawn from
engine data, engine error messages, and the rows other languages lack.
Docs: localization-parity (header, per-language table, overall share,
revision history), ROADMAP (language table, progress log, revision history).
macOS does not install the on-demand PingFang SC (macOS 27 on an English
install ships Hiragino Sans GB, Heiti SC, Songti SC and STSong instead),
and the Simplified Chinese fallback list named only Windows and Linux
families. A Chinese character therefore fell through to the exhaustive
search, which picks the first installed face that covers it — Hiragino
Sans, the Japanese face — so Chinese text in a composition was drawn
with Japanese glyph forms (#453). Japanese kana and kanji were already
handled, and a Chinese-only character the Japanese face lacks (e.g.
页) still found a Chinese face, which is why the symptom looked
selective.
Add the macOS Chinese faces to the fallback lists: Hiragino Sans GB,
Heiti SC, Songti SC and STSong for Simplified Chinese, Songti TC for
Traditional (Heiti TC was already named). The interface language still
chooses between the scripts and an English interface keeps the
Japanese-first order for shared Han ideographs, as designed in #312;
what changes is that a Chinese-locale request has an installed Chinese
family to answer it on macOS.
Tests: a text-layer render test draws Japanese and Chinese text and
checks glyph coverage (skipped where no CJK face is installed); a layout
test checks every CJK glyph comes from a face that has the character, so
a missing-glyph box cannot creep back; and the fonts test fails without
the list change ("Hiragino Sans GB missing from the Han list"), passes
with it, and walks the Han branch's list to prove the first installed
Simplified family is a Chinese face, not a Japanese one.
Verified with CARGO_BUILD_JOBS=2 RUST_TEST_THREADS=2:
effectcraft-text 64 passed; effectcraft-render 233 passed, 1 ignored;
cargo clippy -p effectcraft-text -p effectcraft-render --all-targets --
-D warnings clean; cargo fmt --all -- --check clean. A 900x240 render of
"骨直真具画 中文测试" with the zh-hans request now uses Hiragino Sans GB
and differs from the Japanese render, which still uses Hiragino Sans.