reworked and vastly improved snapping subsystem
This commit is contained in:
@@ -54,6 +54,7 @@
|
||||
#include "widget/menu/menu.h"
|
||||
#include "widget/menu/menushared.h"
|
||||
#include "widget/nodeview/nodeviewundo.h"
|
||||
#include "widget/timeruler/timeruler.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -82,7 +83,6 @@ TimelineWidget::TimelineWidget(QWidget *parent) :
|
||||
ruler_and_time_layout->addWidget(timecode_label_);
|
||||
|
||||
ruler_and_time_layout->addWidget(ruler());
|
||||
ruler()->SetSnapService(this);
|
||||
|
||||
// Create list of TimelineViews - these MUST correspond to the ViewType enum
|
||||
|
||||
@@ -1515,13 +1515,6 @@ void TimelineWidget::EditTo(Timeline::MovementMode mode)
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
}
|
||||
|
||||
void TimelineWidget::ShowSnap(const QVector<rational> ×)
|
||||
{
|
||||
foreach (TimelineAndTrackView* tview, views_) {
|
||||
tview->view()->EnableSnap(times);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::UpdateViewports(const Track::Type &type)
|
||||
{
|
||||
if (type == Track::kNone) {
|
||||
@@ -1573,13 +1566,6 @@ QVector<Block *> TimelineWidget::GetBlocksInGlobalRect(const QPoint &p1, const Q
|
||||
return blocks_in_rect;
|
||||
}
|
||||
|
||||
void TimelineWidget::HideSnaps()
|
||||
{
|
||||
foreach (TimelineAndTrackView* tview, views_) {
|
||||
tview->view()->DisableSnap();
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray TimelineWidget::SaveSplitterState() const
|
||||
{
|
||||
return view_splitter_->saveState();
|
||||
@@ -1734,109 +1720,6 @@ Block *TimelineWidget::GetItemAtScenePos(const TimelineCoordinate& coord)
|
||||
return views_.at(coord.GetTrack().type())->view()->GetItemAtScenePos(coord.GetFrame(), coord.GetTrack().index());
|
||||
}
|
||||
|
||||
struct SnapData {
|
||||
rational time;
|
||||
rational movement;
|
||||
};
|
||||
|
||||
QVector<SnapData> AttemptSnap(const QVector<double>& screen_pt,
|
||||
double compare_pt,
|
||||
const QVector<rational>& start_times,
|
||||
const rational& compare_time) {
|
||||
const qreal kSnapRange = 10; // FIXME: Hardcoded number
|
||||
|
||||
QVector<SnapData> snap_data;
|
||||
|
||||
for (int i=0;i<screen_pt.size();i++) {
|
||||
// Attempt snapping to clip out point
|
||||
if (InRange(screen_pt.at(i), compare_pt, kSnapRange)) {
|
||||
snap_data.append({compare_time, compare_time - start_times.at(i)});
|
||||
}
|
||||
}
|
||||
|
||||
return snap_data;
|
||||
}
|
||||
|
||||
bool TimelineWidget::SnapPoint(QVector<rational> start_times, rational* movement, int snap_points)
|
||||
{
|
||||
if (!GetConnectedNode()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QVector<double> screen_pt;
|
||||
|
||||
foreach (const rational& s, start_times) {
|
||||
screen_pt.append(TimeToScene(s + *movement));
|
||||
}
|
||||
|
||||
QVector<SnapData> potential_snaps;
|
||||
|
||||
if (snap_points & kSnapToPlayhead) {
|
||||
rational playhead_abs_time = GetTime();
|
||||
qreal playhead_pos = TimeToScene(playhead_abs_time);
|
||||
potential_snaps.append(AttemptSnap(screen_pt, playhead_pos, start_times, playhead_abs_time));
|
||||
}
|
||||
|
||||
if (snap_points & kSnapToClips) {
|
||||
foreach (Block* b, added_blocks_) {
|
||||
qreal rect_left = TimeToScene(b->in());
|
||||
qreal rect_right = TimeToScene(b->out());
|
||||
|
||||
// Attempt snapping to clip in point
|
||||
potential_snaps.append(AttemptSnap(screen_pt, rect_left, start_times, b->in()));
|
||||
|
||||
// Attempt snapping to clip out point
|
||||
potential_snaps.append(AttemptSnap(screen_pt, rect_right, start_times, b->out()));
|
||||
}
|
||||
}
|
||||
|
||||
if ((snap_points & kSnapToMarkers)) {
|
||||
for (auto it=GetConnectedNode()->GetTimelinePoints()->markers()->cbegin(); it!=GetConnectedNode()->GetTimelinePoints()->markers()->cend(); it++) {
|
||||
TimelineMarker* m = *it;
|
||||
|
||||
qreal marker_pos = TimeToScene(m->time_range().in());
|
||||
potential_snaps.append(AttemptSnap(screen_pt, marker_pos, start_times, m->time_range().in()));
|
||||
|
||||
if (m->time_range().in() != m->time_range().out()) {
|
||||
marker_pos = TimeToScene(m->time_range().out());
|
||||
potential_snaps.append(AttemptSnap(screen_pt, marker_pos, start_times, m->time_range().out()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (potential_snaps.isEmpty()) {
|
||||
HideSnaps();
|
||||
return false;
|
||||
}
|
||||
|
||||
int closest_snap = 0;
|
||||
rational closest_diff = qAbs(potential_snaps.at(0).movement - *movement);
|
||||
|
||||
// Determine which snap point was the closest
|
||||
for (int i=1; i<potential_snaps.size(); i++) {
|
||||
rational this_diff = qAbs(potential_snaps.at(i).movement - *movement);
|
||||
|
||||
if (this_diff < closest_diff) {
|
||||
closest_snap = i;
|
||||
closest_diff = this_diff;
|
||||
}
|
||||
}
|
||||
|
||||
*movement = potential_snaps.at(closest_snap).movement;
|
||||
|
||||
// Find all points at this movement
|
||||
QVector<rational> snap_times;
|
||||
foreach (const SnapData& d, potential_snaps) {
|
||||
if (d.movement == *movement) {
|
||||
snap_times.append(d.time);
|
||||
}
|
||||
}
|
||||
|
||||
ShowSnap(snap_times);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TimelineWidget::SetSplitterSizesCommand::redo()
|
||||
{
|
||||
old_sizes_ = splitter_->sizes();
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "timeline/timelinecommon.h"
|
||||
#include "timelineandtrackview.h"
|
||||
#include "widget/slider/rationalslider.h"
|
||||
#include "widget/snapservice/snapservice.h"
|
||||
#include "widget/timebased/timebasedwidget.h"
|
||||
#include "widget/timelinewidget/timelinewidgetselections.h"
|
||||
#include "widget/timelinewidget/tool/import.h"
|
||||
@@ -44,7 +43,7 @@ namespace olive {
|
||||
*
|
||||
* Encapsulates TimelineViews, TimeRulers, and scrollbars for a complete widget to manipulate Timelines
|
||||
*/
|
||||
class TimelineWidget : public TimeBasedWidget, public SnapService
|
||||
class TimelineWidget : public TimeBasedWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -113,10 +112,6 @@ public:
|
||||
return selected_blocks_;
|
||||
}
|
||||
|
||||
virtual bool SnapPoint(QVector<rational> start_times, rational *movement, int snap_points = kSnapAll) override;
|
||||
|
||||
virtual void HideSnaps() override;
|
||||
|
||||
QByteArray SaveSplitterState() const;
|
||||
|
||||
void RestoreSplitterState(const QByteArray& state);
|
||||
@@ -276,6 +271,8 @@ protected:
|
||||
virtual void ConnectNodeEvent(ViewerOutput* n) override;
|
||||
virtual void DisconnectNodeEvent(ViewerOutput* n) override;
|
||||
|
||||
virtual const QVector<Block*> *GetSnapBlocks() const override { return &added_blocks_; }
|
||||
|
||||
private:
|
||||
QVector<Timeline::EditToInfo> GetEditToInfo(const rational &playhead_time, Timeline::MovementMode mode);
|
||||
|
||||
@@ -283,8 +280,6 @@ private:
|
||||
|
||||
void EditTo(Timeline::MovementMode mode);
|
||||
|
||||
void ShowSnap(const QVector<rational>& times);
|
||||
|
||||
void UpdateViewports(const Track::Type& type = Track::kNone);
|
||||
|
||||
QVector<Block*> GetBlocksInGlobalRect(const QPoint &p1, const QPoint &p2);
|
||||
|
||||
@@ -79,7 +79,7 @@ void AddTool::MousePress(TimelineViewMouseEvent *event)
|
||||
ghost_->SetTrack(track);
|
||||
parent()->AddGhost(ghost_);
|
||||
|
||||
snap_points_.append(drag_start_point_);
|
||||
snap_points_.push_back(drag_start_point_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -243,8 +243,8 @@ void ImportTool::FootageToGhosts(rational ghost_start, const DraggedFootageData
|
||||
ghost->SetMediaIn(ghost_in);
|
||||
ghost->SetTrack(Track::Reference(track_type, track_offsets.at(track_type)));
|
||||
|
||||
snap_points_.append(ghost->GetIn());
|
||||
snap_points_.append(ghost->GetOut());
|
||||
snap_points_.push_back(ghost->GetIn());
|
||||
snap_points_.push_back(ghost->GetOut());
|
||||
|
||||
// Increment track count for this track type
|
||||
track_offsets[track_type]++;
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "pointer.h"
|
||||
#include "widget/nodeview/nodeviewundo.h"
|
||||
#include "widget/timelinewidget/undo/timelineundopointer.h"
|
||||
#include "widget/timeruler/timeruler.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -793,14 +794,14 @@ void PointerTool::AddGhostInternal(TimelineViewGhostItem* ghost, Timeline::Movem
|
||||
// Prepare snap points (optimizes snapping for later)
|
||||
switch (mode) {
|
||||
case Timeline::kMove:
|
||||
snap_points_.append(ghost->GetIn());
|
||||
snap_points_.append(ghost->GetOut());
|
||||
snap_points_.push_back(ghost->GetIn());
|
||||
snap_points_.push_back(ghost->GetOut());
|
||||
break;
|
||||
case Timeline::kTrimIn:
|
||||
snap_points_.append(ghost->GetIn());
|
||||
snap_points_.push_back(ghost->GetIn());
|
||||
break;
|
||||
case Timeline::kTrimOut:
|
||||
snap_points_.append(ghost->GetOut());
|
||||
snap_points_.push_back(ghost->GetOut());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -78,7 +78,7 @@ protected:
|
||||
|
||||
void InsertGapsAtGhostDestination(MultiUndoCommand* command);
|
||||
|
||||
QVector<rational> snap_points_;
|
||||
std::vector<rational> snap_points_;
|
||||
|
||||
bool dragging_;
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ void TransitionTool::MousePress(TimelineViewMouseEvent *event)
|
||||
|
||||
parent()->AddGhost(ghost_);
|
||||
|
||||
snap_points_.append(transition_start_point);
|
||||
snap_points_.push_back(transition_start_point);
|
||||
|
||||
// Set the drag start point
|
||||
drag_start_point_ = event->GetFrame();
|
||||
|
||||
Reference in New Issue
Block a user