7 Commits
Author SHA1 Message Date
liangforstudyandClaude Opus 5.5 d73196f3f7 Help menu: a dialog keeps the address when no browser opens; shorter hints
When the web browser can't be opened, a dialog now shows the reason and
the address in a read-only field you can select from, with Copy, and
stays until Close or Escape. The status bar message it replaces cleared
itself after 8 seconds and claimed the address was on the clipboard,
which egui can't confirm (a failed copy is only logged), so the address
could be gone after switching to the browser window.

The Help hints lose their "(no web page)" suffix, and System
Compatibility Report's hint is just "Shows a report on this computer."

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 11:21:44 +08:00
liangforstudyandClaude Opus 5.5 3f5d4385dd Help menu: say where each item goes; keep the address when no browser opens
Hovering a Help menu item now tells you what it does: the links (ArtCraft
Discord, website, app page, GitHub, Report an Issue, FilmCraft Help) show
"Opens in your web browser: <address>", and Reveal Log Files, System
Compatibility Report and About FilmCraft say they stay in FilmCraft (no
web page).

When the host can't open a browser, the click was only logged. Now the
address is copied to the clipboard and the status bar names the reason
and the address.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 10:25:53 +08:00
liangforstudyandClaude Opus 5.5 dd69fc594e dialogs: drag them by the title bar (open centred, no longer anchored)
About FilmCraft, System Compatibility Report, Sequence Settings and the
other modal dialogs were placed with `Window::anchor(CENTER_CENTER)`,
and egui makes anchored windows immovable, so dragging the title bar did
nothing. They now open at the centre of the app window through a
centre pivot and `default_pos` (`widgets::dialog_center`, or the
`CenteredDialog::centered` shorthand on one-line chains) and can be
moved like any other window.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 10:07:49 +08:00
liangforstudyandClaude Opus 5.5 979e9a0c56 #402: animated GIF and APNG import as clips, with transparency
APNG and animated GIF files opened as stills showing only their first
frame. They now open as movie clips (crates/media/src/animated.rs):

- every frame is decoded and composited onto the full canvas by the
  image crate (APNG blend/dispose ops, GIF disposal), keeping alpha
- each frame lasts its own delay; GIF delays <= 10 ms play as 100 ms
  and APNG delays < 10 ms as 10 ms, as browsers do
- consecutive identical frames are merged; the clip is one pass of the
  animation and its timebase is the most common frame length
- hostile input: at most 10,000 frames / 1 GiB of decoded pictures; a
  damaged frame ends the clip at the frames before it; files with one
  frame (or none that decode) still open as stills, as before

Tests: media unit tests (timing, transparency, merging, single-frame
files stay stills, truncated/bit-flipped files never panic) and an
engine test that imports an animated GIF and reopens it from a saved
project.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QkQ2PDrNFjs9Vm8T44tdjA
2026-10-11 10:44:15 +08:00
liangforstudyandClaude Opus 5.5 4f8dcdf587 #402: WebM transparency (VP9 alpha in BlockAdditions)
A WebM VP9 track with AlphaMode 1 stores its alpha as a second, independently coded VP9
stream in each block's BlockAdditional (BlockAddID 1). The Matroska reader detected
AlphaMode (has_alpha was true) but never read the additions, so transparent areas
rendered black.

- matroska: BlockGroups' BlockAdditions are parsed; the BlockAdditional with ID 1 of an
  unlaced block is kept as Sample::addition, read with MkvFile::read_sample_addition.
- codecs: a WebM VP9 track with AlphaMode and additions gets an AlphaDecoder
  (webm_alpha.rs): it decodes each sample's alpha frame with a second software VP9
  decoder and attaches its luma plane (full range, converted to the picture's depth)
  as the frame's alpha. After a seek the alpha decoder resynchronises from the nearest
  alpha key frame. Colour pictures are held until their alpha picture is out, since the
  two decoders may return pictures after different calls. A missing or undecodable alpha
  frame leaves that picture opaque; it never fails the colour decode.

Tests: vp9_webm_alpha_layer_matches_libvpx (frames out of order and forward, colour and
alpha exact against ffmpeg's libvpx decode; fails before: no alpha plane; passed 200 of
200 runs with four in parallel), set_alpha unit tests.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Qq8BK1LmohzE1ga4NgAdWM
2026-10-10 17:40:58 +08:00
liangforstudyandClaude Opus 5.5 fcaa6bbdf4 #484: Enable flips each selected clip on its own
With one enabled and one disabled clip selected, Clip > Enable (Shift+E) set every
selected clip to the same state: the first press enabled both, the next disabled both.
Premiere flips each clip separately (confirmed by the reporter in #484), so a mixed
selection swaps. Each clip in the selection (with its linked clips) now flips on its
own; a clip named twice in the parameters still flips once.

Test: enable_flips_each_selected_clip (fails before the fix: the mixed press left
both clips enabled).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Qq8BK1LmohzE1ga4NgAdWM
2026-10-10 09:23:38 +08:00
liangforstudyandClaude Opus 5.5 72e3eeb5de Project files: each sequence reopens with its playhead where it was left
The engine already keeps one playhead per sequence while a project is open, and the
project file's view already stores each sequence's zoom, scroll and track heights, but
not its playhead: after saving and reopening, every sequence started at zero.

ProjectView gains `playheads` (sequence id -> Tick), written beside the tabs and views
and restored with them when "Restore open sequences when opening projects" is on. Files
written before it have none and open as they did. Values from a file are not trusted:
ids that are not sequences are dropped, playheads are clamped to 0..ProjectView::MAX_PLAYHEAD
and snapped to a frame of their sequence.

Tests: each_sequence_reopens_with_its_playhead_where_it_was_left (fails without the
fix), hostile playheads in a_damaged_view_in_a_project_file_is_cleaned_up_or_ignored,
a deleted sequence's playhead is not written, and the format round trip carries it.

Also adds my contributor credit entry (people.toml).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Qq8BK1LmohzE1ga4NgAdWM
2026-10-10 05:22:05 +08:00