Commit Graph
86 Commits
Author SHA1 Message Date
Dylan M. Taylor b37811ec53 edit: look up higher-track transcript coverage by binary search (#4123) 2026-11-03 06:02:49 -05:00
5ed4952d43 Add shared custom colors and complete marker editing (#1435)
* M3: Add shared custom colors and complete marker editing

* #1435: refine native colors and range endpoint flags

Use the macOS Colors panel for custom label colors and reuse the established egui picker on other hosts. Preserve draft confirmation, exact sRGB values, native text shortcuts and project ownership. Compact the swatches and center the add control, split range glyphs across their endpoints, localize the new controls, protect newer marker edits from stale dialogs, and cover the behavior with rendered UI and hit-test regressions.

Co-authored-by: Codex <noreply@openai.com>

* #1435: preserve imported palettes and marker double-click ownership

Union saved OTIO palettes across timelines with deduplication, bounded capacity,
first-name preservation and explicit overflow warnings. Keep null authors
consistent with omitted fields, and consume marker double-clicks before the
work-area gesture so opening the editor does not alter project history.

Correct the CSV URL column and schema documentation. Add six regressions for
palette retention/capacity, author handling, and physical overlapping gestures.

Validation: full cargo xtask ci (3666 passed, 45 skipped), 42 rendered UI tests,
and strict workspace/all-target Clippy on Rust 1.99.1.

Co-authored-by: Codex <noreply@openai.com>

* #1435: retain OTIO swatch names and generator labels

Ignore orphan name entries when retaining saved palette names so input ordering
does not hide valid names after the first 64 entries. Keep names bounded by the
retained palette and preserve existing valid names.

Include generator preset labels alongside custom label colors in OTIO metadata.
Add regressions for orphan-prefixed name maps and three generator kinds with
preset/custom colors through actual export/import round trips.

Validation: both regressions failed before fixes; all 72 interchange tests and
full cargo xtask ci pass (3668 tests, 45 skipped), plus strict workspace/all-target
Clippy on Rust 1.99.1.

Co-authored-by: Codex <noreply@openai.com>

* #1435: preserve distinct OTIO generator item identity

Use exported FilmCraft item IDs for generator media identity so identical
content can retain distinct source names, labels and custom colors. Repeated
references to one source item still share a single imported media entry.

Preserve content-based fallback for missing or invalid item IDs. Cover black
video, bars and tone, and color mattes with distinct items/shared references,
plus legacy and malformed identity metadata.

Validation: distinct-generator regression failed before fix; legacy compatibility
passed. All 74 interchange tests and final full cargo xtask ci pass (3670 tests,
45 skipped); strict workspace/all-target Clippy also passes on Rust 1.99.1.

Co-authored-by: Codex <noreply@openai.com>

* #1435: align Edit Marker layout and add safe marker navigation

Give the editor a wide aligned form, larger Notes area, side action column,
and grouped palette with vertical marker types. Expand the Web Link field
with the form and keep actions accessible in small windows.

Previous/Next saves valid edits as one Undo step and stays with the original
sequence/source owner, including coincident markers. Invalid drafts stay open;
unchanged navigation and Done add no history. Keep native/shared color pickers,
Author, Notes, URL validation and immediate marker creation.

Validation: all 45 rendered sequence/marker UI tests pass, including five new
navigation/owner/validation/layout regressions. Native macOS layout, picker
Cancel and exact single-step Undo restoration verified. Full standard cargo
xtask ci passes 3675 tests (45 skipped), doctests and all remaining gates;
strict Rust 1.99.1 workspace/all-target Clippy also passes.

Co-authored-by: Codex <noreply@openai.com>

* #1435: refine Edit Marker proportions and action alignment

Narrow the dialog to 680 logical pixels and keep the core order Name,
Time/Duration, Notes, Color and marker type. Place Author after the type-specific
options as secondary metadata. Preserve our palette, custom picker and range controls.

Use consistently sized, centered rounded action buttons with a primary Done action.
Shorten Delete Marker to Delete and remove the navigation helper and unused translations.
Keep the existing navigation save/validation/Undo semantics and automation IDs.

Validation: all 45 rendered marker/sequence UI tests pass, including small-window
action accessibility. Actual macOS layout and no-op Previous/Next/Cancel verified.
Full standard cargo xtask ci passes 3675 tests (45 skipped), doctests, formatting,
Clippy, translations, layers, assets and 49 WASM crates. Strict Rust 1.99.1
workspace/all-target Clippy passes separately.

Co-authored-by: Codex <noreply@openai.com>

* #1435: tighten marker layout and validate text editing

Use a narrower aligned form with Author below Name, bounded scrolling Notes,
left-aligned colors, centered actions and an inline Web Link URL/open icon.
Remove the legacy Flash Cue choice while preserving imported marker types.

Constrain timecode typing/paste to complete numeric colon-separated fields,
validate drop-frame labels and frame bounds, and disable Done for invalid timing.
Preserve high-frame-rate timecodes and point-marker semantics when Duration is
unchecked. Route native/menu clipboard and text Undo commands to focused fields;
explicit engine commands retain project Undo and selection semantics.

Validation: standard cargo xtask ci passes 3679 tests (45 standard skips),
doctests, fmt, strict workspace/all-target Clippy, i18n, layers, 69 assets and
49 WASM crates. Also passed 48 rendered marker/sequence tests and strict Rust
1.99.1 Clippy. Actual macOS clipboard, bounded Notes, point save and exact Undo
were checked. Windows/Linux desktop interaction remains pending.

Co-authored-by: Codex <noreply@openai.com>

* M0: Wait for frame-worker recovery before asserting

Do not treat a nonempty request queue as proof of worker death in the
panic-recovery regression. Keep waiting for all injected faults and enough
post-fault completions, then drain the queue without adding more seeks.
Retain the exact fault-count, successful-recovery and empty-queue assertions
and bound the wait with a two-minute deadline.

The inherited test failed twice in independent fork CI. It did not reproduce
locally: baseline passed 20 normal and 10 delayed-report runs; the repair
passed 50 normal and 10 delayed-report runs. No product or marker UI changes.

Validation: standard cargo xtask ci passed all 4485 tests (52 standard skips),
doctests, formatting, strict workspace/all-target Clippy, i18n, layers,
69 assets and 49 WASM crates.

Assisted-by: OpenAI Codex

---------

Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <codex@openai.com>
2026-11-01 03:04:14 +01:00
aiongg a63eaa9b38 Merge PR #3582: Trim: a graphic, still or adjustment layer extends from its left edge 2026-10-31 02:15:56 +00:00
aiongg 5d1a49d3f6 Merge PR #2921: edit: ripple sync-locked captions with deleted items (#2873) 2026-10-31 02:15:20 +00:00
aiongg d3aaf932ff Merge PR #1623: timeline: drop transitions when an edit moves their clips apart
# Conflicts:
#	crates/edit/src/tests.rs
2026-10-31 02:11:32 +00:00
marshiyar eddbf83d7e edit: slip on frame-held no-length media has no floor either (#3367)
Problem: slip checked frame hold before media length, so a graphic stretched left (source_in below 0) and then frame-held got the frame-hold floor of 0: slipping it 1 frame jumped it to 0.

Solution: slip checks media with no length first, as head() does, so a frame-held graphic has no floor either.

Tested with a_slip_moves_a_frame_held_stretched_graphic_by_what_was_asked, which fails without the change.
2026-10-30 03:03:09 -07:00
marshiyar e7850ce21e edit: slip and frame-held clips follow the no-length rule (#3367)
Problem: a graphic stretched left has a source_in below 0. slip still floored source_in at 0, so slipping it 1 frame jumped it back to 0. head() checked frame hold before the no-length rule, so a frame-held graphic with a negative source_in turned into a positive limit and a roll moved the cut the wrong way.

Solution: head() checks media with no length first, then frame hold. slip has no floor for media with no length, frame holds and real media keep theirs.

Tested with a_slip_moves_a_stretched_graphic_by_what_was_asked and a_roll_extends_a_frame_held_graphic, which fail without the change.
2026-10-30 01:48:36 -07:00
marshiyar 8d22cc784e edit: media with no length has no head limit (#3367)
Problem: head() treated graphics, stills and adjustment layers like video. Their source_in starts at 0, so head() answered 0 and trim, roll and slide could not extend them earlier from their left edge.

Solution: media with no length now has no head limit, like its tail. Its source_in may go below 0, so keyframes keep their timeline positions and extending then shortening round-trips.

Tested with a_graphic_extends_from_its_left_edge, a_graphic_ripple_extends_from_its_left_edge, a_roll_extends_a_graphic_from_its_left_edge and a_slide_extends_a_graphic_from_its_left_edge, which fail without the change.

Fixes #3367
2026-10-30 01:20:31 -07:00
05502a4b90 Timeline: grouped clips select together (#3522)
* engine: grouped clips select together

clip.group stored a group id on each item, but nothing read it: clicking a
grouped clip selected only that clip (and its linked partners), so groups
never moved, trimmed or deleted together.

timeline.select now expands the selection with with_groups_and_links: group
members and linked partners, repeated until nothing more joins, so clicking
the audio partner of a grouped video clip also brings the group along.
Alt-click (linked: false) still picks a single member.

Adds grouped_clips_select_together.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjftakwWmCfps6q4KGGnDe

* engine: copies of a group get a group of their own

Paste, Option-drag copy (edit::copy_items), Make Subsequence and placing
a sequence's clips gave each copy a fresh clip and link id but kept the
original's group id. The copies then joined the originals' group, so
clicking either one selected both: the next Option-drag copied (or a
plain drag moved) originals and copies together, and Clear deleted both.

Each of these now remaps group ids the way it remaps link ids: one new
group per copied group.

Adds copies_of_a_group_do_not_join_the_original_group (drag and paste).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjftakwWmCfps6q4KGGnDe

* engine: toggling a group flips it as a whole

timeline.select with toggle decided add or remove per expanded clip, so
toggling a partly selected group (or one whose linked partner was
selected) left it half flipped. Decide once from the requested clips'
selection state and apply that to every grouped and linked clip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjftajchQQEwwLgiUDrtcn

* engine: dedupe unlinked timeline.select replacement

With linked:false, a plain timeline.select assigned the raw clips list,
so repeated ids put the same clip in the selection more than once. Keep
the first of each, in order; add/toggle and linked expansion unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjftajchQQEwwLgiUDrtcn

* engine: dedupe timeline.select replacement with a HashSet

Replace the O(n^2) Vec::contains scan with a seen-set, keeping
first-seen order, so a long hostile id list stays linear.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjftajchQQEwwLgiUDrtcn

* engine: document paste and make_subsequence

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjftajchQQEwwLgiUDrtcn

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: User <user@Mac.local>
2026-10-30 01:22:39 -04:00
NetterSilverandClaude Haiku 5.5 c7966766ef Fix trim_caption moving edges of captions shorter than one frame (#3440)
Found while testing crates/edit/src/captions.rs:~170 (trim_caption, Edge::In branch)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-30 01:22:10 -04:00
aiongg f6dea05f52 Merge #1915: edit: reject repeated clip identities in move plans
# Conflicts:
#	crates/ui-egui/tests/it/timeline_option_drag_ui.rs
2026-10-25 12:35:33 +00:00
aiongg 5ffa3985a4 Batch: transitions share one clamp to their clips; Effect Controls' cut drag previews with roll_delta
#3236 and #3115 each added the same clamp of a transition to its two clips. Both now use keep_within_clips.
#3115's roll_reach repeated #3155's commands::roll_delta without its check that every linked cut rolls by the same amount, so the drag could show a roll that timeline.roll then refuses. The drag uses roll_delta.
2026-10-25 03:21:13 +00:00
aiongg 03f4436e98 Merge #3115: effect controls: drag a transition's cut to move it with the transition 2026-10-25 02:22:54 +00:00
dotCooCoo dbed07f098 Timeline: test a regular trim that leaves a transition longer than its clips 2026-10-24 17:33:11 -07:00
dotCooCoo f1d0c2ddf4 Timeline: a transition stays within its clips after a regular trim
A Regular trim of the second clip's Out edge, or of the first clip's In
edge, could leave a transition between the two clips reaching past
them, and so could a Speed/Duration change without ripple that made
one of them shorter. Only fades to or from nothing followed the trimmed
edge. Such a transition is now shortened when the clips are shorter
than it and moved back inside them, and its stored alignment follows
where that leaves it on the cut.
2026-10-24 15:17:51 -07:00
dotCooCoo 209157740a edit: a ripple trim that shortens a transition's second clip keeps the transition within it
transitions_follow_cuts kept a transition within its two clips only when its cut moved. A ripple trim of the second clip's Out edge leaves the cut in place, so the transition could end past the clip. The check now runs for every transition between two clips.
2026-10-24 09:43:43 -07:00
964424ea8d Timeline: Option-drag duplicates captions (#3040)
* Timeline: Option-drag duplicates captions

Option-dragging a caption block leaves the original in place and drops a copy where it is
released; the cursor turns into a copy cursor and the original stays drawn under the copy while
dragging. A drag now carries the whole caption selection, not only the grabbed block.

New command `captions.duplicate` {captions, delta|deltaFrames}: copies on their own tracks,
never before 0, selected afterwards, one undo step. Captions never overlap, so
`edit::captions::overwrite_captions` places copies over what is there: captions under a copy are
trimmed, split around it or removed.

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

* captions.duplicate: refuse an empty caption list and copy each caption once; move its UI test into the shared ui-egui test binary

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-24 10:17:02 -04:00
NetterSilverandClaude Haiku 5.5 ba4bf46b28 Don't treat pieces with different settings as through edits (#3072)
Found while testing crates/edit/src/through.rs:21 (is_through_edit) and :61-102 (join_through_edits_where)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-24 10:15:42 -04:00
dotCooCoo a988b671f7 effect controls: drag a transition's cut to move it with the transition
In a selected transition's own timeline in Effect Controls, the cut line
over the transition can now be dragged. While it is dragged, the clips
and the transition are drawn where the rolling edit would put them, with
the same limits as `timeline.roll`. On release one rolling edit moves
the cut, so the clips' In and Out points change and the sequence keeps
its length. The ends of the transition still resize it, and the rest of
it still slides it.

A rolling edit now stops where the transition on its cut would leave
one of its two clips. When a ripple trim, a slide or a ripple speed
change moves a cut far enough that the transition on it would leave its
two clips, the transition is moved back within them, shortened when the
clips are now shorter than it, and its stored alignment is updated.
2026-10-24 05:06:39 -07:00
jnohclee-rgb bbd42aafae edit: ripple sync-locked captions with deleted items (#2873)
Reuse caption range extraction for actual closed spans inside the atomic edit. Cover imported captions, multiple spans, locked tracks, rollback and undo/redo.

AI assistance: Antigravity implementation and independent Codex review and validation.
2026-10-23 13:30:05 +08:00
Earl Co b474ca6ca4 edit: reject repeated clip identities in move plans
Reject repeated source IDs before moving items, and normalize selection-derived plans so nudges and drags edit each selected identity once. Keep new-track intent per copy entry so repeated sources retain their requested destinations.

Cover failed-move history preservation, corrected retry, repeated-copy destinations, and Frame Hold followed by dragging.

Signed-off-by: Earl Co <hello@tekiz.ai>
2026-10-14 19:48:23 +02:00
gyro cf9cbd3634 timeline: drop transitions when an edit moves their clips apart
A regular trim that opened a gap at a crossfade's cut (or a razor through
the outgoing clip, or an insert on the cut) left the transition floating
over the gap: remove_orphan_transitions only checked that its clips
existed, not that they still met.

remove_orphan_transitions now also drops a two-clip transition whose
outgoing clip no longer ends where the incoming one starts; a one-sided
fade still needs only its clip.

Session::edit (and edit_merged), which every command goes through, runs
it on each sequence the edit changed, next to the existing self-nesting
check. Sequences an edit did not touch are skipped (Arc::ptr_eq), so a
project saved with stale transitions keeps them until edited. The five
per-command sweeps this replaces (Clear, Nest, Make Subsequence, paste,
Simplify Sequence) are removed.
2026-10-13 04:16:17 -07:00
gyro 25aeb4d8a4 Fix clip drags leaving transitions behind
Dragging a clip kept its transitions on their old spots, so they jumped to the
dropped position on release instead of moving with the clip. The drag preview now
draws each transition where the drop will leave it, applying the same rule the
edit does: a fade travels with its clip, and a cut transition travels only when
every clip it sits on moves to one track by one offset. A cut transition whose
one side stays behind is dropped on release; the preview keeps it on its cut
while dragging, and Option-drag copies show a ghost transition beside the
copies, duplicating only the transitions whose every clip is copied.

- edit: carried_transitions keeps only all-clips-move transitions; move_items
  and copy_items drop or skip the rest
- ui: move_transition_preview draws carried transitions where they land
- tests: timeline_transition_move_ui (fade, both-clips cut, XYZ partial drop,
  cross-track drop, Option-drag ghost); transitions_travel_with_moved_clips
  updated to the drop-on-partial rule
2026-10-12 00:41:05 -07:00
Brandon ThomasandClaude Opus 5.5 0f8533535d Merge main into #972: linked Rate Stretch also leaves clips on locked tracks alone (#934)
rate_stretch_items skips clips on locked tracks and refuses the edit when
every clip is locked, which is what the command loop on main did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:38:34 -04:00
Brandon Thomas 06348de6ee Merge pull request #970 from vbasky/fix/917-locked-track-clip-id
Refuse timeline.move when the source track is locked
2026-10-11 20:24:46 -04:00
Brandon Thomas c2cb113fb8 Merge pull request #969 from vbasky/fix/918-speed-fade-end
Move fade-out with a non-ripple Speed/Duration change
2026-10-11 20:24:45 -04:00
Vikram Bhaskaran df282bcdc1 #918: keep fade-out on the clip end after Speed/Duration
Non-ripple clip.speedDuration shortened the clip but left one-sided
out-edge transitions at the old timeline range. Reposition them with
the same edge-follow used for a regular trim.
2026-10-11 17:14:16 +11:00
Vikram Bhaskaran d79248489b Refuse timeline.move when the clip's source track is locked.
Moving off a locked track used to skip delete_items and overwrite a
second item with the same clip id (#917).
2026-10-11 17:12:33 +11:00
Vikram Bhaskaran 53b99ae335 Keep linked rate-stretch partners at one speed.
A neighbour on only one track used to clamp that partner alone, so picture
and sound stayed linked at different rates. The tightest room now limits
the whole group.
2026-10-11 17:11:52 +11:00
Vikram Bhaskaran 7fef64de6b #911: refuse timing edits on locked tracks
Trim, roll, slip, slide, rate stretch and Speed/Duration now fail with
"track is locked" instead of changing clips on a locked track, matching
same-track move. Linked partners on locked tracks are left alone.
2026-10-11 14:09:05 +11:00
Brandon Thomas bf7ef0e894 Merge pull request #794 from impostazioni/fix/alt-drag-duplicate
Timeline: Option-drag copies clips instead of moving them
2026-10-10 18:15:25 -04:00
Brandon Thomas c6dbc390a4 Merge pull request #756 from vangel76/fix-374-transition-follows-trim
#374: a clip's fades follow its edges on a regular trim
2026-10-10 17:00:43 -04:00
impostazioniandClaude Opus 5.5 a8b3d7f703 Timeline: Option-drag copies clips instead of moving them
Holding Option (Alt) while dragging timeline clips now leaves the
originals in place and drops copies where the pointer lets go, as in
Premiere. The copies are selected; copies of linked clips are linked to
each other, and transitions that would travel with a move are copied.

- edit: copy_items (overwrite / insert, new ids, links and transitions)
- engine: timeline.move takes `copy: true`, returns `copied`
- ui: the drag remembers Option, shows the copy under the pointer while
  the originals stay, copy cursor
- tests: engine copy/link/locked-track test, headless Option-drag UI test

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 21:52:28 +01:00
Brandon ThomasandClaude Opus 5.5 e4f3cab5a0 Merge origin/main into #704 (gap and marker context menus side by side; contributors)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:27:48 -04:00
vangel76 2f49774895 Merge remote-tracking branch 'upstream/main' into fix-374-transition-follows-trim
# Conflicts:
#	crates/edit/src/tests.rs
2026-10-10 22:08:23 +02:00
Brandon ThomasandClaude Opus 5.5 e82f9bca71 Merge origin/main into #627 (keep both trim UI tests)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:02:33 -04:00
Brandon Thomas a6b323056f Merge pull request #755 from vangel76/fix-227-transitions-follow-move
#227: transitions travel with the clips they sit on when moved
2026-10-10 15:53:26 -04:00
vangel76andClaude Opus 5.5 2cab09e69b #374: a clip's fades follow its edges on a regular trim
Problem: dragging a clip's edge with the Selection tool (a regular trim)
moved the edge but left a fade in from nothing / fade out to nothing where
it was; only Ripple trims moved transitions along with the cut.

Fix: after a regular trim, the trimmed clip's one-sided transitions are put
back on its edges, and shortened when the clip gets shorter than them.
Transitions between two clips are untouched (a regular trim cannot move
their cut).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 21:29:55 +02:00
vangel76andClaude Opus 5.5 b86dcf7bb3 #227: transitions travel with the clips they sit on when moved
Problem: moving a clip dropped the transitions at its edges (#227, point 8
of #374). `edit::move_items` deletes the moved clips before placing them
again, and that deletion removes every transition that refers to them, so
a fade on a clip's edge, or the cut between two clips moved together,
vanished.

Fix: before the move, collect the transitions whose clips all move onto one
track by one offset, and put them back on that track shifted by the offset
once the clips have landed (overwrite and insert moves). A crossfade whose
partner stays behind is still dropped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 21:24:52 +02:00
vangel76andClaude Opus 5.5 ce6afffc6f #712: keyboard Slide keeps linked picture and sound aligned at a neighbour limit
Problem: timeline.slideLeft/Right(5) slid every expanded selection member by
the raw requested delta, so when a neighbour limited only one linked partner
(e.g. a short sound-only follower), picture and sound ended up at different
starts. timeline.slide already clamped to a common delta.

Fix: add edit::slide_items, which clamps the delta by the most restrictive
item and slides all items by it, and use it from both the keyboard Slide
commands and timeline.slide.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 20:39:48 +02:00
Oskar 86d113e557 edit: Close Gap refuses a locked track
Closing a gap on a locked track skipped that track but still moved the
sync-locked ones, pulling them out of sync with it. It is now refused
with the usual "locked" error.
2026-10-10 19:15:30 +02:00
JordyUSAandClaude Opus 5.5 696f428faf #374: trim preview keeps the waveform in place instead of squeezing it
While an edge was dragged, the Timeline drew the clip at its new length
from the untrimmed item, so draw_waveform spread the clip's whole source
range over the shorter (or longer) box: the waveform squeezed and the
sound under the pointer moved, which made it hard to trim to where the
music starts (#374, item 13). Trim and roll previews now draw from the
item the edit will leave, so every timeline time still covered shows the
same media and the waveform is cut off at the moving edge. Video
thumbnails show the new first frame the same way. Rate Stretch, which
really fits the same media into a new length, still squeezes.

The item update is factored out of trim and ripple_trim_group into
filmcraft_edit::move_edge, which the preview uses too, so preview and
edit agree for speed-changed, reversed and frame-held clips.

Rendered mid-drag against the released result, the music clip's
waveform matched in 15% of pixel columns before and 100% after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:24:37 +07:00
Brandon ThomasandClaude Opus 5.5 8e0a824dcf Merge origin/main into fix-503 (keep both sides: Volume line + transitions)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 06:44:25 -04:00
Brandon Thomas 9a3692f239 Merge pull request #257 from MrCloudy2/feat/edit-point-menu-219
#219: right-clicking a cut opens the edit point menu
2026-10-10 05:01:25 -04:00
Brandon Thomas 45936c1d6c Merge pull request #575 from MarekSpodBiedry/issue-548
Slide: keep reversed neighbours' source ranges correct (#548)
2026-10-10 04:44:26 -04:00
Brandon Thomas 9e2ebd696e Merge pull request #562 from MarekSpodBiedry/issue-530
Frame-held Regular In trim stops at the previous clip instead of overlapping it (#530)
2026-10-10 04:42:59 -04:00
Brandon Thomas 0e11974976 Merge pull request #559 from MarekSpodBiedry/issue-527
fix(edit): reversed trims use the media handle their playback direction consumes (#527)
2026-10-10 04:42:34 -04:00
MarekSpodBiedry d23b33a9fe Frame-held Regular In trim stops at the previous clip instead of overlapping it (#530) 2026-10-10 09:14:41 +02:00
MarekSpodBiedry 7484343012 fix(edit): reversed trims use the media handle their playback direction consumes (#527) 2026-10-10 09:14:40 +02:00
MarekSpodBiedry 1ccb51fb78 Slide: keep reversed neighbours' source ranges correct (#548) 2026-10-10 09:14:35 +02:00