From be784591fc5c477e7f84a7c829ce45f9c3ee0b20 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 6 Jun 2020 17:50:23 +1000 Subject: [PATCH] timeline: optimized pointer tool ctrl+drop --- app/widget/timelinewidget/timelinewidget.cpp | 49 +------- app/widget/timelinewidget/tool/pointer.cpp | 23 ---- app/widget/timelinewidget/undo/undo.cpp | 124 +++++++++++++++++++ app/widget/timelinewidget/undo/undo.h | 29 +++++ 4 files changed, 158 insertions(+), 67 deletions(-) diff --git a/app/widget/timelinewidget/timelinewidget.cpp b/app/widget/timelinewidget/timelinewidget.cpp index f7e2f8819..2a2c15ad3 100644 --- a/app/widget/timelinewidget/timelinewidget.cpp +++ b/app/widget/timelinewidget/timelinewidget.cpp @@ -824,50 +824,11 @@ QList TimelineWidget::GetSelectedBlocks() void TimelineWidget::InsertGapsAt(const rational &earliest_point, const rational &insert_length, QUndoCommand *command) { - QVector blocks_to_split; - QList blocks_to_append_gap_to; - QList gaps_to_extend; - - foreach (TrackOutput* track, GetConnectedNode()->GetTracks()) { - if (track->IsLocked()) { - continue; - } - - foreach (Block* b, track->Blocks()) { - if (b->out() >= earliest_point) { - if (b->type() == Block::kClip) { - - if (b->out() > earliest_point) { - blocks_to_split.append(b); - } - - blocks_to_append_gap_to.append(b); - - } else if (b->type() == Block::kGap) { - - gaps_to_extend.append(b); - - } - - break; - } - } - } - - // Extend gaps that already exist - foreach (Block* gap, gaps_to_extend) { - new BlockResizeCommand(gap, gap->length() + insert_length, command); - } - - // Split clips here - new BlockSplitPreservingLinksCommand(blocks_to_split, {earliest_point}, command); - - // Insert gaps that don't exist yet - foreach (Block* b, blocks_to_append_gap_to) { - GapBlock* gap = new GapBlock(); - gap->set_length_and_media_out(insert_length); - new NodeAddCommand(static_cast(GetConnectedNode()->parent()), gap, command); - new TrackInsertBlockAfterCommand(TrackOutput::TrackFromBlock(b), gap, b, command); + for (int i=0;itrack_list(static_cast(i)), + earliest_point, + insert_length, + command); } } diff --git a/app/widget/timelinewidget/tool/pointer.cpp b/app/widget/timelinewidget/tool/pointer.cpp index 80d8dc703..e300daff8 100644 --- a/app/widget/timelinewidget/tool/pointer.cpp +++ b/app/widget/timelinewidget/tool/pointer.cpp @@ -248,21 +248,11 @@ void TimelineWidget::PointerTool::FinishDrag(TimelineViewMouseEvent *event) InsertGapsAtGhostDestination(parent()->ghost_items_, command); } - /* - QList tracks_affected; - */ - // Now we can re-add each clip for (int i=0;iGetAdjustedTrack())) { - tracks_affected.append(ghost->GetAdjustedTrack()); - } - */ - if (duplicate_clips) { // Duplicate rather than move Node* copy = block->copy(); @@ -275,11 +265,6 @@ void TimelineWidget::PointerTool::FinishDrag(TimelineViewMouseEvent *event) // Place the copy instead of the original block block = static_cast(copy); - /* - } else if (!tracks_affected.contains(ghost->Track())) { - // Block moved from its original position. Mark its track as affected. - tracks_affected.append(ghost->Track()); - */ } const TrackReference& track_ref = ghost->GetAdjustedTrack(); @@ -290,14 +275,6 @@ void TimelineWidget::PointerTool::FinishDrag(TimelineViewMouseEvent *event) command); } - /* - foreach (const TrackReference& t, tracks_affected) { - new TrackCleanGapsCommand(parent()->GetConnectedNode()->track_list(t.type()), - t.index(), - command); - } - */ - // FIXME: Heavy optimization since MOST of the timeline does NOT change in this time } diff --git a/app/widget/timelinewidget/undo/undo.cpp b/app/widget/timelinewidget/undo/undo.cpp index 9ad33d36e..94b29c364 100644 --- a/app/widget/timelinewidget/undo/undo.cpp +++ b/app/widget/timelinewidget/undo/undo.cpp @@ -1444,4 +1444,128 @@ void TrackListRippleToolCommand::undo_internal() } } +TrackListInsertGaps::TrackListInsertGaps(TrackList *track_list, const rational &point, const rational &length, QUndoCommand *parent) : + UndoCommand(parent), + track_list_(track_list), + point_(point), + length_(length), + split_command_(nullptr) +{ + all_tracks_unlocked_ = true; + + foreach (TrackOutput* track, track_list_->GetTracks()) { + if (track->IsLocked()) { + all_tracks_unlocked_ = false; + continue; + } + + working_tracks_.append(track); + } +} + +Project *TrackListInsertGaps::GetRelevantProject() const +{ + return static_cast(static_cast(track_list_->parent())->parent())->project(); +} + +void TrackListInsertGaps::redo_internal() +{ + if (all_tracks_unlocked_) { + // Optimize by shifting over since we have a constant amount of time being inserted + if (track_list_->type() == Timeline::kTrackTypeVideo) { + static_cast(track_list_->parent())->ShiftVideoCache(point_, point_ + length_); + } else if (track_list_->type() == Timeline::kTrackTypeAudio) { + static_cast(track_list_->parent())->ShiftAudioCache(point_, point_ + length_); + } + + foreach (TrackOutput* track, working_tracks_) { + track->BlockInvalidateCache(); + } + } + + QVector blocks_to_split; + QList blocks_to_append_gap_to; + + foreach (TrackOutput* track, working_tracks_) { + foreach (Block* b, track->Blocks()) { + if (b->type() == Block::kGap && b->in() <= point_ && b->out() >= point_) { + gaps_to_extend_.append(b); + } else if (b->type() == Block::kClip && b->out() >= point_) { + if (b->out() > point_) { + blocks_to_split.append(b); + } + + blocks_to_append_gap_to.append(b); + } + } + } + + foreach (Block* gap, gaps_to_extend_) { + gap->set_length_and_media_out(gap->length() + length_); + } + + if (!blocks_to_split.isEmpty()) { + split_command_ = new BlockSplitPreservingLinksCommand(blocks_to_split, {point_}); + split_command_->redo(); + } + + foreach (Block* block, blocks_to_append_gap_to) { + GapBlock* gap = new GapBlock(); + gap->set_length_and_media_out(length_); + static_cast(block->parent())->AddNode(gap); + TrackOutput::TrackFromBlock(block)->InsertBlockAfter(gap, block); + gaps_added_.append(gap); + } + + if (all_tracks_unlocked_) { + foreach (TrackOutput* track, working_tracks_) { + track->UnblockInvalidateCache(); + track->PushLengthChangeSignal(false); + } + } +} + +void TrackListInsertGaps::undo_internal() +{ + if (all_tracks_unlocked_) { + // Optimize by shifting over since we have a constant amount of time being inserted + if (track_list_->type() == Timeline::kTrackTypeVideo) { + static_cast(track_list_->parent())->ShiftVideoCache(point_ + length_, point_); + } else if (track_list_->type() == Timeline::kTrackTypeAudio) { + static_cast(track_list_->parent())->ShiftAudioCache(point_ + length_, point_); + } + + foreach (TrackOutput* track, working_tracks_) { + track->BlockInvalidateCache(); + } + } + + // Remove added gaps + foreach (GapBlock* gap, gaps_added_) { + TrackOutput::TrackFromBlock(gap)->RippleRemoveBlock(gap); + delete TakeNodeFromParentGraph(gap); + } + gaps_added_.clear(); + + // Un-split blocks + if (split_command_) { + split_command_->undo(); + delete split_command_; + split_command_ = nullptr; + } + + // Restore original length of gaps + foreach (Block* gap, gaps_to_extend_) { + gap->set_length_and_media_out(gap->length() - length_); + } + gaps_to_extend_.clear(); + + if (all_tracks_unlocked_) { + foreach (TrackOutput* track, working_tracks_) { + track->UnblockInvalidateCache(); + track->PushLengthChangeSignal(false); + } + } +} + OLIVE_NAMESPACE_EXIT diff --git a/app/widget/timelinewidget/undo/undo.h b/app/widget/timelinewidget/undo/undo.h index 511fffdb2..bf22022db 100644 --- a/app/widget/timelinewidget/undo/undo.h +++ b/app/widget/timelinewidget/undo/undo.h @@ -574,6 +574,35 @@ private: }; +class TrackListInsertGaps : public UndoCommand { +public: + TrackListInsertGaps(TrackList* track_list, const rational& point, const rational& length, QUndoCommand* parent = nullptr); + + virtual Project* GetRelevantProject() const override; + +protected: + virtual void redo_internal() override; + virtual void undo_internal() override; + +private: + TrackList* track_list_; + + rational point_; + + rational length_; + + QList working_tracks_; + + bool all_tracks_unlocked_; + + QList gaps_to_extend_; + + QList gaps_added_; + + BlockSplitPreservingLinksCommand* split_command_; + +}; + OLIVE_NAMESPACE_EXIT #endif // TIMELINEUNDOABLE_H