Commit Graph
1046 Commits
Author SHA1 Message Date
Claude e625ef3bef Merge pull request #567 from Limestudio90/import-animated-gifs
# Conflicts:
#	crates/media/src/pool.rs
2026-10-10 12:50:00 +00:00
Claude 9093fd1804 Merge pull request #507 from daijro/perf/footage-playback 2026-10-10 12:49:56 +00:00
Claude 0df89c84ec Merge pull request #579 from KattKnight/windows-test-fixes 2026-10-10 12:49:56 +00:00
Claude a12242c806 Format the merged community fixes (#561-#566 follow-up)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 12:49:52 +00:00
Claude 20ac6189bc Scripting: Property.selected=false deselects mask and effect groups too (#566 follow-up)
prop.deselect resolved its uid through prop_ref, which only finds leaf
properties, so mask.selected=false threw. Resolve it as prop.select does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 12:49:52 +00:00
Claude 45897f0aaf Merge pull request #566 from Ni-zav/fix/548-property-selected-false-s20261010T084400Z-a6e9
# Conflicts:
#	crates/script/src/tests.rs
2026-10-10 12:49:18 +00:00
Claude b96628e154 Merge pull request #565 from Ni-zav/fix/541-locked-resize-height-s20261010T084400Z-a6e9
# Conflicts:
#	crates/engine/src/rq_tests.rs
2026-10-10 12:49:18 +00:00
Claude f27c834196 Merge pull request #451 from sanyamsingh001/fix/cli-template-rendering 2026-10-10 12:49:17 +00:00
Claude 6eb386002e Merge pull request #471 from sanyamsingh001/fix/parenting-3d-position 2026-10-10 12:49:17 +00:00
Claude ab474485b7 Merge pull request #497 from sanyamsingh001/fix/time-boundaries-cancellation 2026-10-10 12:49:17 +00:00
Claude f6d130ac38 Merge pull request #512 from sanyamsingh001/fix/settings-info-return 2026-10-10 12:49:17 +00:00
Claude 21a9486d8a Merge pull request #522 from sanyamsingh001/fix/property-key-time-bases 2026-10-10 12:49:17 +00:00
Claude cff0cf390d Merge pull request #524 from sanyamsingh001/fix/key-attribute-selection-order 2026-10-10 12:49:17 +00:00
Claude 1eb154c2d9 Merge pull request #556 from sanyamsingh001/fix/export-audio-sample-positions 2026-10-10 12:49:16 +00:00
Claude f001b8e187 Merge pull request #573 from sanyamsingh001/fix/dock-tab-identity 2026-10-10 12:49:16 +00:00
Claude c7b75a04d7 Merge pull request #555 from LloydNicholson/fix/addsolid-pixel-aspect
# Conflicts:
#	crates/script/src/tests.rs
2026-10-10 12:49:11 +00:00
Claude ead13d81d4 Merge pull request #559 from Ni-zav/fix/544-project-item-deselect-s20261010T084400Z-a6e9
# Conflicts:
#	crates/script/src/tests.rs
2026-10-10 12:49:11 +00:00
Claude c226cd839a Merge pull request #560 from Ni-zav/fix/549-textdocument-baseline-getters-s20261010T084400Z-a6e9 2026-10-10 12:49:11 +00:00
Claude 2e92dcad5f Merge pull request #561 from Ni-zav/fix/545-expression-baseline-getters-s20261010T084400Z-a6e9 2026-10-10 12:49:11 +00:00
Claude f546bf9d9e Merge pull request #562 from Ni-zav/fix/528-open-xml-project-on-launch-s20261010T084400Z-a6e9 2026-10-10 12:49:10 +00:00
Claude 380cb16369 Merge pull request #564 from Ni-zav/fix/542-render-queue-settings-template-s20261010T084400Z-a6e9 2026-10-10 12:49:10 +00:00
Claude cd5441cd1a Merge pull request #563 from Ni-zav/fix/537-validate-new-text-position-s20261010T084400Z-a6e9 2026-10-10 12:49:10 +00:00
sanyamsingh001andCodex b0cceb1723 G2: preserve shown panels when removing inactive tabs
Co-authored-by: Codex <codex@openai.com>
2026-10-10 21:51:18 +10:00
KattandClaude Opus 5.5 a650e6c21d Tests: four failures on Windows (autosave paths, GPU viewer adapter, audio preview race)
- automation / cli autosave restart tests: the MCP instructions embed the
  auto-save state as JSON, so a Windows path's backslashes are escaped there;
  look for the JSON form of the path.
- ui_gpu: egui_kittest prefers a CPU adapter, which on Windows is WARP on
  DirectX 12, where FXC fails to compile the compositor's `pointwise` kernel
  ("compilation aborted unexpectedly"), so the viewer stayed on the CPU and
  the test failed before comparing anything. Build the harness on the adapter
  the headless compositor picked (falling back to egui_kittest's choice).
- ui_audio_scrub (#103 test): with a fixed 2 s comp, a machine with many
  render threads cached the whole preview before the first step, so the sound
  rightly started at once and no silent frame was counted (3 of 24 runs
  failed with 8 copies in parallel). Size the comp to four times the frames
  playback requests per step, so caching takes at least four steps (0 of 24).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:36:52 +05:30
Limestudio90andClaude Sonnet 5.5 bfbdadd34a Import animated GIFs as movies
GIFs went through the still-image path, so an animated GIF came in as a
single frame with zero duration. A GIF with two or more frames is now
probed as a movie: its frame rate is chosen so every per-frame delay is
a whole number of frames (uneven timing is kept exactly), delays of 0
or 1 hundredths count as 10 like in browsers, and the pool decodes the
frame shown at the requested time. A single-frame GIF stays a still.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-10 11:38:00 +02:00
Nigel Ihza Firdausy 4bc619b010 fix(script): deselect individual properties via Property.selected=false (#548) 2026-10-10 15:58:22 +07:00
Nigel Ihza Firdausy c822fcdff3 fix(render-queue): honor height-only locked resize edits (#541) 2026-10-10 15:57:09 +07:00
Nigel Ihza Firdausy 65bf4702fd fix(render-queue): distinguish settings template on queue creation (#542) 2026-10-10 15:55:02 +07:00
Nigel Ihza Firdausy 9d10d84dee fix(engine): validate text layer position coordinates (#537) 2026-10-10 15:53:14 +07:00
Nigel Ihza Firdausy da131fcd57 fix(app): open .ecprojx project copies passed on the command line (#528) 2026-10-10 15:51:14 +07:00
Nigel Ihza Firdausy 6ed3d210fb fix(expr): reflect pending TextStyle baseline edits in expression getters (#545) 2026-10-10 15:50:18 +07:00
Nigel Ihza Firdausy 4f6256c486 fix(script): keep pending TextDocument baseline reads in sync (#549) 2026-10-10 15:49:32 +07:00
Nigel Ihza Firdausy d0489021b5 fix(script): make Item.selected=false deselect only that item (#544) 2026-10-10 15:47:58 +07:00
sanyamsingh001andCodex 34b894a249 G3: preserve exported audio sample positions
Co-authored-by: Codex <codex@openai.com>
2026-10-10 17:55:50 +10:00
lloydandClaude Opus 5.5 6843510a25 Scripting: layers.addSolid keeps the requested pixel aspect (#543)
LayerCollection.addSolid dropped its fifth argument, so layer.newSolid
fell back to the composition's pixel aspect. The wrapper now passes
pixelAspect through; layer.newSolid already validates it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:42:07 +02:00
sanyamsingh001andCodex 8eb77a7d1e G2: preserve keyframe selection during attribute edits
Co-authored-by: Codex <codex@openai.com>
2026-10-10 13:22:32 +10:00
sanyamsingh001andCodex a7a6295bb0 Issue 257: support explicit keyframe time bases
Co-authored-by: Codex <codex@openai.com>
2026-10-10 11:12:14 +10:00
Brandon ThomasandClaude Opus 5.5 813c7c4650 Bump version to 0.7.0 (from 0.6.0) for release; refresh contributors
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.7.0
2026-10-09 21:02:08 -04:00
sanyamsingh001andCodex e4ca1e919a G2: return to Settings after dismissing GPU Information
Preserve pending preference edits through the existing OK and Cancel actions.

Co-authored-by: Codex <codex@openai.com>
2026-10-10 08:46:03 +10:00
daijroandClaude Opus 5.5 ddfa566d7d Render: 8 and 16 bpc quantisation rounds with floor in the browser
Cause: quantize_px rounded with `(v + 0.5) as u32 as f32`. Converting back
from u32 is several instructions in V8's wasm code on x86 (no unsigned
conversion), so quantising a 1080p layer took about 15 ms in the browser:
every 8/16 bpc layer is quantised after its source and every effect, and
the CPU compositor quantises the comp after every layer.

Fix: round_half_up uses floor in wasm (one instruction there) and keeps the
integer conversion elsewhere (x86-64's baseline has no floor instruction,
where floor is slower). The values are the same: both round non-negative
values half up. About 1.5x faster quantising in the browser (15 -> 10 ms
per 1080p layer in a wasm micro-benchmark), unchanged on the desktop.

Tests: color::tests::rounding_forms_agree: both forms agree on 0..=levels
in sixteenths (exact halves included) and on 100 001 products, at 8 and
16 bpc.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 16:44:49 -05:00
daijroandClaude Opus 5.5 74b151cedc Footage: reduced-resolution renders get movie frames converted at their size
Cause: at Half, Third and Quarter resolution (the viewer's Auto resolution
in most windows) every movie frame was converted from Y'CbCr to f32 RGBA at
full size and then resampled down. In the browser (wasm, one thread) that
was about 8 ms converting a 1080p frame, 6 ms resampling it and 2 ms
zeroing a 33 MB buffer, per layer and frame, for a frame shown at a
quarter or a ninth of its pixels; the footage frame cache held the
full-size frames.

Fix: FootageSource::frame_at_size asks for a frame shown at a given size
(default: the full frame, as before). The renderer asks for it where it
resampled footage (below 3/4 scale; not for proxies, fields or Interpret
Footage's pixel options, which need the full frame). MediaPool makes opaque
4:2:0 movie frames of the footage's own size there: it box-filters them to
half size in Y'CbCr before converting (each 2x2 block of luma, and the
[1 6 1]/8 neighbourhood of its chroma sample, which is the mean of the
upsampled chroma its pixels get), resamples the rest of the way and caches
the result per size. Conversion is linear until colours clip, so this is
the RGB box filter resample starts with, except in blocks where some
colours clip. Other frames convert at full size and resample as before.
In the browser the conversion and resampling take about 4 ms instead of
16. Docs (architecture).

Tests:
- convert::scaled_conversion_matches_resampling_the_converted_frame: half,
  third, quarter and odd sizes of an unclipped 4:2:0 frame are within 1e-5
  of resampling the converted frame; larger sizes, odd frame sizes and
  4:4:4 convert at full size.
- tests_footage_size::reduced_renders_take_footage_resampled_by_the_source:
  a source that resamples frames itself renders the same frames as one
  that doesn't, at 8 and 32 bpc and every resolution, and is asked only
  below 3/4 scale, and not with Invert Alpha.
- footage::h264_frames_at_reduced_sizes (ffmpeg fixture): 1080p H.264
  testsrc2 frames, whose saturated colours clip, at 960x540, 640x360,
  480x270 and 323x182 are 58-62 dB from the resampled full frames, and
  are cached per size.
- convert's ignored 1080p bench also times the conversion at a third.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 16:44:49 -05:00
daijroandClaude Opus 5.5 2ccc66e73b Web: the layer and footage caches stay small enough for eight stacked clips
Cause: the browser build kept the desktop's cache budgets (1 GB layer
cache, 1 GB footage frame cache) inside the page's memory, which wasm32
caps at 4 GiB. FilmCraft's decoders keep up to 384 MB of decoded frames
per open movie beside them, so a comp of eight stacked 1080p H.264 clips
grew the page by about 55 MB/s while playing and ran it out of memory
after about 50 s ("unreachable": a failed allocation).

Fix: in the browser Prefs::cache_budgets keeps the Layer Cache within
512 MB and the Footage Frame Cache within 256 MB (WEB_LAYER_CACHE,
WEB_MEDIA_CACHE); smaller settings and the desktop are unchanged, and
the RAM preview keeps its budget. Docs (web, preferences) say so.

Tests: tests_m145::web_cache_budgets_leave_room_for_the_decoders: with
4 GB settings the web budgets are the caps, the desktop's are the
settings, and smaller settings stay as they are.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 16:44:15 -05:00
sanyamsingh001andCodex c37b88602f G3: fix frame-rate boundaries and bounded timecode arithmetic
Preserve relative MIN-field cancellation with direct saturating addition and subtraction.

Co-authored-by: Codex <codex@openai.com>
2026-10-10 06:40:02 +10:00
sanyamsingh001andCodex cac47626f3 fix(engine): preserve supported 3D parenting compensation (#348)
Convert Position values and spatial tangents into the new parent space.
Preserve supported static Orientation and Scale in constant uniform
parent spaces, and convert spatial Position ease speeds for uniform
transforms. Retain the compensation and Undo/Redo regressions.

Refs #348.

Co-authored-by: Codex <codex@openai.com>
2026-10-10 04:51:15 +10:00
BFlat 30aaddf7c2 Merge pull request #459 from storytold/fix/394-408-arabic-flac
Arabic, Hebrew, Indic and Thai names; FLAC preview opens once and off the UI thread (#394, #408)
2026-10-10 01:04:24 +07:00
bflatasticandClaude Opus 5.5 09a5dc357a Audio: a FLAC opens once and off the UI thread; conforming is bounded (#408)
The freeze and quit during a FLAC preview did not reproduce on current
main (Windows 11): a 4-minute stereo and a 10-minute 24-bit 6-channel
96 kHz FLAC played through a RAM preview with a real-time audio pull,
after trimming and zooming, with no stall, no growing queue and memory
bounded by the RAM preview budget; 150 cpal output start/stop cycles
ran clean. Three defects in that path were found and fixed:

- FilmCraft decodes FLAC, MP3, Ogg and AIFF files whole when they are
  opened (8 s and 1.4 GB for the 10-minute 6-channel file). MediaPool
  opened a file outside its lock, so every caller asking before the
  first open finished decoded the whole file too: a preview's frame
  workers, audio feeder, conform and waveform threads at once (8 reads
  at once: 8 decodes). Each path now opens once; the others wait for it.
- AudioPlayback::start mixed its first 50 ms on the calling (UI)
  thread, so the first read of such a file froze the UI for the whole
  decode (audio-only previews start the sound right away). All mixing
  is on the feeder thread now; the device plays silence until the first
  block arrives, and the clock (frames actually played) waits for it.
- Conforming (Settings > Disk > Conformed Audio Folder, on by default)
  held the whole conformed track in memory before writing it, sized by
  the footage duration from the file's header: a header claiming a
  month of audio aborted the app on a failed 995 GB allocation. The
  conformed file is now written a chunk at a time, and footage longer
  than 24 hours is read from its decoder instead of conformed.

Tests: media concurrent_first_reads_open_a_file_once (8 threads: 8
opens before, 1 now; PoolStats::opened), pool
a_header_claiming_a_month_of_audio_is_not_conformed (aborted before),
ui-egui audio starting_audio_does_not_wait_for_slow_footage (start took
the footage's 2 s before), conformed_flac_audio_reads_back_like_the_
decoder, and the robustness test flac_audio_of_any_shape_reads_in_
device_blocks (2 minutes of 24-bit 6-channel 96 kHz, mono 8 kHz,
11.025 kHz, 192 kHz and 8-channel FLAC read in 1024-frame blocks at
48 kHz through and past the end: level, silence after the end, opened
once). FLAC fixtures come from ffmpeg (skipped without it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:53:21 +07:00
bflatasticandClaude Opus 5.5 98a6a3a041 UI: Arabic, Hebrew, Indic and Thai names can be typed and are drawn (#394)
Cause: two things kept Arabic out of a layer name on Windows.
- Windows switches the keyboard layout with Alt+Shift. Releasing Shift
  before Alt left Alt held alone, and the in-window menu bar (#279)
  counted the release as an Alt tap: it took the keyboard focus, the
  rename field closed, and the letters typed next were swallowed by the
  menu bar. The Project panel's rename field lost them the same way.
- The UI fonts are Inter plus the CJK system fallbacks, so Arabic,
  Hebrew, Indic and Thai names that did arrive (pasted, or from a
  project) showed as missing-glyph boxes.

Fix:
- An Alt tap only counts when Alt went down with no other modifier
  held, so Alt+Shift in either release order is no tap; a plain Alt tap
  still focuses the menu bar.
- The UI registers installed system faces for Arabic, Hebrew, Devanagari,
  Bengali, Gurmukhi, Gujarati, Tamil, Telugu, Kannada, Malayalam and Thai
  after the CJK ones, the same way (native only; the web build has no
  system fonts). A face covering several scripts is registered once
  (Segoe UI: Arabic and Hebrew; Nirmala UI: every Indic script).
- The text engine's fallback tries each script's plain platform families
  (Segoe UI, Nirmala UI, Leelawadee UI, Geeza Pro, Kohinoor, Noto…)
  before any covering face, so neither the UI nor a text layer gets a
  calligraphic face that merely sorts first.
- The Timeline's rename field registers `timeline.layer.<id>.nameEdit`.

egui 0.36 shapes each run of one face, so Arabic letters join and a word
reads right to left; it has no bidirectional layout, so the words of a
multi-word Arabic name (and mixed Arabic/Latin) still follow each other
left to right.

Tests: ui_inline_edit a_layout_switch_keeps_the_name_field_and_arabic_
names_are_kept (Alt+Shift both ways in the layer rename, Arabic typed and
stored; Hebrew/Devanagari/Thai in the Project panel; a plain Alt tap
still focuses File; failed before: the field closed), theme
installed_script_fallbacks_draw_arabic_hebrew_indic_and_thai_names
(failed before: replacement glyph for Arabic) and
arabic_words_are_joined_and_read_right_to_left, text
other_scripts_fall_back_to_a_plain_system_family and the script
classification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:53:21 +07:00
BFlat 921f0dbdbe Merge pull request #454 from storytold/fix/397-particle-world-camera
Effects: CC Particle World follows the comp camera (#397)
2026-10-10 00:52:58 +07:00
bflatasticandClaude Opus 5.5 923d978119 Effects: CC Particle World follows the comp camera (#397)
Cause: CC Particle World projected its particles through a fixed camera
(distance 2 layer widths, looking at the layer centre) and never asked the
host for the comp camera, so moving or orbiting a camera layer left the
particles flat on the layer. It also had no Extras > Effect Camera. Separately,
the layer cache key ignored the comp camera and lights, so the effects that
read them (Card Dance / Shatter / Card Wipe Comp Camera, First Comp Light,
Caustics) kept a stale frame when the camera, a light or the layer moved.

Fix: as the Cycore manual describes, Particle World sees its particles through
the comp's active camera layer when there is one (EffectHost::comp_scene now
says whether its camera is a camera layer's, CompScene::camera_layer), through
card3d's comp-camera projection (factored out of Card Dance as comp_proj, with
Proj::view for depth, size scale and screen velocity). Otherwise it uses the
new Extras > Effect Camera: Distance (2), Rotation X / Y / Z (0) and FOV (50)
orbit the world origin; FOV moves the camera so the origin's plane keeps the
scale Distance gives it, so the defaults reproduce the old fixed camera bit for
bit (golden hashes unchanged) and old projects render as before. The Effect
Camera is left out of the simulation cache key, so animating it doesn't
restart the simulation. The plan is shared, so the GPU compositor follows too.
The layer cache folds the comp scene into the key of layers running an effect
in effects::READS_COMP_SCENE (render::comp_scene is shared with the host).

Tests: sim particle_world_follows_the_comp_camera (panning a camera layer moves
the particles, zooming spreads them, the Effect Camera is ignored then, the
default view keeps the Effect Camera, cameras facing away / zero / NaN draw
nothing) and particle_world_effect_camera (missing params = defaults, rotation,
distance and FOV change the view, extremes stay finite, the sim key ignores the
camera); render particle_world_follows_the_comp_camera (a real camera layer
panned 40 px moves the particles left, and the cached render after the move
equals an uncached one: it failed with the old cache key); gpu
particle_world_through_the_comp_camera (CPU vs GPU at 8 / 32 bpc, full and
half resolution). particle_golden / sim_golden unchanged. effects.md
regenerated; parity.md and gaps.md describe the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:35:25 +07:00
BFlat e9032c5ce2 Merge pull request #452 from storytold/fix/363-property-pick-whip
Timeline: every property has a pick whip in the Parent & Link column (#363)
2026-10-10 00:34:54 +07:00