Commit Graph
177 Commits
Author SHA1 Message Date
bflatastic 334bf0f785 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/engine/Cargo.toml
2026-10-30 17:22:12 +07:00
BFlat 3d285116d8 Merge pull request #1539 from nanox333/feat/sam2-roto-tracker
Roto Brush: follow the object with SAM 2.1 (Tiny, Small, Base+, Large; optional models)
2026-10-30 17:02:45 +07:00
bflatastic 2a72f03872 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	apps/effectcraft-cli/tests/it/cli.rs
#	crates/engine/src/output_guard.rs
#	docs/agents.md
2026-10-30 16:38:01 +07:00
Kristian Myram b7d97c20e9 #1743: check final storage overflow destinations for queued outputs 2026-10-30 09:55:49 +01:00
Kristian Myram c5671f6569 #1830: require exporter support before skipping duplicate frames 2026-10-30 08:59:53 +01:00
Kristian Myram a21b9b175e #1539: retain checkpoint provenance and clarify model waits 2026-10-30 08:43:33 +01:00
Kristian Myram 33f545cf64 #1539: keep SAM2 weights install-only until mirrored 2026-10-30 08:43:33 +01:00
Claude 66d8e5e948 SAM 2 roto tracker: review fixes (direction-limited tracking, non-blocking model reload, per-object start passes, loader dispatch, CLI errors, hints)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDvxCS8xcR28VArjzn1x7U
2026-10-30 08:43:32 +01:00
Claude 1eee687ebc Roto Brush: save the tracked frames in the project
The tracked frames lived only in memory, so a saved project lost them: a render in another
process (effectcraft-cli render-frame) segmented the frames again with the classic engine.
A propagate with a tracker now saves the frames it followed with the instance, in a hidden
parameter beside Freeze's (TrackCache: each frame's matte, Refine Edge band, colour models and
confidence, keyed by the inputs it was tracked from).

- They apply while the strokes and span they came from are unchanged, whichever model Settings
  choose, so a project renders the same when it reopens, without the model loaded or chosen.
- A stroke or span change makes them stale until the next Propagate. A Propagate replaces them;
  with the classic engine it leaves none.
- roto.status reports tracker.saved (the model they came from) and a notice when Settings
  choose another model.
- The save at job completion is not an undo step (the frames are a cache of the strokes) and is
  skipped if the strokes changed while tracking. Decoding checks the saved size, so a corrupt
  project is ignored rather than overflowing.

Object Matte saves nothing. Projects saved before this change open unchanged (the parameter is
filled in on open).

Tests: a saved project reopens with the model unloaded and renders the saved frames through
Chain::ensure; choosing the classic engine keeps them until a classic Propagate replaces them; a
stroke change makes them stale. The SAM 2 tests and the failing-tracker test take the Roto test
lock.

Claude-Session: https://claude.ai/code/session_0136kZtXrYo5VUWEFxWduwUD
2026-10-30 08:43:30 +01:00
Claude a7417b578d Roto Brush: don't run the classic engine silently under a selected model
With SAM 2 (or MobileSAM) chosen, a propagate that started before the model had loaded ran
the whole job on the classic engine and reported nothing. The chosen model is now in use
before a job that segments with it starts (Roto Brush 2.0 / 3.0 and Object Matte):

- roto.propagate and the other Roto jobs wait for a load or download under way when called with
  wait: true (bounded to 10 minutes). Without wait they refuse while the model is still loading,
  and start the load in the background. A model that is not installed, or failed to load, is
  refused either way.
- roto.status reports model {selected, installed, active, loading, error} and a notice while the
  chosen model is not the one in use. source is "model" for a frame the model segmented on its own,
  instead of "classical".
- Auto-propagate keeps edited instances pending while the model loads, and shows errors as toasts
  instead of dropping them.
- Docs: what propagate does now; tracked frames live in the session that ran propagate and are not
  saved in the project file, so a separate render process does not show them; roto.model.select
  lists sam2.1-hiera-tiny.

Tests: a selected model that is not installed refuses to propagate (no weights needed); SAM 2
selected without wait is loaded before propagate (EFFECTCRAFT_SAM2). The SAM 2 tests and the
failing-tracker test take the Roto test lock, since they share the process-wide model slot.

Claude-Session: https://claude.ai/code/session_0136kZtXrYo5VUWEFxWduwUD
2026-10-30 08:43:30 +01:00
Kristian MyramandClaude Sonnet 5.5 371e67f51e S2.46: document Roto Brush with SAM 2
How to install and use it, how the port was verified, speed and the benchmark.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-30 08:43:30 +01:00
Kristian MyramandClaude Sonnet 5.5 e5842c0c92 S2.30: SAM 2.1 Tiny in the model registry
Apache-2.0 entry pinned to a Hugging Face commit with its SHA-256 and size,
listed in Settings > Roto Brush and installable with the existing verified
install flow. No weights are bundled.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-30 08:43:30 +01:00
Kristian MyramandClaude Sonnet 5.5 d2930b2554 Fix #1743 (follow-up): commands that write to a given path never replace footage, a proxy or the project file
Session::write_output (and refuse_export) is the one place that checks; Save Frame As
(PNG/PSD/EXR), Export Lottie, Save a Copy (+XML), Collect Files, Export Timeline (and its
pre-rendered movies), Export Template, Save Animation Preset, Export Guides and Export
Shortcuts write through it. The control channel's render.frame/ui.screenshot, MCP
render_frame and CLI render-frame --out check first (new query file.checkOutput for the
bridged cases). Save/Save As/auto-save are untouched.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-30 08:06:48 +01:00
Kristian MyramandClaude Sonnet 5.5 615c4cdffb Render Queue: two outputs of one job never write the same file, and default names avoid the queue's other outputs
Two queue items that resolve to one output (the same comp added twice, a duplicated item) replaced
each other's file inside one job. Nothing is on disk when the job starts, so no check said anything.

- A default output name (renderQueue.add, render.preRender, comp.saveFrameAs {queue},
  file.createProxy) that another item of the queue writes, in any output module or segment, is
  numbered like a footage collision: Main.mp4, Main_1.mp4, Main_2.mp4. Sequences are compared by
  the frames they write, so two stills of one comp at different times keep their names. Names a
  caller gave and names already stored in items are never changed.
- Outputs of one job that still name the same file (explicit names, renderQueue.duplicate, output
  modules, segments) refuse the whole render before anything is written, naming both items.
  Sequences clash only on frames both write; a later item with Skip Existing Files leaves the
  earlier item's frames alone; items refused for footage take no part.

Refusing the whole render, not just the later item: which of two items should keep the file is the
user's to say, and failing only the later one would leave a half-rendered queue found after they
left. renderQueue.duplicate stays a verbatim copy so the clash is reported, not hidden.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDvxCS8xcR28VArjzn1x7U
2026-10-30 08:04:32 +01:00
bflatastic bf19754745 Merge remote-tracking branch 'origin/main' into HEAD 2026-10-30 09:54:28 +07:00
bflatasticandClaude Opus 5.5 2554d3271f Merge main into #2236; no conflicts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 09:23:40 +07:00
bflatastic b9a86f5139 Merge main into #1758; no conflicts 2026-10-30 09:17:08 +07:00
Kristian Myram 199af9213c #1743: use existing CI and consolidate render source documentation 2026-10-30 02:10:36 +01:00
bflatasticandClaude Opus 5.5 d1a3510a42 Merge main into #2442; clean merge, no conflicts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 07:46:40 +07:00
bflatastic 5c89837f91 Merge remote-tracking branch 'origin/main' into HEAD 2026-10-30 07:10:36 +07:00
Marco Arnulfo 86268fc4cc MCP: Text Path Options ▸ Path lists the layer's masks as its options, like the Timeline 2026-10-30 00:44:58 +01:00
Marco Arnulfo 701d9df8a5 MCP: get_property and get_layer list an enum property's options (#2085) 2026-10-30 00:44:58 +01:00
Krueels dcbb806139 #986: add Blender scene export for 3D Camera Tracker 2026-10-29 20:15:25 -03:00
bflatastic 335abf42c4 Merge main into #2474; tests/it/main.rs keeps both ui_env_light_gpu and main's ui_expression_values 2026-10-30 05:53:20 +07:00
bflatastic bd34ab21b6 Merge main into #2279; keep main's Scripts subfolders (RESERVED_FOLDERS) next to the Startup/Shutdown constants, merge docs rows 2026-10-30 05:34:26 +07:00
BFlat d26ab3b83e Merge pull request #2609 from storytold/fix/qa-sequence-import
Tests: QA scenarios ask for image sequences explicitly
2026-10-30 04:33:27 +07:00
BFlat a0bec0905c Merge pull request #2595 from zitann2020/text/keep-empty-layer
fix(text): keep an empty Type-tool layer, as AE does
2026-10-30 04:09:42 +07:00
BFlat 686da9f7eb Merge pull request #1291 from tylerjenningsw/enhance/batch-parent-matte
Timeline: parent and matte selected layers together (#1260)
2026-10-30 04:08:08 +07:00
bflatasticandClaude Opus 5.5 4c787734fd Tests: QA scenarios ask for image sequences explicitly (#2018)
Since #2604 a picked numbered still imports as itself unless the import
asks for a sequence, as in After Effects. The compositing and tracking QA
scenarios import a PNG run, so they pass `sequence: true`; docs/agents.md
describes the new default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 04:04:04 +07:00
BFlat 6f1d11af94 Merge pull request #1385 from tylerjenningsw/enhance/pickwhip-index-refs
Expressions: Alt-pickwhip references effect parameters by index (refs #1072)
2026-10-30 01:18:08 +07:00
BFlat e6e0c98c20 Merge pull request #2311 from marcoarnulfo/feat/run-commands
CLI: run --commands reads {"command", "params"} steps from a JSON or JSON Lines file, or standard input (#2251)
2026-10-30 01:17:37 +07:00
tylerjenningsw 5f22e63e93 Merge remote-tracking branch 'origin/main' into enhance/batch-parent-matte 2026-10-29 13:29:22 -04:00
BFlat f27ecec030 Merge pull request #2344 from becauseno7/mcp-compact-listings
MCP: list_commands and list_effects take compact: true (#2020)
2026-10-30 00:13:36 +07:00
zitann2020andDeepSeek V4.1 Flash 197d6cd229 fix(text): the tests and docs follow the layer being kept
Review of the first commit found three places that still asserted the old cleanup: the UI integration
test (which would have failed CI), docs/agents.md, and the comments on TextEdit::created, layer.newText
and the engine test itself.

Co-Authored-By: DeepSeek V4.1 Flash <noreply@deepseek.com>
2026-10-30 01:09:35 +09:00
Claude 7583fb914a Merge main into fix/1743-render-overwrite-confirm
output_guard joins the split engine lib.rs; the overwrite tests move to tests/render_overwrite.rs
(#2491) and the regression workflow's test filter follows.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDvxCS8xcR28VArjzn1x7U
2026-10-29 10:31:40 +00:00
Z User f47b57d3f8 Merge remote-tracking branch 'origin/main' into fix/environment-light-no-effect-cast-shadows 2026-10-29 08:54:59 +00:00
dotCooCoo 5e32a2a39c Merge main and preserve Startup script tasks across project changes 2026-10-27 11:41:43 -07:00
Z User a8cba23edc Review fixes: the environment shadow follows the tinted radiance (#2436)
dominant_direction weighted texels by their raw channel sum before the
light's colour tinted the radiance, so equally bright red and blue regions
on opposite sides cancelled to no sun and no key — while a red Environment
light's tint removed the blue contribution and left the scene lit
directionally red, with no shadow for its Cast Shadows to show. The tint
now weights the direction sum (a white light weights [1; 3], a coloured
one its normalised colour), so the sun and key are derived from the
radiance the light actually emits; add_environment computes the tint once,
before the direction pass, and reuses it for the texel tinting. An
achromatic image is unaffected (its weights scale uniformly), so the
default studio and white-lit scenes keep their shadows exactly.

Tests: opposed red and blue texels cancel to a white light but a red tint
points the sun straight at the red one (a blue tint, at the blue one); end
to end, a red Environment light over an image with equally bright red and
blue regions on exactly antipodal positions casts the shadow a white light
over the same image does not — and the shadow falls opposite the red
region, the side the tinted radiance comes from.
2026-10-27 14:11:55 +00:00
Z User eb34d10d21 Review fixes: a failed environment source lights nothing (#2436)
Two review points on the merge:

- env_pixels returned None both for an unconfigured light (no Source, no
  Environment Layer) and for a failed source (a deleted layer, missing
  footage, a failed decode), so a selected source that failed silently
  swapped in the default studio environment — relighting and reshadowing
  the scene behind the user's back. It now tells the three apart
  (EnvPixels::Absent/Image/Failed): only the unconfigured light uses the
  default; a failed source contributes nothing, exactly like a layer whose
  source fails renders nothing. The repair the user can act on stays where
  it already lives — missing footage is flagged on the item, with the
  relink commands to fix it.

- The docs claimed only a uniform image casts no shadow. A non-uniform one
  can be directionless too: opposing bright regions cancel, and anything
  under 1% directional is rejected. agents.md, architecture.md and the
  sun/dominant_direction doc comments now say an image without a
  sufficiently strong dominant direction.

Tests: an unreadable Environment Layer (auto-picked), an unreadable
selected Source and a deleted one all light nothing — pixel-equal to the
unlit render, no studio default, no default-environment shadow — while an
unconfigured light still lights; two equal bright spots at opposite
azimuths cancel to no sun and no key, and tilting the balance re-emerges
pointing at the brighter spot.
2026-10-27 12:33:46 +00:00
Jeremy ed3e3d4bfe docs(installer): note that the 32-bit all-users folder is Program Files (x86); tidy wording 2026-10-27 12:25:18 +00:00
Jeremy a41f75b4a7 docs(installer): describe the per-user default install location and scope 2026-10-27 12:09:02 +00:00
Minher0 743119d6e5 Give the Environment light After Effects' look (#2436)
The default studio environment's level-preserving mean of 1 acted like a
100% white Ambient light: with only the Environment light on, a white floor
rendered at full white (95% of the frame saturated) while its shadow core
went to pitch black — a fog over the scene, nothing like After Effects'
default. Three changes bring the look in line, CPU and GPU alike:

- The default environment is a dim studio now: a solid-angle-weighted mean
  of 0.3 (and a stronger key gradient), so a white floor reads a mid gray
  and the light's colour x intensity still scales the level.
- The shadow occludes only the image's directional (key) fraction of the
  light — |sum of dir x radiance| / sum of radiance, computed beside the
  dominant direction and carried in the scene — so the fill keeps shining
  inside the shadow: an area-light shadow, partial like After Effects'
  (a lone bright spot on black still shadows almost fully; a uniform image
  not at all).
- The environment shadow map's penumbra has a floor — eight output pixels,
  or four map texels where those are coarser — because the map covers the
  whole scene bounding sphere rather than the view, and its texels would
  otherwise stair-step the edge (all the more in a draft render's flat 512
  budget). Shadow Diffusion widens it further, as before.

Tests: the key fraction tracks directionality; the default keeps its dim
level, its direction and its key; the default and a bright key both shadow
the floor (the default partial, the key deep) with Cast Shadows off lit
everywhere; and the full look — a mid-gray lit floor (no fog), a partial
core, and a soft edge ramp in quality and draft renders alike.
2026-10-26 23:36:19 +00:00
Minher0 aff46dabb6 Cast shadows from the Environment light's default environment (#2436)
After Effects' default environment map casts shadows out of the box: an
Environment light with Cast Shadows on shadows the scene with no Source
set. The flat default cancelled its dominant direction to zero, so the
option did nothing until a Source image arrived. Give the default a soft
studio gradient (bright above and toward the initial camera, dark below
and behind), level-normalised so the light's colour x intensity still
sets the overall brightness; its dominant region drives the existing
shadow pipeline, CPU and GPU alike.
2026-10-26 20:26:03 +00:00
Minher0 863f0e49c1 Render the Environment light's shadow from its image (#2436)
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.
2026-10-26 13:05:16 +00:00
Minher0 1599790ac9 Light Environment lights: default environment, Casts Shadows, Advanced 3D switch (#2436)
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.
2026-10-26 09:43:47 +00:00
tylerjenningsw 9b57090b00 Merge main into enhance/batch-parent-matte 2026-10-25 14:54:57 -04:00
tylerjenningsw 653a63c0b1 Merge main into enhance/pickwhip-index-refs 2026-10-25 14:26:30 -04:00
skylartaylor 9ee853715d M0.37: migrate EffectCraft to egui 0.37
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.
2026-10-25 02:01:16 +01:00
Kristian Myram 9d33c200d5 #1743: protect render sources and refresh proxies safely 2026-10-24 23:00:46 +00:00
Shuvra Basak 4cc490c8c6 MCP: list_commands and list_effects take compact: true (#2020)
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.
2026-10-24 21:27:40 +00:00