Services::full_path now returns None when the working directory can't be
read, instead of the relative path. file.runScript still runs the script
but does not add it to the list, so a later working directory can't make
the entry open a different file.
File > Scripts lists a bundled script even when an installed ScriptUI
panel has the same name, but running it by name opened the panel. A
script now runs before a panel of the same name, and it enters Recent
Script Files.
- Default disk cache size 20 GB (was 100 GB); settings version 3 migrates the stored old
default and keeps a size the user chose.
- The cache keeps max(2 GB, 5% of the disk) free: sysinfo::disk_space (df -Pk / PowerShell
DriveInfo) is read in the background from memory_tick and caps the limit
(DiskCache::set_disk_space); cache.diskStats reports limitBytes.
- Eviction goes down to 90% of the limit, so the LRU sort runs once per tenth of the limit
written instead of on every write at the limit.
- Failed writes are counted (cache.diskStats failed) and the first is logged.
Also fixes#2063.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
effect.cryptomatteAt rendered the effect's input on every call to learn its pixel grid (up
to ~1 s per hover on a 3D precomp). The aux channels and that grid are now kept in a
CryptoProbe on the Session, keyed by the project revision, layer, effect, frame, scale and
render prefs (nested switches, draft shadows). On footage with nothing animated before the
Cryptomatte effect the frame is the source frame, so a still or a held frame keeps one
probe for every comp time. The effect's own Selection doesn't count: the probe never reads
it, so an animated Selection keeps the probe too.
Session::crypto_probe_ready says whether a query answers from the kept probe and changes
nothing. Session::crypto_probe_job builds it on another thread for the viewer; asking for a
job is starting it. Each started job has a generation: it stores its result only while it
is the newest, a newer job or an edit cancels it, and a panic in the build becomes the
probe's error. A cancelled build checks its generation between its stages (reading the IDs,
rendering the effect's input), so it stops early and lets go of what it read. `probeOnly`
makes cryptomatteAt / pickCryptomatte answer {pending} instead of building on the caller.
A pick re-keys the probe (it only edits the Selection), and undo, redo and history jumps
over picks keep it too (each pick is labelled "Pick Cryptomatte"). Any other edit, footage
changes, Open / New and Session::drop_crypto_probe (the eyedropper disarmed) let it go. The
slot's type is crate-private (the Session field stays public, doc(hidden), so other crates
can still build a Session); crypto_probe_stats and crypto_probe_jobs (jobs run, cancelled
ones included) are doc(hidden), for tests.
Found while testing crates/engine/src/cmd/align_data.rs:75 (parse_stamp)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Three small fixes from the review of the shadow commit:
- light_settings switched a Classic 3D comp to Advanced 3D whenever the
edited light was an Environment light (the resulting kind), so editing
the intensity of one in a comp the user had switched back to Classic 3D
dragged the renderer back. The switch now happens only on the
non-Environment to Environment transition (the sources before and
after), matching the docs; ordinary edits leave the renderer to the
user.
- dominant_direction's thresholds let NaN through (every NaN comparison
is false): a NaN or infinite texel produced a NaN sun direction and
NaN shading with it. A non-finite weight or length now returns no
direction — garbage casts no shadow.
- add_environment walked the full-resolution image for the dominant
direction even when the light casts no shadows, where nothing reads
it. Only a shadow-casting light pays for the pass now.
Tests: editing an existing Environment light in a Classic 3D comp keeps
the renderer and stays toast-silent; a NaN and an infinite environment
image yield no sun direction.
The Casts Shadows option Environment lights got is only half a fix if
nothing shades for it: an image lights the scene from every direction,
and what occludes that light is the image itself — its dominant bright
region, the sun in a sky map.
- dominant_direction finds it: the radiance-weighted mean texel
direction (solid-angle weighted, rotation applied). A uniform image
cancels to zero — a flat default environment shines from everywhere
at once and casts no shadow, which a uniform environment test pins.
- The shadow is one orthographic map over the scene from that
direction, after the lights' maps, like a parallel light's: PCF
widened by Shadow Diffusion, darkened by Shadow Darkness, cleared
when nothing casts, the image is directionless, or the texel budget
drops it.
- It darkens the environment's own diffuse and specular light on
Accepts Shadows surfaces and counts in Cast Shadows Only. CPU and
GPU (WGSL) do the same; Globals carries the environment's sun
direction and shadow settings (40 → 44 floats, preflight updated).
A bright-disc environment turned to shine from behind the camera now
shadows a sphere onto the floor behind it, Cast Shadows off lights it
evenly again, and the GPU scene's sky gradient takes a shadow-casting
Environment light. Also: the renderer-switch toasts read "...renderer,
which draws 3D models", the dialog's Casts Shadows checkbox gets an
auto id (dialog.light.casts) the tests click, and the docs' Environment
notes cover the shadow.
An Environment light had no visible effect, and its Light Settings dialog had
no Casts Shadows option — both halves of #2436.
No effect had two causes:
- Classic 3D (the default for new comps) skips Environment lights entirely,
so creating one did nothing. Adding one (or changing a light's type to it)
now switches the comp to Advanced 3D in the same undo step, with a toast,
exactly as model and primitive layers already do; switching back to
Classic 3D with an Environment light in the comp explains itself too.
- In Advanced 3D, a light with no Source and no Environment Layer produced no
environment at all. It now falls back to a flat default environment of the
light's colour × intensity, as After Effects does, so the light always
lights the scene per its parameters.
Cast Shadows was missing because the dialog and the light's property groups
shared one gate (Falloff and Shadows together) that excluded Environment.
The two are now split: every light but Ambient gets Casts Shadows, Shadow
Darkness and Shadow Diffusion (stored, edited and carried over on type
changes), while Falloff stays on Parallel/Spot/Point only — an environment
light shines from every direction at once and has no use for a falloff.
Tests: the renderer lights a card from a sourceless Environment light (colour
and intensity drive it, zero intensity lights nothing), the engine switches
Classic comps to Advanced 3D on creation and type change (one undo step,
toast, and the Classic 3D switch-back toast), Environment lights take and
carry shadow options but no Falloff, and the dialog ticks Casts Shadows on
a new Environment light.
Wiggle Paths had Size, Detail, Points, Wiggles/Second, Correlation,
Temporal Phase and Random Seed, but no Spatial Phase, which After
Effects lists among its properties (ADBE Vector Spatial Phase). Spatial
Phase now moves each point's own displacement along its subpath: 360
degrees is once around, and a fraction of a point is interpolated
between neighbors. At 0 degrees a path draws as before.
A project saved without the property gets it at 0 degrees, after
Temporal Phase, when it opens. Scripts can read and set every Wiggle
Paths property by its match name.
A failing atomic batch restored the project, history and state but left the
events its steps had already published, so the UI could open the comp the
rollback had just undone. Snapshot the event count with the other snapshots and
truncate before the rollback bumps.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>