diff --git a/app/widget/timelineview/timelineview.h b/app/widget/timelineview/timelineview.h index 9799d43d8..1401f7c30 100644 --- a/app/widget/timelineview/timelineview.h +++ b/app/widget/timelineview/timelineview.h @@ -151,7 +151,9 @@ private: /** * @brief Snaps point `start_point` that is moving by `movement` to currently existing clips */ - bool SnapPoint(rational start_point, rational *movement, int snap_points = kSnapAll); + bool SnapPoint(QList start_times, rational *movement, int snap_points = kSnapAll); + + QList snap_points_; bool dragging_; diff --git a/app/widget/timelineview/tool/import.cpp b/app/widget/timelineview/tool/import.cpp index cdcbfa04c..dc5132bd6 100644 --- a/app/widget/timelineview/tool/import.cpp +++ b/app/widget/timelineview/tool/import.cpp @@ -61,6 +61,8 @@ void TimelineView::ImportTool::DragEnter(QDragEnterEvent *event) // Set ghosts to start where the cursor entered rational ghost_start = parent()->SceneToTime(drag_start_.x() - import_pre_buffer_); + snap_points_.clear(); + while (!stream.atEnd()) { stream >> r >> item_ptr; @@ -89,6 +91,10 @@ void TimelineView::ImportTool::DragEnter(QDragEnterEvent *event) ghost->SetIn(ghost_start); ghost->SetOut(ghost_start + footage_duration); + + snap_points_.append(ghost->In()); + snap_points_.append(ghost->Out()); + ghost->setData(0, QVariant::fromValue(stream)); ghost->SetMode(TimelineViewGhostItem::kMove); @@ -122,12 +128,7 @@ void TimelineView::ImportTool::DragMove(QDragMoveEvent *event) // If snapping is enabled, check for snap points if (olive::core.snapping()) { - foreach (TimelineViewGhostItem* ghost, parent()->ghost_items_) { - if (SnapPoint(ghost->In(), &time_movement) - || SnapPoint(ghost->Out(), &time_movement)) { - break; - } - } + SnapPoint(snap_points_, &time_movement); } // Move ghosts to the mouse cursor diff --git a/app/widget/timelineview/tool/pointer.cpp b/app/widget/timelineview/tool/pointer.cpp index e4dd9220c..7176ac4fc 100644 --- a/app/widget/timelineview/tool/pointer.cpp +++ b/app/widget/timelineview/tool/pointer.cpp @@ -22,6 +22,8 @@ #include +#include "common/range.h" +#include "core.h" #include "node/block/gap/gap.h" TimelineView::PointerTool::PointerTool(TimelineView *parent) : @@ -61,10 +63,13 @@ void TimelineView::PointerTool::MouseMove(QMouseEvent *event) TimelineViewRect* clicked_item = static_cast(GetItemAtScenePos(drag_start_)); + snap_points_.clear(); + // Let's see if there's anything selected to drag if (clicked_item != nullptr) { TimelineViewGhostItem::Mode trim_mode; + if (drag_start_.x() < clicked_item->x() + clicked_item->rect().left() + 20) { trim_mode = TimelineViewGhostItem::kTrimIn; } else if (drag_start_.x() > clicked_item->x() + clicked_item->rect().right() - 20) { @@ -85,6 +90,21 @@ void TimelineView::PointerTool::MouseMove(QMouseEvent *event) 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); + + switch (trim_mode) { + case TimelineViewGhostItem::kMove: + snap_points_.append(ghost->In()); + snap_points_.append(ghost->Out()); + break; + case TimelineViewGhostItem::kTrimIn: + snap_points_.append(ghost->In()); + break; + case TimelineViewGhostItem::kTrimOut: + snap_points_.append(ghost->Out()); + break; + default: + break; + } } else { ghost->SetMode(TimelineViewGhostItem::kNone); } @@ -112,6 +132,11 @@ void TimelineView::PointerTool::MouseMove(QMouseEvent *event) time_movement = ValidateOutTrimming(time_movement, parent()->ghost_items_); track_movement = ValidateTrackMovement(track_movement, parent()->ghost_items_); + // Perform snapping if enabled + if (olive::core.snapping()) { + SnapPoint(snap_points_, &time_movement); + } + // Perform movement foreach (TimelineViewGhostItem* ghost, parent()->ghost_items_) { switch (ghost->mode()) { diff --git a/app/widget/timelineview/tool/tool.cpp b/app/widget/timelineview/tool/tool.cpp index f8893b9fc..f1a34c59c 100644 --- a/app/widget/timelineview/tool/tool.cpp +++ b/app/widget/timelineview/tool/tool.cpp @@ -136,32 +136,39 @@ rational TimelineView::Tool::ValidateOutTrimming(rational movement, const QVecto return movement; } -void AttemptSnap(double proposed_point, +void AttemptSnap(const QList& proposed_pts, double compare_point, - rational start_time, + const QList& start_times, rational compare_time, rational* movement, double* diff) { const qreal kSnapRange = 10; // FIXME: Hardcoded number - // Attempt snapping to clip out point - if (InRange(proposed_point, compare_point, kSnapRange)) { - double this_diff = qAbs(compare_point - proposed_point); + for (int i=0;i= 0) { + *movement = compare_time - start_times.at(i); + *diff = this_diff; + } } } } -bool TimelineView::Tool::SnapPoint(rational start_point, rational* movement, int snap_points) +bool TimelineView::Tool::SnapPoint(QList start_times, rational* movement, int snap_points) { QList items = parent()->scene_.items(); double diff = DBL_MAX; - double proposed_point = (start_point + *movement).toDouble() * parent()->scale_; + QList proposed_pts; + + foreach (rational s, start_times) { + proposed_pts.append((s + *movement).toDouble() * parent()->scale_); + } if (snap_points & kSnapToPlayhead) { qreal playhead_pos = parent()->playhead_line_->x(); @@ -169,7 +176,7 @@ bool TimelineView::Tool::SnapPoint(rational start_point, rational* movement, int rational playhead_abs_time = rational(parent()->playhead_ * parent()->timebase_.numerator(), parent()->timebase_.denominator()); - AttemptSnap(proposed_point, playhead_pos, start_point, playhead_abs_time, movement, &diff); + AttemptSnap(proposed_pts, playhead_pos, start_times, playhead_abs_time, movement, &diff); } if (snap_points & kSnapToClips) { @@ -181,10 +188,10 @@ bool TimelineView::Tool::SnapPoint(rational start_point, rational* movement, int qreal rect_right = rect_left + timeline_rect->rect().width(); // Attempt snapping to clip in point - AttemptSnap(proposed_point, rect_left, start_point, timeline_rect->clip()->in(), movement, &diff); + AttemptSnap(proposed_pts, rect_left, start_times, timeline_rect->clip()->in(), movement, &diff); // Attempt snapping to clip out point - AttemptSnap(proposed_point, rect_right, start_point, timeline_rect->clip()->out(), movement, &diff); + AttemptSnap(proposed_pts, rect_right, start_times, timeline_rect->clip()->out(), movement, &diff); } } }