Commit Graph
4638 Commits
Author SHA1 Message Date
ash bde8bea2bb Merge pull request #3564 from arnav-hiwarkar/fix/3535-analysis-inputs
Warp Stabilizer, 3D Camera Tracker: analysis keys cover masks, effects above and precomp contents (#3535)
2026-11-12 17:19:35 +05:30
ash 6ea9476ee4 Merge pull request #3560 from arnav-hiwarkar/fix/3538-ocio-file-reload
OCIO File Transform and custom OCIO configs follow their files on disk (#3538)
2026-11-12 17:08:11 +05:30
ash 46eb4d104d Merge pull request #3561 from arnav-hiwarkar/fix/3539-viewer-reload
Viewers show footage reloaded with unchanged metadata (#3539)
2026-11-12 17:03:17 +05:30
Dylan M. Taylor 740afc2869 FBX: records stay within their parent; textures, materials and links are indexed
* fix(model): FBX records stay within their parent, and textures, materials and links are indexed

A binary child record could end past its parent: the parent's end was then restored and the
child's tail parsed again. A failed array decompression printed the decompressed bytes in the
error. Texture objects aliasing one embedded Video or file each decoded and kept their own
pixels, outside the import budget. Each polygon scanned the primitive groups for its material,
and each object scanned every connection for its children.

* address review: FBX textures: key image cache by the source used, charge decoded size before decoding, propagate budget errors

* Import: a model's left-out parts reach the user as an import warning (Model::warnings, Importer::probe_noting)

* Import: a model's left-out parts reach the user as an import warning

* FBX: textures past the limits are left out with an import warning, not a failed import; 2^29-pixel allowance
2026-11-12 06:30:20 -05:00
Dylan M. Taylor cb5bc81d28 Automation: refuse Watch Folder and Edit Original while file access is confined
* fix(automation): refuse Watch Folder and Edit Original while file access is confined
2026-11-12 06:30:03 -05:00
Dylan M. Taylor 075aa03ebe Render: memoized audio detection, bounded stretch, preroll, waveform, cache entries, 3D bounds, solids and selector time
* Render: memoized audio detection, bounded stretch, preroll, waveform, cache entries, 3D bounds, solids and selector time

comp_has_audio walked a precomp again for every layer using it; each comp
is answered once. A tiny stored stretch made one audio block fetch a vast
source range; playback speed is capped at 100x. Effect preroll is capped at
10 s. Waveforms stop where the audio ends and summarise at most a day.
Disk cache entries are decompressed only when their stated size matches
what their dimensions need (and at most 1 GiB). Advanced 3D triangle bounds
are clamped on both sides before narrowing. Solids larger than 16 Mpx are
made at a lower scale. A camera-facing layer's parent recursion is bounded.
A layer's Expression Selectors share one time allowance. A disk cache
folder under the temp folder is made private and may not be a link.

* address review: audio detection by breadth-first search, private cache folder resolved before the temp check, oversized layers not written, solid cap after rounding, selector static amount, viewport i32 clamp

* address review: private-folder check skips the temp folder itself; override value in expression fallback; assert alias cache opens

* address review: refuse the shared temp folder itself as a disk cache folder

* address review: shared counted selector budget, 30 s preroll, cache hardening (shared temp roots, matte discard, exact LZ4 length, render version 7), orient nesting guard
2026-11-12 06:29:56 -05:00
Dylan M. Taylor a287044644 Media: check still, EXR channel, GIF and WebP canvas sizes before allocating
* fix(media): check still, EXR channel, GIF and WebP canvas sizes before allocating

* address review: GIF frame allocation limit, lower wasm32 still limit, no EXR fallback after a size-limit error

* address review: the 2^25-pixel still limit also applies on 32-bit native targets

* Media: raise the still pixel limit to 2^28 (16384 x 16384) on 64-bit targets
2026-11-12 06:29:46 -05:00
Dylan M. Taylor 4d6036265b Convert Expression to Keyframes: refuse layers of more than 2^18 frames
* fix(engine): refuse to convert an expression on a layer of more than 2^18 frames

* address review: refuse a non-positive frame duration; count a partial last frame; check every selected layer before converting

* Convert Expression to Keyframes: cap at 2^20 frames (a 3-hour 60 fps comp is 648,000)
2026-11-12 06:29:38 -05:00
Dylan M. Taylor 2b30f53e7a Export: Skip Existing keeps a frame already in the overflow folder
* Export: Skip Existing keeps a frame already in the overflow folder

* Export: Skip Existing checks every overflow folder before a frame is placed
2026-11-12 06:29:31 -05:00
Dylan M. Taylor bdc56ca75e Timewarp: bound the motion search's total work by coarsening the vector grid
* Timewarp: bound the motion search's total comparisons by coarsening the vector grid

* Timewarp: coarsen within the frame, keep the pyramid depth and the window inside the frame
2026-11-12 06:29:25 -05:00
Dylan M. Taylor 9f93ac03fa Text layout: a wrapped line finds its glyphs and end caret by bisection
* Text layout: a wrapped line finds its glyphs and end caret by bisection

* Fix merge of layout tests
2026-11-12 06:29:20 -05:00
Dylan M. Taylor 6e1dd08147 Import: a 3D model's left-out textures reach the user as an import warning
* Import: a model's left-out parts reach the user as an import warning (Model::warnings, Importer::probe_noting)

* Import: a model's left-out parts reach the user as an import warning
2026-11-12 06:29:14 -05:00
arnav-hiwarkar 28c63ce728 #3535: the analysis key leaves out the effects above while the Effects switch is off
The renderer skips the whole effect stack then, so editing those effects
doesn't change the analysed frames. Roto Brush Input Keys keep their text.
2026-11-12 16:30:24 +05:30
arnav-hiwarkar b0133cf862 Merge remote-tracking branch 'upstream/main' into fix/3535-analysis-inputs 2026-11-12 16:14:53 +05:30
ash 44aa7302f8 Merge pull request #3550 from arnav-hiwarkar/fix/3534-3536-analysis-signatures
Warp Stabilizer, 3D Camera Tracker, Roto Brush: one explicit analysis key; offline footage keeps analyses (#3534, #3536)
2026-11-12 16:11:59 +05:30
arnav-hiwarkar 64c28b56d7 #3535: docs: which key covers what, why markers and audio are or aren't keyed 2026-11-12 15:47:50 +05:30
arnav-hiwarkar 36eecad00f #3538: a cached config's size counts the LUTs it holds 2026-11-12 15:30:14 +05:30
arnav-hiwarkar 9831d70bfa #3539: a cache purge gives the viewers' frames new keys
Reload Footage Changed on Disk of a file whose metadata didn't change keeps the
project's revision; PurgeCaches emptied the viewer frame cache but the new
frame came back under the key of the one on screen, so neither the Composition
viewer nor the passive viewers uploaded it. Count purges and mix the count into
the frame key's options, as #3493 does with the LUT generation.
2026-11-12 15:11:13 +05:30
arnav-hiwarkar 4d24233505 #3538: a custom config not read yet is read for its LUT files 2026-11-12 15:07:48 +05:30
arnav-hiwarkar 637d33f796 Merge #3550's branch: the frames key writes names; precomp layer names are keyed too (#3535) 2026-11-12 15:04:14 +05:30
arnav-hiwarkar 385b9530a1 #3535: Warp Stabilizer and 3D Camera Tracker keys cover a precomp's contents
On a precomp layer the key covered only the nested comp's size, rate and
duration, so an edit inside the precomp kept a stale analysis. The key now
writes the precomp layer's Essential Properties and what its comp draws, field
by field and recursively. Each comp is written once per key and nesting is
capped, so shared, deep or cyclic precomps are keyed in bounded time. Docs say
what clears an analysis.
2026-11-12 15:00:14 +05:30
arnav-hiwarkar 51b8521eb3 #3539: test that the viewers show a still reloaded at the same size 2026-11-12 14:53:09 +05:30
arnav-hiwarkar 57990d9a47 #3535: Warp Stabilizer and 3D Camera Tracker keys cover the layer's masks and the effects above them
Their analyses are made from the layer's input to the effect (masks, then the
effects above it), but the key covered only the layer's frames, so a mask or
effect edit kept a stale analysis. frames_key::analysis_key adds the masks,
the effects above the instance and the Effects switch. Keys saved before
(frames only) stay valid while each edit keeps the input.
2026-11-12 14:48:30 +05:30
arnav-hiwarkar 94ab5d77cf #3536: pin the key text of non-default footage, source layer, Cineon, colour space and solid values; every mask mode keys apart 2026-11-12 14:47:05 +05:30
arnav-hiwarkar a700c5c8db #3538: layer keys and render reads include OCIO files and a config's LUTs 2026-11-12 14:43:54 +05:30
arnav-hiwarkar ef137cb2ce #3538: OCIO transform files and configs follow their files through #3493's LUT cache
Move the LUT cache that follows files by size and modification time into
effects::file_cache and use it for ocio::lut::load_file and
ocio_config::load_config. A config's entry depends on the .ocio file, the LUTs
its FileTransforms read and the search-path places it looked for missing ones.
check_lut_files and lut_generation now cover all three caches.
2026-11-12 14:43:54 +05:30
arnav-hiwarkar e04ae226a9 #3536: the frames key writes group and property names, and the uid of a property with an expression
Expressions find effects by name and read names (thisProperty.name,
propertyGroup(1).name), and seed random/wiggle with the property uid, so
both can change the frames. The Debug-based key had them.
2026-11-12 14:37:02 +05:30
arnav-hiwarkar 0547c51e47 #3538: test that OCIO transform files and configs are read again once they change 2026-11-12 14:33:21 +05:30
ash 41585f2aec Merge pull request #3450 from arnav-hiwarkar/fix/3087-aep-effect-placeholders
.aep import: keep effects without a counterpart as placeholders (#3087)
2026-11-12 14:21:58 +05:30
arnav-hiwarkar 1c8d20a12f #3534: test a key 0.24.1 saved while the footage was offline; the frames key doc says what is read in full 2026-11-12 14:19:24 +05:30
arnav-hiwarkar a19ffbc0db #3534, #3536: docs: the Warp Stabilizer and Roto Brush keys come from analysis::frames_key 2026-11-12 14:10:55 +05:30
arnav-hiwarkar 54cf31f841 #3534: footage going offline no longer drops saved analyses
Whether a footage file is there is an observation (footage.check sets
Footage::missing without an edit), not part of the footage. The
signature leaves it out, and keys saved by 0.22-0.24, which hashed it,
are recognised with the file either online or offline. Warp Stabilizer,
3D Camera Tracker and Roto Brush analyses are kept through the next edit
while the footage is offline and after it comes back.
2026-11-12 14:10:23 +05:30
arnav-hiwarkar 54d53fff76 #3536: one explicit analysis signature for Warp Stabilizer, 3D Camera Tracker and Roto Brush
analysis::frames_key writes what a layer's frames are made of field by
field: every struct and enum it writes is destructured or matched in full
and each variant is a fixed word, so a new field doesn't compile until it
is decided and a rename doesn't change keys. Names, labels, UI hints and
markers are left out. Roto Brush's Input Key writes masks and the effects
above it the same way, instead of their Debug text.

Keys saved by 0.22-0.24 are recognised by the old code, moved unchanged
to frames_key::legacy, and kept rather than rewritten (frozen mattes hash
them).
2026-11-12 14:08:57 +05:30
arnav-hiwarkar d361a6cb4e #3534, #3536: pin analysis keys saved by 0.24.1
A fixture keyed by the current release: Warp Stabilizer, 3D Camera Tracker
and Roto Brush keys keep matching through edits that keep the frames, undo
and save/reopen, and real changes still clear them.
2026-11-12 13:56:48 +05:30
arnav-hiwarkar e7a396856d #3087: a placeholder's float slider keeps its range
It arrived as a plain number, so Effect Controls neither dragged it over its
slider range nor clamped an edit to its valid range, as After Effects does.
2026-11-12 13:54:03 +05:30
arnav-hiwarkar 04bbc67528 #3087: test a placeholder found by its match name under ADBE Effect Parade 2026-11-12 13:42:53 +05:30
arnav-hiwarkar b762b4800d Merge remote-tracking branch 'upstream/main' into fix/3087-aep-effect-placeholders
# Conflicts:
#	crates/expr/src/host.rs
2026-11-12 13:42:21 +05:30
Sean Hawkey 24df676af5 Expressions, Scripting: a layer's property numbers and match names follow After Effects (#3528) (#3529)
* Expressions, Scripting: a layer's property numbers follow After Effects

In After Effects a layer's top-level number reaches the same group on every layer of a kind:
Marker is 1, and slots the layer has not used yet (Time Remap, Motion Trackers, Layer Styles,
Data, Sets...) keep their place. EffectCraft numbered only the groups a layer holds, without
Marker, so `layer(n)` and `layer.property(n)` reached a different group, and the numbers moved
as groups were added. Rigs that read a palette by number, such as
`comp("Palette").layer(1)(4)(n)(1)` on a shape layer, read Transform instead of Effects; their
`try` fell back to the stored value and every linked colour rendered near-black, with no
expression error.

`effectcraft_project::ae_order` holds After Effects' slot order per layer kind, observed in
After Effects 26.3 from a script (`layer.property(i).matchName`) and from an expression
(`thisComp.layer(..)(i).name`) on new layers of each kind. The expression host and the
scripting model resolve a layer's numbers through it: 1 is the markers, a used slot is its
group, an unused one is an empty group (never null, so loops over `numProperties` are safe).
`numProperties` at layer level and `propertyIndex` of top-level groups are After Effects'
numbers too. 3D model and primitive layers keep EffectCraft's own numbers.

* Expressions: a layer's top-level groups by After Effects match name

`thisLayer("ADBE Effect Parade")`, as scripts such as Karton write their expressions, reaches the
group through the same table as the layer's numbers: Effects, or an empty group for a slot the
layer has not used, and `("ADBE Marker")` the markers.

* Expressions, Scripting: review follow-ups for After Effects layer numbers

- An enabled Time Remap (a top-level property) reports After Effects' number 2 as its propertyIndex.
- In scripting, an unused slot resolves to the same empty group by match name
  (`property("ADBE Layer Styles")`) as by number (`property(7)`).
- The empty group is callable like any group: `layer.property(7)(1)` is null, not a TypeError.
2026-11-12 13:40:56 +05:30
arnav-hiwarkar a2ada5a5fe #3087: count every parameter a placeholder walks, and popup names by length
A definition of parameters that are not kept, shared by many instances, was
walked again for each one without spending the budget; long popup item
names were kept per instance with each item counted once.
2026-11-12 13:14:16 +05:30
arnav-hiwarkar 6f8c39d5f4 #3087: expressions find an effect by its After Effects match name
effect("Pseudo/0.25") and thisLayer("Effects")("Pseudo/0.25") now match a
placeholder's effect id, now that its match id is one path segment.
2026-11-12 13:06:51 +05:30
arnav-hiwarkar 0da7691d9d #3087: give a placeholder a match id that is one path segment
A pseudo effect's match name (Pseudo/0.25) was its group's match id, so a
match path to its parameters (keyframe paste, pick whip) was cut apart at
'/' and '.' and found nothing. The effect id stays the match name.
2026-11-12 13:06:51 +05:30
arnav-hiwarkar f6e2bdf6a0 Merge remote-tracking branch 'upstream/main' into fix/3087-aep-effect-placeholders
# Conflicts:
#	docs/aep-import.md
2026-11-12 13:01:53 +05:30
ash 9a4d02a827 Merge pull request #3449 from arnav-hiwarkar/fix/3087-aep-psd-layers
.aep import: an item made from one Photoshop layer shows that layer (#3087)
2026-11-12 12:58:31 +05:30
ash 103760584a Merge pull request #3533 from arnav-hiwarkar/fix/3493-lut-cache
Apply Color LUT and Lumetri follow a LUT file that changes on disk (#3493)
2026-11-12 12:00:00 +05:30
ash c9e553266c Merge pull request #3530 from arnav-hiwarkar/fix/3456-tracker-signature
Warp Stabilizer, 3D Camera Tracker: keep analyses saved before 0.23 (#3456)
2026-11-12 11:39:19 +05:30
ash 8a2b4cc633 #2796: ScriptUI panel bars hide while the window fits its dock (#2880)
A docked panel's solid bars, once shown, took their width from the viewport, so a window that exactly filled its dock stayed too large and kept its bars. The bars are now hidden while the window fits its dock (to the whole point, #2585) and stay solid when it overflows (#269).
2026-11-12 11:37:26 +05:30
arnav-hiwarkar 63520598a0 #3493: test the followed-files limit on a cache of its own
The test filled the shared cache past the limit, which could let go of a
file another test running alongside still follows.
2026-11-12 11:36:40 +05:30
arnav-hiwarkar dc3e5245c2 #3493: show the frame again in the viewers once a LUT file changes
The viewers replace their picture only when the frame key changes, and a
frame rendered again after a LUT change had the same key, so the old look
stayed on screen. The viewer frame keys carry the LUT generation (in memory
only), which also leaves frames still rendering with the old LUT unasked
for, so the refusal of late frames is no longer needed.
2026-11-12 11:29:57 +05:30
arnav-hiwarkar d036127bf4 #3493: key a layer reading a precomp on the LUT file its override names
A precomp instance whose Essential Property names another LUT file renders
with that file, but a layer reading the instance through a layer parameter
was keyed on the nested comp's own file, so editing the overriding file left
that layer cached.
2026-11-12 11:29:57 +05:30
arnav-hiwarkar 82c2a23f07 #3493: keep following the LUT file just read past the followed-files limit
Past 1024 followed files, the trim kept only files with a cached LUT and
dropped the one being noted (its LUT is cached right after), so a later
edit to it went unnoticed. The tests start from an empty folder.
2026-11-12 11:29:57 +05:30