Commit Graph
4329 Commits
Author SHA1 Message Date
JonRC 74d71d0f01 Import: BT.2020 PQ and HLG video gets the Rec. 2100 profile (#2849)
profile_of matched BT.2020 primaries before looking at the transfer, so
HDR10 and HLG footage got the Rec. 2020 profile and a managed project
decoded it with the 2.4 gamma. A PQ render of a solid that is 191,64,128
re-imported as 130,73,101, and HLG as 156,36,97.

Map BT.2020 + PQ to Rec. 2100 PQ and BT.2020 + HLG to Rec. 2100 HLG, the
profiles Interpret Footage already offers. A PQ and an HLG ProRes render
now read back into an sRGB project as the solid they came from.
2026-11-02 12:56:27 -03:00
JonRC 1a9eeb9e1b Lottie: warn when embedded glyphs (chars) are not imported
A Lottie file can carry glyph outlines in `chars` for players that lack
the fonts. The import drops them and sets the text in installed fonts,
which can draw it in a fallback font. It now says so in the warnings,
naming the font families the glyphs were for.

Fixes #2844.
2026-11-02 12:33:02 -03:00
JonRC ace329d126 Roto Brush: a Freeze job reads the frozen cache once (#2833)
frame_matte looked up the frozen mattes for every frame, and that hashes
the whole serialized cache and recomputes its keys, so freezing a long
span again grew with frames times cache size. The Freeze job now
resolves the applicable cache once (applying_frozen) and passes it to
frame_matte.
2026-11-02 12:32:25 -03:00
JonRC 70adad5587 Import: an EDL's "rebase after probing" note names only the media left on timecode (#2832)
The import now does the rebase FilmCraft's reader asks for, so passing the
reader's note on told people to do something already done. It is dropped
when every file the list uses at an hour or more of timecode was rebased,
and replaced by a warning naming the ones that weren't (the file is missing
or has no start timecode).
2026-11-02 12:26:37 -03:00
JonRC 0af6d2aab8 Text animators: a later animator's Opacity can show characters an earlier one hid
Animator Opacity stacked by multiplying, so once one animator set 0 %
no animator below it could raise it again. Each animator now blends the
opacity left by the ones above it toward its own value. A single Opacity
animator gives the same result as before.

Fixes #2838.
2026-11-02 12:16:12 -03:00
JonRC 7d00b5322d Lottie: read the closed flag older Bodymovin files keep outside the path
Bodymovin 3.x and early 4.x write `cl` on a mask and `closed` on an `sh`
item, with no `c` in the path, so the import brought these masks and
paths in open. An open mask doesn't cut its layer, and masked solids
filled the frame. The path's own `c` still wins.

Fixes #2837.
2026-11-02 12:07:55 -03:00
JonRC 0de8d57cf8 Import: EDL source timecodes land on each file's own time (#2832)
FilmCraft's EDL reader keeps source timecodes as media time and leaves the
rebase to the caller after probing. The probe now keeps the file's start
timecode (Footage::file_timecode), and an EDL import rebases each found
file's clips with filmcraft_interchange::rebase_source_timecode before the
layers are made, as FilmCraft's own import does.
2026-11-02 11:46:03 -03:00
JonRC 1cd7c2e6f6 Roto Brush: freezing again keeps frames that are frozen already (#2833)
With frozen mattes now used in a session without the model that froze
them, a second Freeze in such a session still segmented every frame
again, so it replaced the model's matte with the session engine's.
frame_matte, which only Freeze calls, now returns a frame's frozen matte
while the frozen mattes apply, and segments only frames that have none.
2026-11-02 11:42:22 -03:00
JonRC c08e6f6d5f Roto Brush: keep frozen mattes in a session without their model (#2833)
The frozen key hashes the chain keys, whose seed holds the session's
model, so mattes frozen with SAM 2.1 didn't match in a session on
Classic, such as a fresh effectcraft-cli render, and the frame was
segmented again with Classic. Accept the key under any Roto Brush model
too, as Object Matte has done since #1852. frozen_key is unchanged for
projects frozen today, and editing a stroke or a matte setting still
makes the frozen mattes stale.
2026-11-02 11:04:25 -03:00
ashandClaude Opus 5.5 9d7baea5cc Fix #2823: Propagate boxes SAM 2 around the matte shown on the stroked frame (#2826)
* Fix #2823: Propagate boxes SAM 2 around the matte shown on the stroked frame

The tracker's box prompt came from the classic graph cut of the strokes,
which can leak into the background; SAM 2 then filled the whole box.
Build the box from the model's own matte (segment_with), the one shown
before Propagate. segment_with falls back to the classic cut when the
model can't segment, so non-model paths are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fix #2823: box a lone object around the matte shown on correction frames too

A correction frame shows a matte propagated from the frame before, not a
fresh model cut, so the tracker's box came from a different matte than
the one on screen. With one object the box now comes from Chain::ensure,
the matte shown on that frame. Several objects share one shown matte, so
each keeps the model's cut of its own strokes. Cancelling while the shown
matte is computed stops instead of falling back, and the prompt frame is
read only when needed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:18:41 +01:00
rahul05ranjan 540ee9fbc5 Motion Tile: mirror folds sample the edge texel, not the transparent outside
A tile boundary that lands exactly on an output pixel centre puts the tile
fraction at exactly 0 or 1, and the sample position at the source's geometric
edge — where sample_bilinear mixes in half a texel of the transparent outside.
The fold column comes out half-faded: a visible seam line along the mirrored
boundary, which sweeps the tile as Tile Center animates across pixel centres
(#2820). Both the CPU path and the GPU kernel switch to the clamped sampler,
which repeats the edge texel there; interior samples are untouched, and the
default single-tile identity mapping already sampled texel centres.

The regression test puts the folds exactly on pixel centres (tileWidth 50%,
centre on the layer, mirror on) and asserts the fold columns stay opaque and
equal the edge texels they mirror — it fails on the unfixed code at alpha 0.5.

Fixes #2820

Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com>
2026-11-02 12:30:58 +00:00
JonRC a2f6cd3ed5 3D Camera Tracker: a partial solve is not reported as solved (#2822)
camera.solveStatus said `solved: true` for any stored solve, but the solver
keeps the frames it cannot resect as unsolved and interpolates the camera
there. `solved` now needs every frame, the same check camera.exportBlender
makes, and `partial` marks a solve with gaps, next to `solvedFrames`.
2026-11-02 09:15:05 -03:00
Rahulandrahul05ranjan c920155679 test(cli): a child that exits before draining stdin breaks the write, not the test
The FreeBSD run of run_reads_commands_from_a_file_or_stdin hit a race: the CLI
exits with code 2 on the usage-error cases before the helper finishes writing
its standard input, so write_all fails with BrokenPipe and the unwrap panicked
at apps/effectcraft-cli/tests/it/cli.rs:139:61.

Ignore exactly BrokenPipe while writing the piped standard input and assert on
any other error kind, so an early exit keeps feeding the assertions below
instead of failing the harness.

Fixes #2794

Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com>
2026-11-02 15:20:45 +05:30
heojunfoandClaude Opus 5.5 3b2e26ceef Render Queue EXR sequences are scan-line, not tiled (#2805)
image's OpenEXR encoder writes 64x64 RLE tiles, which FilmCraft and other
scan-line readers refuse. Write the frames with the exr crate in scan lines
with ZIP, like comp.saveFrameAsExr.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 15:29:59 +09:00
Brandon Thomas ad7abfa507 Merge PR #2792 (author's repin, same as main) 2026-11-01 22:15:08 -05:00
Brandon ThomasandClaude Opus 5.5 f6b09d7816 test(ui): the fake sound card waits to pull until the starting frame is checked
Under load its thread pulled samples before the test read the clock, so
'from the first frame' saw frame 1 and a_started_preview_follows_its_sound flaked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 22:13:48 -05:00
Brandon ThomasandClaude Opus 5.5 35ce2186a4 Follow-up to #2804: ProRes frame headers carry the colr atom's colour codes
They said BT.709 for every output, so a non-709 render disagreed with its atom.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 21:53:42 -05:00
Brandon ThomasandClaude Opus 5.5 7441ccf187 Follow-up to #2781: Swedish Keys, File, Top and Bottom read as they're used
Keyframes column, a file field, crop/alignment edges.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 21:51:17 -05:00
Brandon ThomasandClaude Opus 5.5 d2fa9c1905 Follow-up to #2792: pin craft-ecproj-format to craft-libs main (ca1b5e2e, #409)
The PR pinned the head of a fork branch, not in craft-libs history; the crate
source is byte-identical at both revs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 21:51:09 -05:00
Brandon Thomas f3cedac8cc Merge PR #2792 2026-11-01 21:50:53 -05:00
Brandon Thomas 1467d94945 Merge PR #2804 2026-11-01 21:50:53 -05:00
Brandon Thomas 4375b689ea Merge PR #2798 2026-11-01 21:50:53 -05:00
Brandon Thomas 6f89617042 Merge PR #2790 2026-11-01 21:50:53 -05:00
Brandon Thomas a658ec736a Merge PR #1266 2026-11-01 21:50:53 -05:00
Brandon Thomas 4515418fd4 Merge PR #2742 2026-11-01 21:50:53 -05:00
Brandon Thomas 546da0a1f5 Merge PR #2679 2026-11-01 21:50:53 -05:00
Brandon Thomas 5068f42601 Merge PR #2781 2026-11-01 21:50:53 -05:00
Brandon Thomas e0cd2914ba Merge PR #2783 2026-11-01 21:50:53 -05:00
Brandon Thomas e80d5c42c2 Merge PR #2771 2026-11-01 21:50:52 -05:00
Brandon Thomas 43d76d38a0 Merge PR #2759 2026-11-01 21:50:52 -05:00
Brandon Thomas 7c151edd40 Merge PR #2758 2026-11-01 21:50:52 -05:00
dotCooCoo d4f4c43a29 Project files: pin craft-ecproj-format to craft-libs main
craft-libs #409 merged as ca1b5e2. The crate's source is the same as
at the earlier pin d74959f.
2026-11-01 17:39:27 -08:00
JonRC e935818f77 Contributors: add JonRC's name 2026-11-01 22:28:24 -03:00
JonRC d0e7e09ecb Export: write a colr atom in ProRes MOVs (#2801)
ProRes renders had no colr atom, so the stream reported no primaries,
transfer or matrix. Write an nclc atom, as FilmCraft does for MOV, with
the codes of what the render path makes: the project's output space when
it has a working space, BT.709 otherwise.

sRGB output stays at transfer 1, which is still open on #340 and #464.
The frames don't change, so the pinned ProRes bytes move by exactly the
atom's 18 bytes.
2026-11-01 22:28:23 -03:00
dotCooCoo 1c08d8cb04 Merge storytold/effectcraft main into feat/ecproj-format-from-craft-libs 2026-11-01 17:20:50 -08:00
Jonas Neubauer bfe7535a5e G2: web Save As asks before replacing a stored project (#2788) 2026-11-02 01:15:08 +01:00
Jonas Neubauer 55a8a7e0d9 G2: web Save As keeps the project extension on dotted names (#2788) 2026-11-02 01:01:54 +01:00
jayzed80 9bdee07281 fix(path): Wiggle Paths no longer overflows on an absurd speed, time or phase 2026-11-01 22:18:36 +00:00
Jonas Neubauer 9a4c160f0e G2: distinct XML copy name and a name prompt for web Save As (#2788) 2026-11-01 21:08:01 +01:00
Jonas Neubauer 4dac9d04fc G2: Save a Copy starts from "<name> copy" (#2788) 2026-11-01 20:44:57 +01:00
dotCooCoo b133c0500f Project files: read savedBy through craft-ecproj-format's Head
The craft-ecproj-format pin moves to storytold/craft-libs#409's new
head, where Head::read is the one reader and saved_by() is removed.
effectcraft-project's saved_by reads savedBy with Head::read, and from
ReadError::TooNew for a project with a newer schema.

saved_by now returns None for text that is not a JSON object with a u32
schema. EffectCraft calls it only on files Project::from_json opened,
so opening and importing projects are unchanged.
2026-11-01 11:02:30 -08:00
Brandon ThomasandClaude Opus 5.5 720c67117e Release 0.20.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.20.0
2026-11-01 13:59:03 -05:00
dotCooCoo 42b04479be Merge storytold/effectcraft main into feat/ecproj-format-from-craft-libs 2026-11-01 09:42:43 -08:00
dotCooCoo b1571abaaa Project files: the file envelope comes from craft-ecproj-format
effectcraft-project writes and checks the envelope of .ecproj files with
craft-ecproj-format from craft-libs: File (savedBy, then the saved view
and the project) with to_json and to_json_compact for Save Compact
Project Files, check_schema and its message, SCHEMA_VERSION and
saved_by, which stay re-exported under their names. Project, SavedView
and the schema 1 conversion stay here.

Saved files are byte-identical. saved_by now reads only a JSON object,
so a project written as a JSON array no longer reports a savedBy.
2026-11-01 09:42:43 -08:00
Jonas Neubauer cccd5cba8f G2: Save As starts from the open project's name (#2788) 2026-11-01 18:37:46 +01:00
Dylan M. Taylor 6372545dab docs: sync Craft App Suite list with ArtCraft Launcher 2026-11-01 12:30:01 -05:00
tylerjenningswandChewybone-sudo 3ab2167e47 Auto-Trace: traced outlines map back into layer space (#2764)
Co-authored-by: Chewybone-sudo <347238078+Chewybone-sudo@users.noreply.github.com>
2026-11-01 09:05:56 -05:00
tylerjenningswandChewybone-sudo 49774ca5f9 Auto-Trace: test that traced outlines map back into layer space (#2764)
Co-authored-by: Chewybone-sudo <347238078+Chewybone-sudo@users.noreply.github.com>
2026-11-01 09:02:42 -05:00
Patrik LermonandClaude Opus 5.5 34b32d60da i18n(sv): translate 85 new strings
Brings the Swedish catalog up to date with upstream main (e71dd629).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 14:36:23 +01:00
becauseno7 25a7d98ebc PDF import: a trailer string in a stream does not trigger the window fallback
A `trailer` marker inside an unreferenced stream followed by `(` and more
than 4 KiB of text made the lexer stop at the window's end, so a later
`/Encrypt` name anywhere in the file refused a plain file. The unbounded
scan read a string there and opened it. The past-the-window fallback now
applies only when no object starts in the window or the first one opens
a dictionary (`<<`, including one split by the window's end).

Regression test with `trailer(` and `trailer[` in a stream and a later
Encrypt name.
2026-11-01 14:44:26 +06:00