diff --git a/app/node/block/block.h b/app/node/block/block.h index 7976e271b..8fe6b5cb0 100644 --- a/app/node/block/block.h +++ b/app/node/block/block.h @@ -42,7 +42,6 @@ public: enum Type { kClip, kGap, - kTrack, kTransition }; diff --git a/app/node/output/track/track.cpp b/app/node/output/track/track.cpp index 07cbf39e4..e1ec0933b 100644 --- a/app/node/output/track/track.cpp +++ b/app/node/output/track/track.cpp @@ -60,7 +60,7 @@ const Timeline::TrackType& TrackOutput::track_type() Block::Type TrackOutput::type() const { - return kTrack; + return kClip; } Block *TrackOutput::copy() const diff --git a/app/widget/curvewidget/curvewidget.cpp b/app/widget/curvewidget/curvewidget.cpp index 14584a463..b4cb73a87 100644 --- a/app/widget/curvewidget/curvewidget.cpp +++ b/app/widget/curvewidget/curvewidget.cpp @@ -145,10 +145,12 @@ const double &CurveWidget::GetScale() return ruler_->scale(); } -void CurveWidget::SetScale(const double &scale) +void CurveWidget::SetScale(double scale) { + scale = qMin(scale, TimelineViewBase::kMaximumScale); + ruler_->SetScale(scale); - view_->SetScale(scale); + view_->SetScale(scale, true); } const double &CurveWidget::GetVerticalScale() diff --git a/app/widget/curvewidget/curvewidget.h b/app/widget/curvewidget/curvewidget.h index 8d09d64ea..74e711582 100644 --- a/app/widget/curvewidget/curvewidget.h +++ b/app/widget/curvewidget/curvewidget.h @@ -31,7 +31,7 @@ public: void SetVerticalScale(const double& vscale); public slots: - void SetScale(const double& scale); + void SetScale(double scale); signals: void TimeChanged(const int64_t& timestamp); diff --git a/app/widget/nodeparamview/nodeparamview.cpp b/app/widget/nodeparamview/nodeparamview.cpp index a01edec94..712d90be8 100644 --- a/app/widget/nodeparamview/nodeparamview.cpp +++ b/app/widget/nodeparamview/nodeparamview.cpp @@ -179,10 +179,12 @@ const double &NodeParamView::GetScale() const return ruler_->scale(); } -void NodeParamView::SetScale(const double& scale) +void NodeParamView::SetScale(double scale) { + scale = qMin(scale, TimelineViewBase::kMaximumScale); + ruler_->SetScale(scale); - keyframe_view_->SetScale(scale); + keyframe_view_->SetScale(scale, true); } void NodeParamView::SetTime(const int64_t ×tamp) diff --git a/app/widget/nodeparamview/nodeparamview.h b/app/widget/nodeparamview/nodeparamview.h index 800bac25b..97ff5ff5c 100644 --- a/app/widget/nodeparamview/nodeparamview.h +++ b/app/widget/nodeparamview/nodeparamview.h @@ -41,7 +41,7 @@ public: const double& GetScale() const; public slots: - void SetScale(const double &scale); + void SetScale(double scale); void SetTime(const int64_t& timestamp); diff --git a/app/widget/timelinewidget/timelinewidget.cpp b/app/widget/timelinewidget/timelinewidget.cpp index db41c7a45..dfb827126 100644 --- a/app/widget/timelinewidget/timelinewidget.cpp +++ b/app/widget/timelinewidget/timelinewidget.cpp @@ -616,9 +616,9 @@ void TimelineWidget::CenterOn(qreal scene_pos) horizontal_scroll_->setValue(qRound(scene_pos - horizontal_scroll_->width()/2)); } -void TimelineWidget::SetScale(double scale) +void TimelineWidget::SetScale(double scale, bool center_on_playhead) { - scale_ = scale; + scale_ = qMin(scale, TimelineViewBase::kMaximumScale); ruler_->SetScale(scale_); @@ -637,7 +637,7 @@ void TimelineWidget::SetScale(double scale) } foreach (TimelineAndTrackView* view, views_) { - view->view()->SetScale(scale_); + view->view()->SetScale(scale_, center_on_playhead); } } @@ -768,9 +768,6 @@ void TimelineWidget::AddBlock(Block *block, TrackReference track) connect(block, SIGNAL(Refreshed()), this, SLOT(BlockChanged())); break; } - case Block::kTrack: - // Do nothing - break; } } @@ -870,6 +867,11 @@ void TimelineWidget::ShowSpeedDurationDialog() speed_diag.exec(); } +void TimelineWidget::DeferredScrollAction() +{ + horizontal_scroll_->setValue(deferred_scroll_value_); +} + void TimelineWidget::AddGhost(TimelineViewGhostItem *ghost) { ghost->SetScale(scale_); @@ -888,20 +890,24 @@ void TimelineWidget::SetBlockLinksSelected(Block* block, bool selected) } } -void TimelineWidget::StartRubberBandSelect(bool select_links) +void TimelineWidget::StartRubberBandSelect(bool enable_selecting, bool select_links) { drag_origin_ = QCursor::pos(); rubberband_.show(); - MoveRubberBandSelect(select_links); + MoveRubberBandSelect(enable_selecting, select_links); } -void TimelineWidget::MoveRubberBandSelect(bool select_links) +void TimelineWidget::MoveRubberBandSelect(bool enable_selecting, bool select_links) { QPoint rubberband_now = QCursor::pos(); rubberband_.setGeometry(QRect(mapFromGlobal(drag_origin_), mapFromGlobal(rubberband_now)).normalized()); + if (!enable_selecting) { + return; + } + QList new_selected_list; foreach (TimelineAndTrackView* tview, views_) { @@ -954,9 +960,9 @@ void TimelineWidget::MoveRubberBandSelect(bool select_links) rubberband_now_selected_ = new_selected_list; } -void TimelineWidget::EndRubberBandSelect(bool select_links) +void TimelineWidget::EndRubberBandSelect(bool enable_selecting, bool select_links) { - MoveRubberBandSelect(select_links); + MoveRubberBandSelect(enable_selecting, select_links); rubberband_.hide(); rubberband_now_selected_.clear(); } diff --git a/app/widget/timelinewidget/timelinewidget.h b/app/widget/timelinewidget/timelinewidget.h index d20b69783..722689c42 100644 --- a/app/widget/timelinewidget/timelinewidget.h +++ b/app/widget/timelinewidget/timelinewidget.h @@ -300,6 +300,7 @@ private: virtual void MousePress(TimelineViewMouseEvent *event) override; virtual void MouseMove(TimelineViewMouseEvent *event) override; virtual void MouseRelease(TimelineViewMouseEvent *event) override; + }; class AddTool : public Tool @@ -337,9 +338,9 @@ private: QPoint drag_origin_; - void StartRubberBandSelect(bool select_links); - void MoveRubberBandSelect(bool select_links); - void EndRubberBandSelect(bool select_links); + void StartRubberBandSelect(bool enable_selecting, bool select_links); + void MoveRubberBandSelect(bool enable_selecting, bool select_links); + void EndRubberBandSelect(bool enable_selecting, bool select_links); QRubberBand rubberband_; QList rubberband_now_selected_; @@ -377,6 +378,8 @@ private: TimeSlider* timecode_label_; + int deferred_scroll_value_; + int GetTrackY(const TrackReference& ref); int GetTrackHeight(const TrackReference& ref); @@ -385,7 +388,7 @@ private: void AddGhost(TimelineViewGhostItem* ghost); private slots: - void SetScale(double scale); + void SetScale(double scale, bool center_on_playhead = true); void UpdateInternalTime(const int64_t& timestamp); @@ -425,6 +428,8 @@ private slots: void ShowSpeedDurationDialog(); + void DeferredScrollAction(); + }; #endif // TIMELINEWIDGET_H diff --git a/app/widget/timelinewidget/tool/pointer.cpp b/app/widget/timelinewidget/tool/pointer.cpp index 6167ace84..1eb1511c3 100644 --- a/app/widget/timelinewidget/tool/pointer.cpp +++ b/app/widget/timelinewidget/tool/pointer.cpp @@ -91,7 +91,7 @@ void TimelineWidget::PointerTool::MousePress(TimelineViewMouseEvent *event) } } else { // Start rubberband drag - parent()->StartRubberBandSelect(!(event->GetModifiers() & Qt::AltModifier)); + parent()->StartRubberBandSelect(true, !(event->GetModifiers() & Qt::AltModifier)); rubberband_selecting_ = true; } @@ -102,7 +102,7 @@ void TimelineWidget::PointerTool::MouseMove(TimelineViewMouseEvent *event) if (rubberband_selecting_) { // Process rubberband select - parent()->MoveRubberBandSelect(!(event->GetModifiers() & Qt::AltModifier)); + parent()->MoveRubberBandSelect(true, !(event->GetModifiers() & Qt::AltModifier)); } else if (!dragging_) { // Now that the cursor has moved, we will assume the intention is to drag @@ -124,7 +124,7 @@ void TimelineWidget::PointerTool::MouseMove(TimelineViewMouseEvent *event) void TimelineWidget::PointerTool::MouseRelease(TimelineViewMouseEvent *event) { if (rubberband_selecting_) { - parent()->EndRubberBandSelect(!(event->GetModifiers() & Qt::AltModifier)); + parent()->EndRubberBandSelect(true, !(event->GetModifiers() & Qt::AltModifier)); rubberband_selecting_ = false; return; diff --git a/app/widget/timelinewidget/tool/zoom.cpp b/app/widget/timelinewidget/tool/zoom.cpp index 1ee48aec6..4d5b2143d 100644 --- a/app/widget/timelinewidget/tool/zoom.cpp +++ b/app/widget/timelinewidget/tool/zoom.cpp @@ -32,28 +32,59 @@ void TimelineWidget::ZoomTool::MousePress(TimelineViewMouseEvent *event) void TimelineWidget::ZoomTool::MouseMove(TimelineViewMouseEvent *event) { - Q_UNUSED(event) + if (dragging_) { + parent()->MoveRubberBandSelect(false, false); + } else { + parent()->StartRubberBandSelect(false, false); + + dragging_ = true; + } } void TimelineWidget::ZoomTool::MouseRelease(TimelineViewMouseEvent *event) { - double scale = parent()->scale_; + if (dragging_) { + // Zoom into the rubberband selection + QRect screen_coords = parent()->rubberband_.geometry(); - // Normalize zoom location for 1.0 scale - double frame_x = parent()->TimeToScene(event->GetFrame()); + parent()->EndRubberBandSelect(false, false); - if (event->GetModifiers() & Qt::AltModifier) { - // Zoom out if the user clicks while holding Alt - scale *= 0.5; + TimelineView* reference_view = parent()->views_.first()->view(); + QPointF scene_topleft = reference_view->mapToScene(reference_view->mapFrom(parent(), screen_coords.topLeft())); + QPointF scene_bottomright = reference_view->mapToScene(reference_view->mapFrom(parent(), screen_coords.bottomRight())); + + double scene_left = scene_topleft.x(); + double scene_right = scene_bottomright.x(); + + // Normalize scale to 1.0 scale + double scene_width = (scene_right - scene_left) / parent()->scale_; + + double new_scale = qMin(TimelineViewBase::kMaximumScale, static_cast(reference_view->viewport()->width()) / scene_width); + parent()->deferred_scroll_value_ = qMax(0, qRound(scene_left / parent()->scale_ * new_scale)); + + parent()->SetScale(new_scale, false); + + dragging_ = false; } else { - // Otherwise zoom in - scale *= 2; + // Simple zoom in/out at the cursor position + double scale = parent()->scale_; + + if (event->GetModifiers() & Qt::AltModifier) { + // Zoom out if the user clicks while holding Alt + scale *= 0.5; + } else { + // Otherwise zoom in + scale *= 2.0; + } + + parent()->SetScale(scale, false); + + // Adjust scroll location for new scale + double frame_x = event->GetFrame().toDouble() * scale; + + parent()->deferred_scroll_value_ = qMax(0, qRound(frame_x - parent()->views_.first()->view()->viewport()->width()/2)); } - parent()->SetScale(scale); - - // Adjust zoom location for new scale - frame_x *= scale; - - parent()->CenterOn(frame_x); + // (using a hacky singleShot so the scroll occurs after the scene and its scrollbars have updated) + QTimer::singleShot(0, parent(), &TimelineWidget::DeferredScrollAction); } diff --git a/app/widget/timelinewidget/view/timelineviewbase.cpp b/app/widget/timelinewidget/view/timelineviewbase.cpp index c0e50e9b9..ecded975f 100644 --- a/app/widget/timelinewidget/view/timelineviewbase.cpp +++ b/app/widget/timelinewidget/view/timelineviewbase.cpp @@ -9,6 +9,8 @@ #include "common/timecodefunctions.h" #include "config/config.h" +const double TimelineViewBase::kMaximumScale = 8192; + TimelineViewBase::TimelineViewBase(QWidget *parent) : QGraphicsView(parent), playhead_(0), @@ -25,7 +27,7 @@ TimelineViewBase::TimelineViewBase(QWidget *parent) : scene_.addItem(end_item_); // Set default scale - SetScale(1.0); + SetScale(1.0, true); SetDefaultDragMode(NoDrag); @@ -35,9 +37,9 @@ TimelineViewBase::TimelineViewBase(QWidget *parent) : connect(Core::instance(), &Core::ToolChanged, this, &TimelineViewBase::ApplicationToolChanged); } -void TimelineViewBase::SetScale(const double &scale) +void TimelineViewBase::SetScale(const double &scale, bool center_on_playhead) { - scale_ = scale; + scale_ = qMin(scale, kMaximumScale); end_item_->SetScale(scale_); @@ -46,9 +48,11 @@ void TimelineViewBase::SetScale(const double &scale) // Force redraw for playhead viewport()->update(); - // Zoom towards the playhead - // (using a hacky singleShot so the scroll occurs after the scene and its scrollbars have updated) - QTimer::singleShot(0, this, &TimelineViewBase::CenterScrollOnPlayhead); + if (center_on_playhead) { + // Zoom towards the playhead + // (using a hacky singleShot so the scroll occurs after the scene and its scrollbars have updated) + QTimer::singleShot(0, this, &TimelineViewBase::CenterScrollOnPlayhead); + } } void TimelineViewBase::SetTimebase(const rational &timebase) diff --git a/app/widget/timelinewidget/view/timelineviewbase.h b/app/widget/timelinewidget/view/timelineviewbase.h index 2caadb8df..dfaa12c2f 100644 --- a/app/widget/timelinewidget/view/timelineviewbase.h +++ b/app/widget/timelinewidget/view/timelineviewbase.h @@ -14,10 +14,12 @@ class TimelineViewBase : public QGraphicsView, public TimelineScaledObject public: TimelineViewBase(QWidget* parent = nullptr); - void SetScale(const double& scale); + void SetScale(const double& scale, bool center_on_playhead); void SetEndTime(const rational& length); + static const double kMaximumScale; + public slots: void SetTimebase(const rational& timebase); diff --git a/app/widget/timelinewidget/view/timelineviewblockitem.cpp b/app/widget/timelinewidget/view/timelineviewblockitem.cpp index c90837e76..836e9959b 100644 --- a/app/widget/timelinewidget/view/timelineviewblockitem.cpp +++ b/app/widget/timelinewidget/view/timelineviewblockitem.cpp @@ -176,7 +176,5 @@ void TimelineViewBlockItem::paint(QPainter *painter, const QStyleOptionGraphicsI } break; } - case Block::kTrack: - break; } }