From 9439494c109a86cfdf263459787d75ed5dc4724e Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 23 Aug 2019 12:12:13 +1000 Subject: [PATCH] added basic razor tool --- app/node/output/timeline/timeline.cpp | 16 ++++++ app/node/output/timeline/timeline.h | 10 ++++ app/node/output/track/track.cpp | 17 +++++++ app/node/output/track/track.h | 7 +++ app/widget/timelineview/timelineview.cpp | 51 +++++++++++++++++-- app/widget/timelineview/timelineview.h | 16 ++++++ app/widget/timelineview/tool/CMakeLists.txt | 1 + app/widget/timelineview/tool/pointer.cpp | 12 ++--- app/widget/timelineview/tool/razor.cpp | 56 +++++++++++++++++++++ 9 files changed, 175 insertions(+), 11 deletions(-) create mode 100644 app/widget/timelineview/tool/razor.cpp diff --git a/app/node/output/timeline/timeline.cpp b/app/node/output/timeline/timeline.cpp index 6a1140721..b7c0e1639 100644 --- a/app/node/output/timeline/timeline.cpp +++ b/app/node/output/timeline/timeline.cpp @@ -64,6 +64,7 @@ void TimelineOutput::AttachTimeline(TimelinePanel *timeline) //disconnect(view, SIGNAL(RequestInsertBlockAtIndex(Block*, int)), this, SLOT(InsertBlockAtIndex(Block*, int))); disconnect(view, SIGNAL(RequestPlaceBlock(Block*, rational, int)), this, SLOT(PlaceBlock(Block*, rational, int))); disconnect(view, SIGNAL(RequestReplaceBlock(Block*, Block*, int)), this, SLOT(ReplaceBlock(Block*, Block*, int))); + disconnect(view, SIGNAL(RequestSplitAtTime(rational, int)), this, SLOT(SplitAtTime(rational, int))); // Remove existing UI objects from TimelinePanel attached_timeline_->Clear(); @@ -86,6 +87,7 @@ void TimelineOutput::AttachTimeline(TimelinePanel *timeline) //connect(view, SIGNAL(RequestInsertBlockAtIndex(Block*, int)), this, SLOT(InsertBlockAtIndex(Block*, int))); connect(view, SIGNAL(RequestPlaceBlock(Block*, rational, int)), this, SLOT(PlaceBlock(Block*, rational, int))); connect(view, SIGNAL(RequestReplaceBlock(Block*, Block*, int)), this, SLOT(ReplaceBlock(Block*, Block*, int))); + connect(view, SIGNAL(RequestSplitAtTime(rational, int)), this, SLOT(SplitAtTime(rational, int))); } } @@ -255,3 +257,17 @@ void TimelineOutput::ReplaceBlock(Block *old, Block *replace, int track) { track_cache_.at(track)->ReplaceBlock(old, replace); } + +void TimelineOutput::SplitAtTime(rational time, int track) +{ + if (track >= track_cache_.size()) { + return; + } + + track_cache_.at(track)->SplitAtTime(time); +} + +void TimelineOutput::ResizeBlock(Block *block, rational new_length) +{ + block->set_length(new_length); +} diff --git a/app/node/output/timeline/timeline.h b/app/node/output/timeline/timeline.h index 0b8c76d41..e47f80467 100644 --- a/app/node/output/timeline/timeline.h +++ b/app/node/output/timeline/timeline.h @@ -112,6 +112,16 @@ private slots: */ void ReplaceBlock(Block* old, Block* replace, int track); + /** + * @brief Forwards a SplitAtTime signal to the appropriate track + */ + void SplitAtTime(rational time, int track); + + /** + * @brief Resizes a Block + */ + void ResizeBlock(Block* block, rational new_length); + }; #endif // TIMELINEOUTPUT_H diff --git a/app/node/output/track/track.cpp b/app/node/output/track/track.cpp index 4b426c002..471467632 100644 --- a/app/node/output/track/track.cpp +++ b/app/node/output/track/track.cpp @@ -327,6 +327,23 @@ Block* TrackOutput::SplitBlock(Block *block, rational time) return copy; } +void TrackOutput::SplitAtTime(rational time) +{ + // Find Block that contains this time + for (int i=0;iout() == time) { + // This time is between blocks, no split needs to occur + return; + } else if (b->in() < time && b->out() > time) { + // We found the Block, split it + SplitBlock(b, time); + return; + } + } +} + void TrackOutput::RippleRemoveArea(rational in, rational out, Block *insert) { // Block that needs to be split to remove this area diff --git a/app/node/output/track/track.h b/app/node/output/track/track.h index 48b77bfee..e884d0bd2 100644 --- a/app/node/output/track/track.h +++ b/app/node/output/track/track.h @@ -116,6 +116,13 @@ public: */ Block *SplitBlock(Block* block, rational time); + /** + * @brief Attempt to split at a certain time + * + * Finds the Block that surrounds this time and splits it. If there is no Block there, this is a no-op. + */ + void SplitAtTime(rational time); + /** * @brief Clears the area between in and out * diff --git a/app/widget/timelineview/timelineview.cpp b/app/widget/timelineview/timelineview.cpp index 455b8d44f..53725899b 100644 --- a/app/widget/timelineview/timelineview.cpp +++ b/app/widget/timelineview/timelineview.cpp @@ -27,13 +27,16 @@ #include #include +#include "core.h" #include "node/input/media/media.h" #include "project/item/footage/footage.h" +#include "tool/tool.h" TimelineView::TimelineView(QWidget *parent) : QGraphicsView(parent), pointer_tool_(this), import_tool_(this), + razor_tool_(this), playhead_(0) { setScene(&scene_); @@ -145,17 +148,25 @@ void TimelineView::SetTime(const int64_t time) void TimelineView::mousePressEvent(QMouseEvent *event) { - pointer_tool_.MousePress(event); + active_tool_ = GetActiveTool(); + + if (active_tool_ != nullptr) { + active_tool_->MousePress(event); + } } void TimelineView::mouseMoveEvent(QMouseEvent *event) { - pointer_tool_.MouseMove(event); + if (active_tool_ != nullptr) { + active_tool_->MouseMove(event); + } } void TimelineView::mouseReleaseEvent(QMouseEvent *event) { - pointer_tool_.MouseRelease(event); + if (active_tool_ != nullptr) { + active_tool_->MouseRelease(event); + } } void TimelineView::dragEnterEvent(QDragEnterEvent *event) @@ -185,6 +196,40 @@ void TimelineView::resizeEvent(QResizeEvent *event) UpdateSceneRect(); } +TimelineView::Tool *TimelineView::GetActiveTool() +{ + switch (olive::core.tool()) { + case olive::tool::kNone: + return nullptr; + case olive::tool::kPointer: + return &pointer_tool_; + case olive::tool::kEdit: + return nullptr; // FIXME: Implement + case olive::tool::kRipple: + return nullptr; // FIXME: Implement + case olive::tool::kRolling: + return nullptr; // FIXME: Implement + case olive::tool::kRazor: + return &razor_tool_; + case olive::tool::kSlip: + return nullptr; // FIXME: Implement + case olive::tool::kSlide: + return nullptr; // FIXME: Implement + case olive::tool::kHand: + return nullptr; // FIXME: Implement + case olive::tool::kZoom: + return nullptr; // FIXME: Implement + case olive::tool::kTransition: + return nullptr; // FIXME: Implement + case olive::tool::kRecord: + return nullptr; // FIXME: Implement + case olive::tool::kAdd: + return nullptr; // FIXME: Implement + } + + return nullptr; +} + int TimelineView::GetTrackY(int track_index) { int y = 0; diff --git a/app/widget/timelineview/timelineview.h b/app/widget/timelineview/timelineview.h index 57af1831b..4fed1f35e 100644 --- a/app/widget/timelineview/timelineview.h +++ b/app/widget/timelineview/timelineview.h @@ -61,6 +61,7 @@ public slots: signals: void RequestPlaceBlock(Block* block, rational start, int track); void RequestReplaceBlock(Block* old, Block* replace, int track); + void RequestSplitAtTime(rational time, int track); protected: virtual void mousePressEvent(QMouseEvent *event) override; @@ -175,11 +176,24 @@ private: int import_pre_buffer_; }; + class RazorTool : public Tool + { + public: + RazorTool(TimelineView* parent); + + virtual void MousePress(QMouseEvent *event); + virtual void MouseMove(QMouseEvent *event); + virtual void MouseRelease(QMouseEvent *event); + }; + + Tool* GetActiveTool(); + int GetTrackY(int track_index); int GetTrackHeight(int track_index); PointerTool pointer_tool_; ImportTool import_tool_; + RazorTool razor_tool_; void AddGhost(TimelineViewGhostItem* ghost); @@ -208,6 +222,8 @@ private: TimelineViewPlayheadItem* playhead_line_; + Tool* active_tool_; + private slots: /** * @brief Slot for when a Block node changes its parameters and the graphics need to update diff --git a/app/widget/timelineview/tool/CMakeLists.txt b/app/widget/timelineview/tool/CMakeLists.txt index 9c974d975..5bfeda7f6 100644 --- a/app/widget/timelineview/tool/CMakeLists.txt +++ b/app/widget/timelineview/tool/CMakeLists.txt @@ -18,6 +18,7 @@ set(OLIVE_SOURCES ${OLIVE_SOURCES} widget/timelineview/tool/import.cpp widget/timelineview/tool/pointer.cpp + widget/timelineview/tool/razor.cpp widget/timelineview/tool/tool.cpp PARENT_SCOPE ) diff --git a/app/widget/timelineview/tool/pointer.cpp b/app/widget/timelineview/tool/pointer.cpp index 252fcf0cc..e4dd9220c 100644 --- a/app/widget/timelineview/tool/pointer.cpp +++ b/app/widget/timelineview/tool/pointer.cpp @@ -81,17 +81,13 @@ void TimelineView::PointerTool::MouseMove(QMouseEvent *event) ghost->SetScale(parent()->scale_); - /* // Determine correct mode for ghost - if (trim_mode == TimelineViewGhostItem::kMove) { - // Movement is indiscriminate, all the ghosts can be set to this - ghost->SetMode(TimelineViewGhostItem::kMove); + if (trim_mode == TimelineViewGhostItem::kMove // Movement is indiscriminate, all the ghosts can be set to this + || clip_item == clicked_item) { // Trimming should only be the currently clicked Block + ghost->SetMode(trim_mode); } else { - + ghost->SetMode(TimelineViewGhostItem::kNone); } - */ - // FIXME: Determine correct modes - ghost->SetMode(trim_mode); parent()->ghost_items_.append(ghost); parent()->scene_.addItem(ghost); diff --git a/app/widget/timelineview/tool/razor.cpp b/app/widget/timelineview/tool/razor.cpp new file mode 100644 index 000000000..e68a4501a --- /dev/null +++ b/app/widget/timelineview/tool/razor.cpp @@ -0,0 +1,56 @@ +/*** + + 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" + +TimelineView::RazorTool::RazorTool(TimelineView* parent) : + Tool(parent) +{ +} + +void TimelineView::RazorTool::MousePress(QMouseEvent *event) +{ + MouseMove(event); +} + +void TimelineView::RazorTool::MouseMove(QMouseEvent *event) +{ + if (!dragging_) { + drag_start_ = GetScenePos(event->pos()); + dragging_ = true; + } + + QPointF current_scene_pos = GetScenePos(event->pos()); + + // Always split at the same time + rational split_time = parent()->SceneToTime(drag_start_.x()); + + // Split at the current cursor track + int split_track = parent()->SceneToTrack(current_scene_pos.y()); + + emit parent()->RequestSplitAtTime(split_time, split_track); +} + +void TimelineView::RazorTool::MouseRelease(QMouseEvent *event) +{ + Q_UNUSED(event) + + dragging_ = false; +}