FootageItem had no replaceWithSequence, setProxy, setProxyWithSequence or
setProxyToNone, useProxy and proxySource were fixed stubs, and mainSource
was a new object on every read with no conformFrameRate. They now run the
existing commands (file.replaceFootage, file.setProxy, file.useProxy,
file.setProxyNone, file.interpretFootage); the item info reports the proxy
and the conform/native frame rates, and mainSource is one live
FootageSource per FootageItem. replaceSource is not covered: it needs an
engine command that changes a layer's source.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
epaint's has_glyph compares face keys, so a glyph drawn by the replacement
face reads as missing. With no face in the stack covering egui's `◻`, Inter's
`?` becomes the replacement and Inter's `•` fails the check, which happens
once another test (the #1141 one) has loaded a system face without `◻`: the
fallback tries loaded faces first. Compare the drawn glyph with the
replacement glyph instead, as assert_drawn already does.
Stretched layers copied the nearest source sample for each output sample, which adds error: at
48 kHz the worst error on a 440 Hz tone was 0.025, and 0.15 at 8 kHz. They now blend the two
source samples either side. Layers at 100% and 50% speed keep their exact samples.
The render tests cover a plain precomp, which mixes the same audio as its layers, and the stretch
error against the exact tone.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Adding a marker replaced the comp, so every cached frame stopped matching and the preview had to
re-render before its audio could carry on. Plain markers change no pixels; protected time markers
with a duration still do (Responsive Design). Markers count in full again when a project uses
expressions, which can read them.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
A script asks a light's options for "ADBE Casts Shadows", which returned null. The light's option
is named "Casts Shadows" here, so the lookup never matched. The name is now an alias for the
castsShadows property, and a regression test checks the lookup returns the property.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Inside a function wrapper such as (function () { ... })(), boa places a ReferenceError at the start of
the function, so a script's error was reported at the wrapper's first line rather than the line that
failed. The first use of the undefined name in the code is now the position, and boa's frames remain
the fallback. Thrown errors and object-model errors already report their own lines. A regression
test covers a thrown error, an undefined name, and an object-model error inside a wrapper.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
The Chinese UI fallback was chosen by probing 文, which Japanese faces
cover too. Fallback takes a face already loaded first, so after the
English interface had loaded a Japanese face for kana, switching to
Simplified Chinese reused it, and the simplified-only hanzi (选, 删,
层, 设, 页 ...) drew as boxes. A Simplified Chinese interface now probes
页, as wordcraft does for its interface font (storytold/wordcraft#248).
The layer context menu gains an Effects submenu between Blending Mode and Arrange, mirroring the After Effects layer menu: the effect registry grouped by category (sorted), synced with the Effect menu; picking one applies it to the selected layers.
Psd::tree flattens groups nested deeper than MAX_GROUP_DEPTH into their depth-64 parent, keeping every layer, so the importer recursion and the tree's Drop/Clone/PartialEq are bounded. The import result reports how many groups were flattened.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The handle was filled with the colour of its own track (both the field
background), so it only showed while hovered or dragged. It now takes the text
colour, in every scroll area.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Enter closes the editor like its OK button, also while the search field has
focus. It stays with the shortcut recorder (Enter can be recorded), the preset
rename field and an open preset menu.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The editor's content was a little taller than its dialog, so the outer scroll
area clipped the OK button and its scrollbar covered the right edge. The dialog
now has no outer scroll area: the command list takes whatever height is left,
so the button row always fits, in small windows too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
Undoes the 800 px Project Settings width from #980: the form is back at the
shared 480 px.
A form's choice popup keeps its 240 px column and ends a long choice (a GPU
adapter's name) in an ellipsis instead of widening the grid past the dialog.
Only the fields scroll, and only vertically; OK and Cancel sit under the
scroll area, so they stay in view.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>