From 85c9687f91fe539bda4dc47c1619d9b4b79465e3 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 23 Sep 2019 23:50:03 +1000 Subject: [PATCH] slip tool implemented --- app/widget/timelineview/timelineview.cpp | 4 +- app/widget/timelineview/timelineview.h | 14 +++- .../timelineview/timelineviewghostitem.cpp | 28 ++++++- .../timelineview/timelineviewghostitem.h | 7 ++ app/widget/timelineview/tool/CMakeLists.txt | 1 + app/widget/timelineview/tool/pointer.cpp | 4 +- app/widget/timelineview/tool/ripple.cpp | 4 - app/widget/timelineview/tool/rolling.cpp | 4 - app/widget/timelineview/tool/slide.cpp | 4 - app/widget/timelineview/tool/slip.cpp | 83 +++++++++++++++++++ 10 files changed, 135 insertions(+), 18 deletions(-) create mode 100644 app/widget/timelineview/tool/slip.cpp diff --git a/app/widget/timelineview/timelineview.cpp b/app/widget/timelineview/timelineview.cpp index e4ebacdd0..3a82a23e9 100644 --- a/app/widget/timelineview/timelineview.cpp +++ b/app/widget/timelineview/timelineview.cpp @@ -40,6 +40,7 @@ TimelineView::TimelineView(QWidget *parent) : rolling_tool_(this), razor_tool_(this), slide_tool_(this), + slip_tool_(this), hand_tool_(this), zoom_tool_(this), timeline_node_(nullptr), @@ -271,7 +272,7 @@ TimelineView::Tool *TimelineView::GetActiveTool() case olive::tool::kRazor: return &razor_tool_; case olive::tool::kSlip: - return nullptr; // FIXME: Implement + return &slip_tool_; case olive::tool::kSlide: return &slide_tool_; case olive::tool::kHand: @@ -386,4 +387,3 @@ void TimelineView::UpdateSceneRect() scene_.setSceneRect(bounding_rect); } - diff --git a/app/widget/timelineview/timelineview.h b/app/widget/timelineview/timelineview.h index 7ed75275a..080ead65f 100644 --- a/app/widget/timelineview/timelineview.h +++ b/app/widget/timelineview/timelineview.h @@ -197,9 +197,10 @@ private: * Ghost's length becomes 0 or negative. */ rational ValidateOutTrimming(rational movement, const QVector ghosts, bool prevent_overwriting); + + virtual void ProcessDrag(const QPoint &mouse_pos); private: void InitiateDrag(const QPoint &mouse_pos); - void ProcessDrag(const QPoint &mouse_pos); void AddGhostInternal(TimelineViewGhostItem* ghost, olive::timeline::MovementMode mode); @@ -281,6 +282,16 @@ private: bool allow_gap_trimming) override; }; + class SlipTool : public PointerTool + { + public: + SlipTool(TimelineView* parent); + + protected: + virtual void ProcessDrag(const QPoint &mouse_pos) override; + virtual void MouseReleaseInternal(QMouseEvent *event) override; + }; + class HandTool : public Tool { public: @@ -316,6 +327,7 @@ private: RollingTool rolling_tool_; RazorTool razor_tool_; SlideTool slide_tool_; + SlipTool slip_tool_; HandTool hand_tool_; ZoomTool zoom_tool_; diff --git a/app/widget/timelineview/timelineviewghostitem.cpp b/app/widget/timelineview/timelineviewghostitem.cpp index 7a07d571d..2b2796db3 100644 --- a/app/widget/timelineview/timelineviewghostitem.cpp +++ b/app/widget/timelineview/timelineviewghostitem.cpp @@ -24,8 +24,6 @@ TimelineViewGhostItem::TimelineViewGhostItem(QGraphicsItem *parent) : TimelineViewRect(parent), - in_adj_(0), - out_adj_(0), track_adj_(0), stream_(nullptr), mode_(olive::timeline::kNone), @@ -40,6 +38,7 @@ TimelineViewGhostItem *TimelineViewGhostItem::FromBlock(Block *block, int track, ghost->SetIn(block->in()); ghost->SetOut(block->out()); + ghost->SetMediaIn(block->media_in()); ghost->SetTrack(track); ghost->SetY(y); ghost->SetHeight(height); @@ -78,6 +77,11 @@ const rational &TimelineViewGhostItem::Out() const return out_; } +const rational &TimelineViewGhostItem::MediaIn() const +{ + return media_in_; +} + rational TimelineViewGhostItem::Length() const { return out_ - in_; @@ -102,6 +106,11 @@ void TimelineViewGhostItem::SetOut(const rational &out) UpdateRect(); } +void TimelineViewGhostItem::SetMediaIn(const rational &media_in) +{ + media_in_ = media_in; +} + void TimelineViewGhostItem::SetInAdjustment(const rational &in_adj) { in_adj_ = in_adj; @@ -121,6 +130,11 @@ void TimelineViewGhostItem::SetTrackAdjustment(const int &track_adj) track_adj_ = track_adj; } +void TimelineViewGhostItem::SetMediaInAdjustment(const rational &media_in_adj) +{ + media_in_adj_ = media_in_adj; +} + const rational &TimelineViewGhostItem::InAdjustment() const { return in_adj_; @@ -131,6 +145,11 @@ const rational &TimelineViewGhostItem::OutAdjustment() const return out_adj_; } +const rational &TimelineViewGhostItem::MediaInAdjustment() const +{ + return media_in_adj_; +} + const int &TimelineViewGhostItem::TrackAdjustment() const { return track_adj_; @@ -146,6 +165,11 @@ rational TimelineViewGhostItem::GetAdjustedOut() const return out_ + out_adj_; } +rational TimelineViewGhostItem::GetAdjustedMediaIn() const +{ + return media_in_ + media_in_adj_; +} + int TimelineViewGhostItem::GetAdjustedTrack() const { return track_ + track_adj_; diff --git a/app/widget/timelineview/timelineviewghostitem.h b/app/widget/timelineview/timelineviewghostitem.h index b33e3a13e..80577590f 100644 --- a/app/widget/timelineview/timelineviewghostitem.h +++ b/app/widget/timelineview/timelineviewghostitem.h @@ -50,23 +50,28 @@ public: const rational& In() const; const rational& Out() const; + const rational& MediaIn() const; rational Length() const; rational AdjustedLength() const; void SetIn(const rational& in); void SetOut(const rational& out); + void SetMediaIn(const rational& media_in); void SetInAdjustment(const rational& in_adj); void SetOutAdjustment(const rational& out_adj); void SetTrackAdjustment(const int& track_adj); + void SetMediaInAdjustment(const rational& media_in_adj); const rational& InAdjustment() const; const rational& OutAdjustment() const; + const rational& MediaInAdjustment() const; const int& TrackAdjustment() const; rational GetAdjustedIn() const; rational GetAdjustedOut() const; + rational GetAdjustedMediaIn() const; int GetAdjustedTrack() const; const olive::timeline::MovementMode& mode() const; @@ -79,9 +84,11 @@ protected: private: rational in_; rational out_; + rational media_in_; rational in_adj_; rational out_adj_; + rational media_in_adj_; int track_adj_; diff --git a/app/widget/timelineview/tool/CMakeLists.txt b/app/widget/timelineview/tool/CMakeLists.txt index 830b77956..93d42e09d 100644 --- a/app/widget/timelineview/tool/CMakeLists.txt +++ b/app/widget/timelineview/tool/CMakeLists.txt @@ -23,6 +23,7 @@ set(OLIVE_SOURCES widget/timelineview/tool/ripple.cpp widget/timelineview/tool/rolling.cpp widget/timelineview/tool/slide.cpp + widget/timelineview/tool/slip.cpp widget/timelineview/tool/tool.cpp widget/timelineview/tool/zoom.cpp PARENT_SCOPE diff --git a/app/widget/timelineview/tool/pointer.cpp b/app/widget/timelineview/tool/pointer.cpp index 723c64133..414a5c024 100644 --- a/app/widget/timelineview/tool/pointer.cpp +++ b/app/widget/timelineview/tool/pointer.cpp @@ -94,7 +94,9 @@ void TimelineView::PointerTool::MouseRelease(QMouseEvent *event) // Default QGraphicsView behavior (item selection) parent()->QGraphicsView::mouseReleaseEvent(event); - MouseReleaseInternal(event); + if (!parent()->ghost_items_.isEmpty()) { + MouseReleaseInternal(event); + } if (dragging_) { parent()->ClearGhosts(); diff --git a/app/widget/timelineview/tool/ripple.cpp b/app/widget/timelineview/tool/ripple.cpp index 23f6fec7e..d030fe435 100644 --- a/app/widget/timelineview/tool/ripple.cpp +++ b/app/widget/timelineview/tool/ripple.cpp @@ -32,10 +32,6 @@ void TimelineView::RippleTool::MouseReleaseInternal(QMouseEvent *event) { Q_UNUSED(event) - if (parent()->ghost_items_.isEmpty()) { - return; - } - // For ripple operations, all ghosts will be moving the same way olive::timeline::MovementMode movement_mode = parent()->ghost_items_.first()->mode(); diff --git a/app/widget/timelineview/tool/rolling.cpp b/app/widget/timelineview/tool/rolling.cpp index 6cb2a6eab..f6e839c90 100644 --- a/app/widget/timelineview/tool/rolling.cpp +++ b/app/widget/timelineview/tool/rolling.cpp @@ -32,10 +32,6 @@ void TimelineView::RollingTool::MouseReleaseInternal(QMouseEvent *event) { Q_UNUSED(event) - if (parent()->ghost_items_.isEmpty()) { - return; - } - QUndoCommand* command = new QUndoCommand(); // Find earliest point to ripple around diff --git a/app/widget/timelineview/tool/slide.cpp b/app/widget/timelineview/tool/slide.cpp index 32b2c74af..8f466fb10 100644 --- a/app/widget/timelineview/tool/slide.cpp +++ b/app/widget/timelineview/tool/slide.cpp @@ -33,10 +33,6 @@ void TimelineView::SlideTool::MouseReleaseInternal(QMouseEvent *event) { Q_UNUSED(event) - if (parent()->ghost_items_.isEmpty()) { - return; - } - QUndoCommand* command = new QUndoCommand(); // Find earliest point to ripple around diff --git a/app/widget/timelineview/tool/slip.cpp b/app/widget/timelineview/tool/slip.cpp new file mode 100644 index 000000000..52ff93dfa --- /dev/null +++ b/app/widget/timelineview/tool/slip.cpp @@ -0,0 +1,83 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#include "widget/timelineview/timelineview.h" + +#include + +#include "common/timecodefunctions.h" +#include "config/config.h" + +TimelineView::SlipTool::SlipTool(TimelineView *parent) : + PointerTool(parent) +{ + SetTrimmingAllowed(false); + SetTrackMovementAllowed(false); +} + +void TimelineView::SlipTool::ProcessDrag(const QPoint &mouse_pos) +{ + // Retrieve cursor position difference + QPointF scene_pos = GetScenePos(mouse_pos); + QPointF movement = scene_pos - drag_start_; + + // Determine frame movement + rational time_movement = -parent()->SceneToTime(movement.x()); + + // Validate slip (enforce all ghosts moving in legal ways) + foreach (TimelineViewGhostItem* ghost, parent()->ghost_items_) { + if (ghost->MediaIn() + time_movement < 0) { + time_movement = -ghost->MediaIn(); + } + } + + // Perform slip + foreach (TimelineViewGhostItem* ghost, parent()->ghost_items_) { + ghost->SetMediaInAdjustment(time_movement); + } + + // Show tooltip + // Generate tooltip (showing earliest in point of imported clip) + int64_t earliest_timestamp = olive::time_to_timestamp(time_movement, parent()->timebase_); + QString tooltip_text = olive::timestamp_to_timecode(earliest_timestamp, + parent()->timebase_, + kTimecodeDisplay, + true); + QToolTip::showText(QCursor::pos(), + tooltip_text, + parent()); +} + +void TimelineView::SlipTool::MouseReleaseInternal(QMouseEvent *event) +{ + Q_UNUSED(event) + + QUndoCommand* command = new QUndoCommand(); + + // Find earliest point to ripple around + foreach (TimelineViewGhostItem* ghost, parent()->ghost_items_) { + Block* b = Node::ValueToPtr(ghost->data(TimelineViewGhostItem::kAttachedBlock)); + + new BlockSetMediaInCommand(b, ghost->GetAdjustedMediaIn(), command); + } + + olive::undo_stack.pushIfHasChildren(command); +} +