Commit Graph
4122 Commits
Author SHA1 Message Date
BFlat 142bb75f2e Merge pull request #1895 from ki2pixel/mute-keyframes
Keyframes: mute keyframes without deleting them (#1894)
2026-10-30 07:01:54 +07:00
bflatastic 80cb8a06ae Merge remote-tracking branch 'origin/main' into HEAD 2026-10-30 07:01:38 +07:00
Marco Arnulfo efd6ab97dc fix(effects): cover Particle World's Texture Layer buffer before sampling it
Text and shape layers hand over a buffer that spans only their content;
the clamped sampling then stretched its edge pixels across the squares.
2026-10-30 00:52:10 +01:00
Marco Arnulfo a76c65bd00 fix(effects): keep Particle World on the GPU unless Textured Square draws the Texture Layer
A Texture Layer left set with another Particle Type forced the CPU for
nothing. gpu_supported now asks the same predicate the CPU path uses.
2026-10-30 00:52:10 +01:00
Marco Arnulfo 2a5e9066e5 fix(effects): draw Particle World's Texture Layer in the motion-trail samples too
With the shutter open the textured squares fell back to the particle
colour. Both branches now draw through the same sprite closure, and the
sharp frame goes through plan.post like the trails.
2026-10-30 00:52:10 +01:00
Marco Arnulfo 0c35a7a889 fix(effects): let CC Particle World's Textured Square use a Texture Layer (fixes #1465) 2026-10-30 00:52:10 +01:00
midasdf d3aa81ffba Merge remote-tracking branch 'origin/main' into jp/ja-dialogs
Resolve the two conflicts the panel catalogs and the Composition Settings
rewrite left:

- i18n/ui.rs: keep both sides' rows in the Simplified and Traditional Chinese
  catalogs, which grew at the same anchor (the PR's 301 panel/dialog rows, then
  main's 43 tool and Preview-panel rows). The tables are grouped by feature, not
  sorted by key, so the two blocks sit one after the other. Both sides also added
  "Frame Rate" once: keep one row per catalog, main's 影格速率 in Traditional
  (matching the table's existing 影格速率:) and 帧速率 in Simplified.
- comp_settings.rs: take main's rewritten tab_body (it returns () and matches on
  the tab, and show() measures the tabs) and re-apply the wrapping the old layout
  had: the three tab labels go through tr(), as Basic, Advanced and 3D Renderer
  already have rows. The old horizontal layout and its out accumulator are gone.

cargo test -p effectcraft-ui-egui --lib: 336 passed, 0 failed, 3 ignored.
2026-10-30 08:47:55 +09:00
BFlat 9250a30b37 Merge pull request #2622 from storytold/fix/2593-render-countdown
Render Queue: elapsed and remaining time tick between frames (#2593)
2026-10-30 06:45:16 +07:00
BFlat b704bb4780 Merge pull request #2621 from storytold/fix/script-replace-single-file
Scripts: FootageItem.replace() swaps in one file, as in After Effects
2026-10-30 06:45:09 +07:00
Marco Arnulfo 495243c5b6 Scale Composition: refuse more than one of factor, width and height instead of ignoring the others 2026-10-30 00:44:58 +01: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 807803c14b Scale Composition: escape pipes in the parity table, check redo in the test 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
Marco Arnulfo fc7882b0ee Scale Composition: scale the Point of Interest depth of a camera or light under a 2D parent
Otherwise the eye moves back while the point it looks at stays put, and the
view direction changes.
2026-10-30 00:44:58 +01:00
Marco Arnulfo 1f693acea6 Scale Composition: walk the parent chain through cameras and lights, and give Z its own Scale speed
The renderer applies every ancestor's transform, so a scaled null above a
camera already carries the camera's children. A Scale key with one shared
ease gets a separate Z ease before its speed is scaled.
2026-10-30 00:44:58 +01:00
Marco Arnulfo 76e02f88b7 Scale Composition: keep the ease of depth moves under 2D parents, and scale depth once through a 3D ancestor
Position speeds stretch with the path's direction at each key and Scale's Z
speed with the factor, so the ease keeps its shape. A 3D layer under a 2D
parent scales its own Z only when no 3D ancestor's Scale already carries it.
2026-10-30 00:44:58 +01:00
Marco Arnulfo 76369bc10a Scale Composition: Z of 3D layers under 2D parents, percentage guides left alone, region of interest scaled
A 2D parent's Scale carries no depth, so its 3D children scale their own Z.
Percentage guides keep their percent exactly instead of drifting by rounding.
Tests now check the specific errors and cover a layer parented to a camera.
2026-10-30 00:44:58 +01:00
Marco Arnulfo 4aaba7c3bf Scale Composition: comp.scale resizes a comp and scales its layers, keys, cameras and guides by one factor
Like After Effects' File > Scripts > Scale Composition.jsx: a factor, or a new
width or height that keeps the aspect ratio, in one undo step. Layers whose
parent has a Scale follow that parent; nested precomps and expressions are
left as they are. No dialog yet.

Refs #2208
2026-10-30 00:44:58 +01:00
Marco Arnulfo 09a93b6d62 Layer Styles: changed Blending Options outlive the last style and only pixel-changing styles block a clip export (#1389) 2026-10-30 00:44:57 +01:00
Marco Arnulfo cc94fccda5 Layer Styles: Blending Options can be edited on a layer with no styles (#1389) 2026-10-30 00:44:57 +01:00
bflatasticandClaude Opus 5.5 e806f0d34e i18n: the menu test expects German's own Can't Undo wording now that it has one
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 06:43:12 +07:00
bflatasticandClaude Opus 5.5 cf912e1f61 Automation: the file-parameter audit counts RUNS_SCRIPTS as classified
file.runScript and script.run moved from REFUSED to RUNS_SCRIPTS, which
check_command refuses too; the audit test now looks there as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 06:42:54 +07:00
erythrofr 63ec5f2aad Export: apply crop once when calculating resize dimensions
Calculate frame_size from the original rendered dimensions and effective
render scale before cropping, so locked-aspect resize does not apply the
crop margins a second time in its dimension calculation.

Add dimension and decoded-PNG regressions for crop, resize, padding, scaled
ROI, both interpolation qualities, and zero or extreme requested sizes.

AI assistance: OpenAI Codex (GPT-6).
2026-10-30 00:39:56 +01:00
tylerjenningsw d91b14db54 Viewer: a precomp's undecodable proxy has its notice with Collapse on, now that a proxy keeps the flattened path (#1701) 2026-10-29 19:30:31 -04:00
bflatasticandClaude Opus 5.5 4a4aa28184 Render Queue: elapsed and remaining time tick between frames (#2593)
The job reports its times when a frame finishes, so with slow frames the
Current Render strip held the same Est. Remain long enough to look
stalled, then jumped. Between reports both times now count on from the
last one, as a clock does (remaining never below zero, a finished job
stands still), and the panel repaints twice a second while rendering.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 06:27:58 +07:00
BFlat a8d83b9717 Merge pull request #2619 from storytold/fix/2592-mp4-edit-duration
Import: an MP4 lasts as long as its video edit list shows (#2592)
2026-10-30 06:19:18 +07:00
Krueels 73817dc3f0 #986: confine Blender exports and trim generated header 2026-10-29 20:15:25 -03:00
Krueels e2b56f1ba5 #986: remove personal credit from generated Blender scripts 2026-10-29 20:15:25 -03:00
Krueels dcbb806139 #986: add Blender scene export for 3D Camera Tracker 2026-10-29 20:15:25 -03:00
Jason LukerandClaude Opus 5.5 9eb127d223 UI test: compare the viewer's GPU frame only once the compositor is attached
With the compositor built on a worker thread, the parity test's first
frame could be composited on the CPU while the build ran. Frame keys
don't name the compositor (by design: the disk cache serves frames from
either), so after the hand-over the viewer could keep showing that CPU
frame, and the GPU-vs-CPU comparison would pass comparing the CPU with
itself. The test now waits for the compositor, then opens the project
and sets the time, so every frame it compares was requested with the
compositor attached.

(`viewer_on_gpu()` can't tell here: on the desktop GPU frames are read
back into CPU images, and only the browser draws them from their texture.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 16:10:41 -07:00
Jason LukerandClaude Opus 5.5 83bb74d21c UI: "Preparing the GPU compositor…" stays until the compositor is attached
The status line is the toast that clears itself after 5 s, so the
preparing notice went blank while the viewer was still on the CPU for the
rest of a cold-cache build (tens of seconds), though `init_gpu` says the
status bar tells the user so. draw_toast now leaves that one status up
while `gpu_initializing()`; `finish_gpu_build` clears it when the
compositor lands, and the worker's repaint brings that frame, so the
toast doesn't tick meanwhile. A click still dismisses it; every other
status clears as before.

Test: with the build held on its gate, 30 more steps (7.5 s) leave the
status as it was; before this change it was empty by then.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 16:10:41 -07:00
bflatastic 2e92ddaaf6 Merge main into #1340; add Polish to main's Option-based undo/redo wording table, keep main's recounted rows and the Polish row in localization-parity.md 2026-10-30 06:08:35 +07:00
bflatastic 72a2c4a1bc Merge main into #1439; Preview checkbox moved into main's split comp_settings::show (tab_body), gradient editor keeps main's pub(super) to_color32 2026-10-30 06:03:52 +07:00
bflatastic 0039081952 Merge main into #2567; keep both test modules, and convert four layer stacks main's new render tests assign as Vec<Layer> with .into() 2026-10-30 06:01:06 +07:00
bflatasticandClaude Opus 5.5 883171eece Scripts: FootageItem.replace() swaps in one file, as in After Effects
Since #2107, Replace Footage keeps an item's kind by default, so
replace() on a sequence item brought the new file's whole numbered run.
In After Effects, replace() swaps in the one file and replaceWithSequence()
brings a run; replace() now asks for exactly that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 05:59:40 +07:00
bflatastic 8e3324eefa Merge main into #2615; file.import's parameter doc: main's sequence wording plus the PR's newComp option 2026-10-30 05:59:29 +07:00
tylerjenningsw 852f98d6a5 Merge enhance/filmcraft-avi-backend into enhance/avi-import
# Conflicts:
#	crates/export/tests/it/movie_bytes.rs
2026-10-29 18:58:57 -04:00
bflatasticandClaude Opus 5.5 4bdb68a812 Import: an MP4 lasts as long as its video edit list shows (#2592)
The reader reports a track's media duration (mdhd). For H.264 with
B-frames that runs past the last shown frame by the encoder delay the
edit list trims, so a 75-frame 25 fps clip imported as 76 frames / 3.04 s.
The footage's duration now follows the video track's edit list when it
is shorter (never longer; a delayed start keeps the reader's duration),
as the frame rate is already corrected from the header.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 05:54:16 +07:00
bflatastic 56fde5c3d6 Merge main into #1279; effects/lib.rs: keep the PR's Buf::grow_left_top/align beside main's budgeted Buf::pad, and put cover_plan's doc comment back on cover_plan (the PR's new items had split it off) 2026-10-30 05:53:43 +07: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 bc868c7138 Merge main into #1581; keep main's toolbar/Preview rows and the PR's rows in both Chinese panel catalogs, tr() the tab labels in main's comp_settings::show (tab_body split) 2026-10-30 05:51:32 +07:00
Camille Moine 8ac2dec42a Keyframes: offer Unmute Keyframes in the Animation menu
The menu only carried Mute, so unmuting meant the timeline's context menu.
Add the second row bound to `keys.setMuted {"muted":false}`, its translation
in the ten catalogs, and a test that runs both rows through Session::execute
with undo and redo.
2026-10-29 23:51:04 +01:00
Camille Moine 047ffbaba5 Keyframes: mute keyframes without deleting them (#1894)
Add a muted flag to Keyframe. Muted keys stay in the Timeline and Graph Editor (dimmed, selectable and movable) but evaluation skips them, so the active neighbours interpolate as if they were not there; auto-Bezier and eases use the active neighbours. When every key is muted the property falls back to its static value.\n\nkeys.setMuted {muted} mutes or unmutes the selected keys in one undo step. The Timeline context menu offers Mute/Unmute Keyframes and the Animation menu has Mute Keyframes. Muted keys have no Bezier handles and motion-path points are dimmed.\n\nLottie export omits muted keys (with a warning) because Lottie has no mute state; scripting keeps seeing them in numKeys/key().\n\nTests: keyframe evaluation (linear, auto-Bezier spatial, all muted), serialization and value replacement, engine command + undo, Lottie export.
2026-10-29 23:51:04 +01:00
tylerjenningsw c9a91d9ddf Merge remote-tracking branch 'origin/main' into pr1736-avi-backend 2026-10-29 18:49:01 -04:00
bflatastic c53dd7f0a0 Merge main into #2600; clean 2026-10-30 05:46:55 +07:00
bflatastic d7ab6bc11b Merge main into #1387; clean 2026-10-30 05:46:52 +07:00
bflatastic dfa5d9eeea Merge main into #1784; main already maps ru/fr/de and has Russian undo/redo: keep main's supported() and history table, add only the French and German undo/redo wording, test Russian with main's colon form 2026-10-30 05:44:55 +07:00
tylerjenningsw aecdffecb0 Media: read the LATM configuration only when FilmCraft plays that MPEG stream, not an ADTS one before it (#1701) 2026-10-29 18:44:34 -04:00
tylerjenningsw 800b555e51 Media: read the AAC configuration of the MP4 or Matroska track FilmCraft plays, not an empty one before it (#1701) 2026-10-29 18:44:05 -04:00
Jason LukerandClaude Fable 5.1 57adb3e3ed UI: open the window before the GPU compositor is built
`init_gpu` built the compositor on the UI thread in the first frame, and eframe shows the window
only after that frame has painted. The compositor's ~235 compute pipelines take tens of seconds to
compile on a cold Metal shader cache (first launch, after an OS update, after an update that touched
a shader): about 40 s of no window at all, measured 39–41 s on an M2 Max.

On the desktop the compositor is now built on a worker thread (`gpu-compositor`), inside the same
`catch_unwind`, and attached when its result arrives; the worker requests a repaint, so nothing
polls. Until then the viewer composites on the CPU, as it already does without a GPU, and the
status line and `help.systemInfo` say "Preparing the GPU compositor…". A device failure during the
build discards the result; a thread that can't be spawned, and the browser, build in place as
before. `Hooks::before_gpu_build` lets tests hold or fail the build; `gpu_initializing()` exposes
the pending state.

Measured (release, cold cache, A/B interleaved): time to the window 39.0/40.9 s → 1.9/0.5 s, and
the control channel answers right after; with a heavy project opened at launch 38.3 s → 0.64 s
(first frame 88 ms after the app was created). Warm: 776 → 355 ms. The compile itself is not
faster; #1705 (effect kernels on first use) is the complementary half.

Tests: the interface draws, composites a CPU frame and reports the preparing state while the build
is held on a gate, then attaches the compositor; a build that panics leaves the viewer on the CPU
with the reason; the existing GPU/CPU parity test waits for the asynchronous hand-over.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-29 15:43:42 -07:00