From 4510f6d36a1e484d09ab1838b992680d5cbaa497 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 2 Aug 2021 07:44:05 -0700 Subject: [PATCH] timeline: add move in/out to playhead Fixes #1691 --- app/panel/timeline/timeline.cpp | 10 +++ app/panel/timeline/timeline.h | 4 + app/widget/panel/panel.h | 4 + app/widget/timelinewidget/timelinewidget.cpp | 86 ++++++++++++++++++-- app/widget/timelinewidget/timelinewidget.h | 6 ++ app/window/mainwindow/mainmenu.cpp | 12 +++ app/window/mainwindow/mainmenu.h | 4 + 7 files changed, 117 insertions(+), 9 deletions(-) diff --git a/app/panel/timeline/timeline.cpp b/app/panel/timeline/timeline.cpp index 903320c3e..50b6c7508 100644 --- a/app/panel/timeline/timeline.cpp +++ b/app/panel/timeline/timeline.cpp @@ -174,6 +174,16 @@ void TimelinePanel::NudgeRight() timeline_widget()->NudgeRight(); } +void TimelinePanel::MoveInToPlayhead() +{ + timeline_widget()->MoveInToPlayhead(); +} + +void TimelinePanel::MoveOutToPlayhead() +{ + timeline_widget()->MoveOutToPlayhead(); +} + void TimelinePanel::InsertFootageAtPlayhead(const QVector &footage) { timeline_widget()->InsertFootageAtPlayhead(footage); diff --git a/app/panel/timeline/timeline.h b/app/panel/timeline/timeline.h index 17604eb9c..f27726d65 100644 --- a/app/panel/timeline/timeline.h +++ b/app/panel/timeline/timeline.h @@ -92,6 +92,10 @@ public: virtual void NudgeRight() override; + virtual void MoveInToPlayhead() override; + + virtual void MoveOutToPlayhead() override; + void ShowSpeedDurationDialogForSelectedClips() { timeline_widget()->ShowSpeedDurationDialogForSelectedClips(); diff --git a/app/widget/panel/panel.h b/app/widget/panel/panel.h index 51c989af2..95c0743ae 100644 --- a/app/widget/panel/panel.h +++ b/app/widget/panel/panel.h @@ -174,6 +174,10 @@ public: virtual void NudgeRight(){} + virtual void MoveInToPlayhead(){} + + virtual void MoveOutToPlayhead(){} + signals: void CloseRequested(); diff --git a/app/widget/timelinewidget/timelinewidget.cpp b/app/widget/timelinewidget/timelinewidget.cpp index 8a6978e97..5174a4e8c 100644 --- a/app/widget/timelinewidget/timelinewidget.cpp +++ b/app/widget/timelinewidget/timelinewidget.cpp @@ -739,6 +739,16 @@ void TimelineWidget::NudgeRight() } } +void TimelineWidget::MoveInToPlayhead() +{ + MoveToPlayheadInternal(false); +} + +void TimelineWidget::MoveOutToPlayhead() +{ + MoveToPlayheadInternal(true); +} + void TimelineWidget::ShowSpeedDurationDialogForSelectedClips() { QVector clips; @@ -1179,19 +1189,73 @@ void TimelineWidget::UpdateViewTimebases() void TimelineWidget::NudgeInternal(const rational &amount) { - MultiUndoCommand *command = new MultiUndoCommand(); + if (!selected_blocks_.isEmpty()) { + MultiUndoCommand *command = new MultiUndoCommand(); - foreach (Block* b, selected_blocks_) { - command->add_child(new TrackReplaceBlockWithGapCommand(b->track(), b, false)); - command->add_child(new TrackPlaceBlockCommand(sequence()->track_list(b->track()->type()), b->track()->Index(), b, b->in() + amount)); + foreach (Block* b, selected_blocks_) { + command->add_child(new TrackReplaceBlockWithGapCommand(b->track(), b, false)); + command->add_child(new TrackPlaceBlockCommand(sequence()->track_list(b->track()->type()), b->track()->Index(), b, b->in() + amount)); + } + + // Nudge selections + TimelineWidgetSelections new_sel = GetSelections(); + new_sel.ShiftTime(amount); + command->add_child(new TimelineWidget::SetSelectionsCommand(this, new_sel, GetSelections(), true)); + + Core::instance()->undo_stack()->push(command); } +} - // Nudge selections - TimelineWidgetSelections new_sel = GetSelections(); - new_sel.ShiftTime(amount); - command->add_child(new TimelineWidget::SetSelectionsCommand(this, new_sel, GetSelections(), true)); +void TimelineWidget::MoveToPlayheadInternal(bool out) +{ + if (GetConnectedNode() && !selected_blocks_.isEmpty()) { + MultiUndoCommand *command = new MultiUndoCommand(); - Core::instance()->undo_stack()->pushIfHasChildren(command); + // Remove each block from the graph + QHash earliest_pts; + foreach (Block *b, selected_blocks_) { + command->add_child(new TrackReplaceBlockWithGapCommand(b->track(), b, false)); + + rational r = earliest_pts.value(b->track(), out ? RATIONAL_MIN : RATIONAL_MAX); + rational compare = out ? b->out() : b->in(); + if (compare < r == !out) { + earliest_pts.insert(b->track(), compare); + } + } + + foreach (Block *b, selected_blocks_) { + rational shift_amt = GetTime() - earliest_pts.value(b->track()); + rational new_in = b->in() + shift_amt; + bool can_shift = true; + + if (new_in < 0) { + // Handle clips threatening to go below 0 + rational new_out = new_in + b->length(); + if (new_out <= 0) { + can_shift = false; + } else { + command->add_child(new BlockResizeWithMediaInCommand(b, new_out)); + new_in = 0; + } + } + + if (can_shift) { + command->add_child(new TrackPlaceBlockCommand(sequence()->track_list(b->track()->type()), b->track()->Index(), b, new_in)); + } + } + + // Shift selections + TimelineWidgetSelections new_sel = GetSelections(); + for (auto it=new_sel.begin(); it!=new_sel.end(); it++) { + rational track_adj = GetTime() - earliest_pts.value(GetTrackFromReference(it.key()), GetTime()); + if (!track_adj.isNull()) { + it.value().shift(track_adj); + } + } + command->add_child(new SetSelectionsCommand(this, new_sel, GetSelections(), true)); + + Core::instance()->undo_stack()->push(command); + } } void TimelineWidget::SetViewBeamCursor(const TimelineCoordinate &coord) @@ -1620,6 +1684,10 @@ void TimelineWidget::RemoveSelection(Block *item) void TimelineWidget::SetSelections(const TimelineWidgetSelections &s, bool process_block_changes) { + if (selections_ == s) { + return; + } + if (process_block_changes) { SignalDeselectedBlocks(GetBlocksInSelection(selections_.Subtracted(s))); SignalSelectedBlocks(GetBlocksInSelection(s.Subtracted(selections_))); diff --git a/app/widget/timelinewidget/timelinewidget.h b/app/widget/timelinewidget/timelinewidget.h index 060b64a60..50052c413 100644 --- a/app/widget/timelinewidget/timelinewidget.h +++ b/app/widget/timelinewidget/timelinewidget.h @@ -95,6 +95,10 @@ public: void NudgeRight(); + void MoveInToPlayhead(); + + void MoveOutToPlayhead(); + void ShowSpeedDurationDialogForSelectedClips(); /** @@ -319,6 +323,8 @@ private: void NudgeInternal(const rational &amount); + void MoveToPlayheadInternal(bool out); + private slots: void ViewMousePressed(TimelineViewMouseEvent* event); void ViewMouseMoved(TimelineViewMouseEvent* event); diff --git a/app/window/mainwindow/mainmenu.cpp b/app/window/mainwindow/mainmenu.cpp index b53d94e63..8c1d3052c 100644 --- a/app/window/mainwindow/mainmenu.cpp +++ b/app/window/mainwindow/mainmenu.cpp @@ -110,6 +110,8 @@ MainMenu::MainMenu(MainWindow *parent) : edit_menu_->addSeparator(); edit_nudge_left_item_ = edit_menu_->AddItem("nudgeleft", this, &MainMenu::NudgeLeftTriggered, "Alt+Left"); edit_nudge_right_item_ = edit_menu_->AddItem("nudgeright", this, &MainMenu::NudgeRightTriggered, "Alt+Right"); + edit_move_in_to_playhead_item_ = edit_menu_->AddItem("moveintoplayhead", this, &MainMenu::MoveInToPlayheadTriggered, "["); + edit_move_out_to_playhead_item_ = edit_menu_->AddItem("moveouttoplayhead", this, &MainMenu::MoveOutToPlayheadTriggered, "]"); edit_menu_->addSeparator(); MenuShared::instance()->AddItemsForInOutMenu(edit_menu_); edit_delete_inout_item_ = edit_menu_->AddItem("deleteinout", this, &MainMenu::DeleteInOutTriggered, ";"); @@ -550,6 +552,16 @@ void MainMenu::NudgeRightTriggered() PanelManager::instance()->CurrentlyFocused()->NudgeRight(); } +void MainMenu::MoveInToPlayheadTriggered() +{ + PanelManager::instance()->CurrentlyFocused()->MoveInToPlayhead(); +} + +void MainMenu::MoveOutToPlayheadTriggered() +{ + PanelManager::instance()->CurrentlyFocused()->MoveOutToPlayhead(); +} + void MainMenu::ActionSearchTriggered() { ActionSearch as(parentWidget()); diff --git a/app/window/mainwindow/mainmenu.h b/app/window/mainwindow/mainmenu.h index baa864b9b..4cedd3522 100644 --- a/app/window/mainwindow/mainmenu.h +++ b/app/window/mainwindow/mainmenu.h @@ -156,6 +156,8 @@ private slots: void NudgeLeftTriggered(); void NudgeRightTriggered(); + void MoveInToPlayheadTriggered(); + void MoveOutToPlayheadTriggered(); void ActionSearchTriggered(); @@ -223,6 +225,8 @@ private: QAction* edit_edit_to_out_item_; QAction* edit_nudge_left_item_; QAction* edit_nudge_right_item_; + QAction* edit_move_in_to_playhead_item_; + QAction* edit_move_out_to_playhead_item_; QAction* edit_delete_inout_item_; QAction* edit_ripple_delete_inout_item_; QAction* edit_set_marker_item_;