From 1fa51613f9f643c223dd45ed00a8f7f364cd9479 Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Sun, 15 May 2022 11:06:45 -0700 Subject: [PATCH] improved transition behavior This is still not complete, but definitely should help a lot --- app/widget/timelinewidget/tool/pointer.cpp | 127 ++++++++++++++---- app/widget/timelinewidget/tool/pointer.h | 4 + .../view/timelineviewghostitem.h | 1 - 3 files changed, 108 insertions(+), 24 deletions(-) diff --git a/app/widget/timelinewidget/tool/pointer.cpp b/app/widget/timelinewidget/tool/pointer.cpp index 9361d779e..7158cb906 100644 --- a/app/widget/timelinewidget/tool/pointer.cpp +++ b/app/widget/timelinewidget/tool/pointer.cpp @@ -264,10 +264,30 @@ void PointerTool::InitiateDragInternal(Block *clicked_item, return; } - // Determine if this move is a slide, which is determined by either - bool clips_are_sliding = (slide_instead_of_moving || dynamic_cast(clicked_item)); + bool sliding_due_to_transition = false; - if (clips_are_sliding) { + if (!slide_instead_of_moving) { + // If the user tries to move a transition without moving the clip it belongs to, we turn + // this into a slide + foreach (Block* block, clips) { + if (TransitionBlock* transit = dynamic_cast(block)) { + if (!CanTransitionMove(transit, clips)) { + slide_instead_of_moving = true; + break; + } + } else if (ClipBlock *clip = dynamic_cast(block)) { + if ((clip->in_transition() && !CanTransitionMove(clip->in_transition(), clips)) + || (clip->out_transition() && !CanTransitionMove(clip->out_transition(), clips))) { + slide_instead_of_moving = true; + break; + } + } + } + + sliding_due_to_transition = slide_instead_of_moving; + } + + if (slide_instead_of_moving) { // This is a slide. What we do here is move clips within their own track, between the clips // that they're already next to. We don't allow changing tracks or changing the order of // blocks. @@ -297,17 +317,51 @@ void PointerTool::InitiateDragInternal(Block *clicked_item, Block* latest = latest_block_on_track.value(i.key()); // First we add the block that's out trimming, the one prior to the earliest - TimelineViewGhostItem* earliest_ghost; - if (earliest->previous()) { - earliest_ghost = AddGhostFromBlock(earliest->previous(), Timeline::kTrimOut); - } else { - earliest_ghost = AddGhostFromNull(earliest->in(), earliest->in(), track->ToReference(), Timeline::kTrimOut); + { + TimelineViewGhostItem* earliest_ghost; + bool slide_with_earliest_previous = true; + if (sliding_due_to_transition && earliest->previous()) { + if (TransitionBlock *transit = dynamic_cast(earliest)) { + if (earliest->previous() != transit->connected_out_block()) { + slide_with_earliest_previous = false; + } + } else if (ClipBlock *clip = dynamic_cast(earliest)) { + if (earliest->previous() != clip->in_transition()) { + slide_with_earliest_previous = false; + } + } + } + + if (earliest->previous() && slide_with_earliest_previous) { + earliest_ghost = AddGhostFromBlock(earliest->previous(), Timeline::kTrimOut); + } else { + earliest_ghost = AddGhostFromNull(earliest->in(), earliest->in(), track->ToReference(), Timeline::kTrimOut); + } + SetGhostToSlideMode(earliest_ghost); } - SetGhostToSlideMode(earliest_ghost); // Then we add the block that's in trimming, the one after the latest if (latest->next()) { - TimelineViewGhostItem* latest_ghost = AddGhostFromBlock(latest->next(), Timeline::kTrimIn); + TimelineViewGhostItem* latest_ghost; + + bool slide_with_latest_next = true; + if (sliding_due_to_transition) { + if (TransitionBlock *transit = dynamic_cast(latest)) { + if (latest->next() != transit->connected_in_block()) { + slide_with_latest_next = false; + } + } else if (ClipBlock *clip = dynamic_cast(latest)) { + if (latest->next() != clip->out_transition()) { + slide_with_latest_next = false; + } + } + } + + if (slide_with_latest_next) { + latest_ghost = AddGhostFromBlock(latest->next(), Timeline::kTrimIn); + } else { + latest_ghost = AddGhostFromNull(latest->out(), latest->out(), track->ToReference(), Timeline::kTrimIn); + } SetGhostToSlideMode(latest_ghost); } @@ -329,13 +383,18 @@ void PointerTool::InitiateDragInternal(Block *clicked_item, } else { // Prepare for a standard pointer move by creating ghosts for them and any related blocks foreach (Block* block, clips) { - if (dynamic_cast(block) || dynamic_cast(block)) { - // Gaps cannot move, and we handle transitions further down - continue; - } - // Create ghost for this block - AddGhostFromBlock(block, trim_mode, true); + auto ghost = AddGhostFromBlock(block, trim_mode, true); + Q_UNUSED(ghost) + + if (ClipBlock *clip = dynamic_cast(block)) { + if (clip->out_transition()) { + AddGhostFromBlock(clip->out_transition(), trim_mode, true); + } + if (clip->in_transition()) { + AddGhostFromBlock(clip->in_transition(), trim_mode, true); + } + } } } @@ -454,6 +513,18 @@ void PointerTool::InitiateDragInternal(Block *clicked_item, } } +bool PointerTool::CanTransitionMove(TransitionBlock *transit, const QVector &clips) +{ + Block *out = transit->connected_out_block(); + Block *in = transit->connected_in_block(); + + if ((out && !clips.contains(out)) || (in && !clips.contains(in))) { + return false; + } + + return true; +} + void PointerTool::ProcessDrag(const TimelineCoordinate &mouse_pos) { // Calculate track movement @@ -691,8 +762,7 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event) } if (!movement.isNull()) { - QHash >::const_iterator i; - for (i=slide_info.constBegin(); i!=slide_info.constEnd(); i++) { + for (auto i=slide_info.constBegin(); i!=slide_info.constEnd(); i++) { command->add_child(new TrackSlideCommand(parent()->GetTrackFromReference(i.key()), i.value(), in_adjacents.value(i.key()), @@ -737,6 +807,17 @@ void PointerTool::InitiateDrag(Block *clicked_item, Timeline::MovementMode trim_ InitiateDragInternal(clicked_item, trim_mode, modifiers, false, false, false); } +TimelineViewGhostItem *PointerTool::GetExistingGhostFromBlock(Block *block) +{ + foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) { + if (Node::ValueToPtr(ghost->GetData(TimelineViewGhostItem::kAttachedBlock)) == block) { + return ghost; + } + } + + return nullptr; +} + //#define HIDE_GAP_GHOSTS TimelineViewGhostItem* PointerTool::AddGhostFromBlock(Block* block, Timeline::MovementMode mode, bool check_if_exists) @@ -747,17 +828,17 @@ TimelineViewGhostItem* PointerTool::AddGhostFromBlock(Block* block, Timeline::Mo return nullptr; } + TimelineViewGhostItem* ghost; + // Check if we've already made a ghost for this block if (check_if_exists) { - foreach (TimelineViewGhostItem* ghost, parent()->GetGhostItems()) { - if (Node::ValueToPtr(ghost->GetData(TimelineViewGhostItem::kAttachedBlock)) == block) { - return ghost; - } + if ((ghost = GetExistingGhostFromBlock(block))) { + return ghost; } } // Otherwise, it's time to make a ghost for this block - TimelineViewGhostItem* ghost = TimelineViewGhostItem::FromBlock(block); + ghost = TimelineViewGhostItem::FromBlock(block); #ifdef HIDE_GAP_GHOSTS if (block->type() == Block::kGap) { diff --git a/app/widget/timelinewidget/tool/pointer.h b/app/widget/timelinewidget/tool/pointer.h index abea934e1..be4e0cf90 100644 --- a/app/widget/timelinewidget/tool/pointer.h +++ b/app/widget/timelinewidget/tool/pointer.h @@ -41,6 +41,8 @@ protected: virtual void InitiateDrag(Block* clicked_item, Timeline::MovementMode trim_mode, Qt::KeyboardModifiers modifiers); + TimelineViewGhostItem *GetExistingGhostFromBlock(Block *block); + TimelineViewGhostItem* AddGhostFromBlock(Block *block, Timeline::MovementMode mode, bool check_if_exists = false); TimelineViewGhostItem* AddGhostFromNull(const rational& in, const rational& out, const Track::Reference& track, Timeline::MovementMode mode); @@ -72,6 +74,8 @@ protected: const Timeline::MovementMode& drag_movement_mode() const { return drag_movement_mode_; } void set_drag_movement_mode(const Timeline::MovementMode &d) { drag_movement_mode_ = d; } + static bool CanTransitionMove(TransitionBlock *transit, const QVector &clips); + void SetMovementAllowed(bool e) { movement_allowed_ = e; diff --git a/app/widget/timelinewidget/view/timelineviewghostitem.h b/app/widget/timelinewidget/view/timelineviewghostitem.h index bbabf1341..16a3c0e8a 100644 --- a/app/widget/timelinewidget/view/timelineviewghostitem.h +++ b/app/widget/timelinewidget/view/timelineviewghostitem.h @@ -75,7 +75,6 @@ public: ghost->can_have_zero_length_ = false; } else if (dynamic_cast(block)) { ghost->can_have_zero_length_ = false; - ghost->SetCanMoveTracks(false); } return ghost;