reworked and vastly improved snapping subsystem
This commit is contained in:
@@ -38,6 +38,7 @@
|
|||||||
#include "node/project/sequence/sequence.h"
|
#include "node/project/sequence/sequence.h"
|
||||||
#include "task/taskmanager.h"
|
#include "task/taskmanager.h"
|
||||||
#include "ui/icons/icons.h"
|
#include "ui/icons/icons.h"
|
||||||
|
#include "widget/timeruler/timeruler.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
#include "common/rational.h"
|
#include "common/rational.h"
|
||||||
|
#include "common/timerange.h"
|
||||||
#include "node/param.h"
|
#include "node/param.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
@@ -86,6 +87,14 @@ public:
|
|||||||
const rational& time() const;
|
const rational& time() const;
|
||||||
void set_time(const rational& time);
|
void set_time(const rational& time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dummy function for TimeBasedViewSelectionManager compatibility
|
||||||
|
*
|
||||||
|
* FIXME: Once we upgrade to C++17, we won't need this because we'll be able to check types in
|
||||||
|
* TimeBasedViewSelectionManager's template functions
|
||||||
|
*/
|
||||||
|
TimeRange time_range() const { return TimeRange(time_, time_); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The value of this keyframe (i.e. the value to use at this keyframe's time)
|
* @brief The value of this keyframe (i.e. the value to use at this keyframe's time)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -38,10 +38,17 @@ public:
|
|||||||
TimelineMarker(QObject* parent = nullptr);
|
TimelineMarker(QObject* parent = nullptr);
|
||||||
TimelineMarker(int color, const TimeRange& time, const QString& name = QString(), QObject* parent = nullptr);
|
TimelineMarker(int color, const TimeRange& time, const QString& name = QString(), QObject* parent = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dummy function for TimeBasedViewSelectionManager compatibility
|
||||||
|
*
|
||||||
|
* FIXME: Once we upgrade to C++17, we won't need this because we'll be able to check types in
|
||||||
|
* TimeBasedViewSelectionManager's template functions
|
||||||
|
*/
|
||||||
const rational &time() const { return time_.in(); }
|
const rational &time() const { return time_.in(); }
|
||||||
|
void set_time(const rational& time);
|
||||||
|
|
||||||
const TimeRange &time_range() const { return time_; }
|
const TimeRange &time_range() const { return time_; }
|
||||||
void set_time(const TimeRange& time);
|
void set_time(const TimeRange& time);
|
||||||
void set_time(const rational& time);
|
|
||||||
|
|
||||||
bool has_sibling_at_time(const rational &t) const;
|
bool has_sibling_at_time(const rational &t) const;
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "common/timecodefunctions.h"
|
#include "common/timecodefunctions.h"
|
||||||
#include "node/node.h"
|
#include "node/node.h"
|
||||||
#include "widget/keyframeview/keyframeviewundo.h"
|
#include "widget/keyframeview/keyframeviewundo.h"
|
||||||
|
#include "widget/timeruler/timeruler.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ public:
|
|||||||
return selection_manager_.GetSelectedObjects();
|
return selection_manager_.GetSelectedObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QVector<KeyframeViewInputConnection*> &GetKeyframeTracks() const
|
||||||
|
{
|
||||||
|
return tracks_;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void SelectionManagerSelectEvent(void *obj) override;
|
virtual void SelectionManagerSelectEvent(void *obj) override;
|
||||||
virtual void SelectionManagerDeselectEvent(void *obj) override;
|
virtual void SelectionManagerDeselectEvent(void *obj) override;
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
|
|
||||||
void SetYBehavior(YBehavior e);
|
void SetYBehavior(YBehavior e);
|
||||||
|
|
||||||
const QVector<NodeKeyframe*> GetKeyframes() const
|
const QVector<NodeKeyframe*> &GetKeyframes() const
|
||||||
{
|
{
|
||||||
return input_.input().node()->GetKeyframeTracks(input_.input()).at(input_.track());
|
return input_.input().node()->GetKeyframeTracks(input_.input()).at(input_.track());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "common/timecodefunctions.h"
|
#include "common/timecodefunctions.h"
|
||||||
#include "node/output/viewer/viewer.h"
|
#include "node/output/viewer/viewer.h"
|
||||||
#include "widget/nodeview/nodeviewundo.h"
|
#include "widget/nodeview/nodeviewundo.h"
|
||||||
|
#include "widget/timeruler/timeruler.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
@@ -117,6 +118,7 @@ NodeParamView::NodeParamView(bool create_keyframe_view, QWidget *parent) :
|
|||||||
// Create keyframe view
|
// Create keyframe view
|
||||||
keyframe_view_ = new KeyframeView();
|
keyframe_view_ = new KeyframeView();
|
||||||
keyframe_view_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
keyframe_view_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
keyframe_view_->SetSnapService(this);
|
||||||
ConnectTimelineView(keyframe_view_);
|
ConnectTimelineView(keyframe_view_);
|
||||||
keyframe_area_layout->addWidget(keyframe_view_);
|
keyframe_area_layout->addWidget(keyframe_view_);
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,16 @@ protected:
|
|||||||
|
|
||||||
virtual void ConnectedNodeChangeEvent(ViewerOutput* n) override;
|
virtual void ConnectedNodeChangeEvent(ViewerOutput* n) override;
|
||||||
|
|
||||||
|
virtual const QVector<KeyframeViewInputConnection*> *GetSnapKeyframes() const override
|
||||||
|
{
|
||||||
|
return keyframe_view_ ? &keyframe_view_->GetKeyframeTracks() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const std::vector<NodeKeyframe*> *GetSnapIgnoreKeyframes() const override
|
||||||
|
{
|
||||||
|
return keyframe_view_ ? &keyframe_view_->GetSelectedKeyframes() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateItemTime(const rational &time);
|
void UpdateItemTime(const rational &time);
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
# Olive - Non-Linear Video Editor
|
|
||||||
# Copyright (C) 2021 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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
set(OLIVE_SOURCES
|
|
||||||
${OLIVE_SOURCES}
|
|
||||||
widget/snapservice/snapservice.cpp
|
|
||||||
widget/snapservice/snapservice.h
|
|
||||||
PARENT_SCOPE
|
|
||||||
)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
#include "snapservice.h"
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#ifndef SNAPSERVICE_H
|
|
||||||
#define SNAPSERVICE_H
|
|
||||||
|
|
||||||
#include "common/rational.h"
|
|
||||||
|
|
||||||
namespace olive {
|
|
||||||
|
|
||||||
class SnapService
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SnapService() = default;
|
|
||||||
|
|
||||||
enum SnapPoints {
|
|
||||||
kSnapToClips = 0x1,
|
|
||||||
kSnapToPlayhead = 0x2,
|
|
||||||
kSnapToMarkers = 0x4,
|
|
||||||
kSnapAll = 0xFF
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Snaps point `start_point` that is moving by `movement` to currently existing clips
|
|
||||||
*/
|
|
||||||
virtual bool SnapPoint(QVector<rational> start_times, rational *movement, int snap_points = kSnapAll) = 0;
|
|
||||||
|
|
||||||
virtual void HideSnaps() = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SNAPSERVICE_H
|
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include "common/timecodefunctions.h"
|
#include "common/timecodefunctions.h"
|
||||||
|
#include "widget/timebased/timebasedwidget.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ void TimeBasedView::TimebaseChangedEvent(const rational &)
|
|||||||
viewport()->update();
|
viewport()->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeBasedView::EnableSnap(const QVector<rational> &points)
|
void TimeBasedView::EnableSnap(const std::vector<rational> &points)
|
||||||
{
|
{
|
||||||
snapped_ = true;
|
snapped_ = true;
|
||||||
snap_time_ = points;
|
snap_time_ = points;
|
||||||
@@ -78,11 +79,6 @@ void TimeBasedView::DisableSnap()
|
|||||||
viewport()->update();
|
viewport()->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeBasedView::SetSnapService(SnapService *service)
|
|
||||||
{
|
|
||||||
snap_service_ = service;
|
|
||||||
}
|
|
||||||
|
|
||||||
const double &TimeBasedView::GetYScale() const
|
const double &TimeBasedView::GetYScale() const
|
||||||
{
|
{
|
||||||
return y_scale_;
|
return y_scale_;
|
||||||
@@ -211,7 +207,7 @@ bool TimeBasedView::PlayheadMove(QMouseEvent *event)
|
|||||||
if (Core::instance()->snapping() && snap_service_) {
|
if (Core::instance()->snapping() && snap_service_) {
|
||||||
rational movement;
|
rational movement;
|
||||||
|
|
||||||
snap_service_->SnapPoint({mouse_time}, &movement, SnapService::kSnapAll & ~SnapService::kSnapToPlayhead);
|
snap_service_->SnapPoint({mouse_time}, &movement, TimeBasedWidget::kSnapAll & ~TimeBasedWidget::kSnapToPlayhead);
|
||||||
|
|
||||||
mouse_time += movement;
|
mouse_time += movement;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,21 +22,23 @@
|
|||||||
#define TIMELINEVIEWBASE_H
|
#define TIMELINEVIEWBASE_H
|
||||||
|
|
||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "timescaledobject.h"
|
#include "timescaledobject.h"
|
||||||
#include "widget/handmovableview/handmovableview.h"
|
#include "widget/handmovableview/handmovableview.h"
|
||||||
#include "widget/snapservice/snapservice.h"
|
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
|
class TimeBasedWidget;
|
||||||
|
|
||||||
class TimeBasedView : public HandMovableView, public TimeScaledObject
|
class TimeBasedView : public HandMovableView, public TimeScaledObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
TimeBasedView(QWidget* parent = nullptr);
|
TimeBasedView(QWidget* parent = nullptr);
|
||||||
|
|
||||||
void EnableSnap(const QVector<rational> &points);
|
void EnableSnap(const std::vector<rational> &points);
|
||||||
void DisableSnap();
|
void DisableSnap();
|
||||||
bool IsSnapped() const
|
bool IsSnapped() const
|
||||||
{
|
{
|
||||||
@@ -45,8 +47,8 @@ public:
|
|||||||
|
|
||||||
const rational &GetTime() const { return playhead_; }
|
const rational &GetTime() const { return playhead_; }
|
||||||
|
|
||||||
SnapService *GetSnapService() const { return snap_service_; }
|
TimeBasedWidget *GetSnapService() const { return snap_service_; }
|
||||||
void SetSnapService(SnapService* service);
|
void SetSnapService(TimeBasedWidget* service) { snap_service_ = service; }
|
||||||
|
|
||||||
const double& GetYScale() const;
|
const double& GetYScale() const;
|
||||||
void SetYScale(const double& y_scale);
|
void SetYScale(const double& y_scale);
|
||||||
@@ -117,11 +119,11 @@ private:
|
|||||||
QGraphicsScene scene_;
|
QGraphicsScene scene_;
|
||||||
|
|
||||||
bool snapped_;
|
bool snapped_;
|
||||||
QVector<rational> snap_time_;
|
std::vector<rational> snap_time_;
|
||||||
|
|
||||||
rational end_time_;
|
rational end_time_;
|
||||||
|
|
||||||
SnapService* snap_service_;
|
TimeBasedWidget* snap_service_;
|
||||||
|
|
||||||
bool y_axis_enabled_;
|
bool y_axis_enabled_;
|
||||||
|
|
||||||
|
|||||||
@@ -22,5 +22,4 @@
|
|||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "common/rational.h"
|
#include "common/rational.h"
|
||||||
#include "common/timecodefunctions.h"
|
#include "common/timecodefunctions.h"
|
||||||
#include "timebasedview.h"
|
#include "timebasedview.h"
|
||||||
|
#include "timebasedwidget.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
@@ -38,9 +39,15 @@ class TimeBasedViewSelectionManager
|
|||||||
public:
|
public:
|
||||||
TimeBasedViewSelectionManager(TimeBasedView *view) :
|
TimeBasedViewSelectionManager(TimeBasedView *view) :
|
||||||
view_(view),
|
view_(view),
|
||||||
rubberband_(nullptr)
|
rubberband_(nullptr),
|
||||||
|
snap_mask_(TimeBasedWidget::kSnapAll)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
void SetSnapMask(TimeBasedWidget::SnapMask e)
|
||||||
|
{
|
||||||
|
snap_mask_ = e;
|
||||||
|
}
|
||||||
|
|
||||||
void ClearDrawnObjects()
|
void ClearDrawnObjects()
|
||||||
{
|
{
|
||||||
drawn_objects_.clear();
|
drawn_objects_.clear();
|
||||||
@@ -156,19 +163,40 @@ public:
|
|||||||
initial_drag_item_ = initial_item;
|
initial_drag_item_ = initial_item;
|
||||||
|
|
||||||
dragging_.resize(selected_.size());
|
dragging_.resize(selected_.size());
|
||||||
|
snap_points_.resize(selected_.size()*2);
|
||||||
for (size_t i=0; i<selected_.size(); i++) {
|
for (size_t i=0; i<selected_.size(); i++) {
|
||||||
T *obj = selected_.at(i);
|
T *obj = selected_.at(i);
|
||||||
|
|
||||||
dragging_[i] = obj->time();
|
dragging_[i] = obj->time();
|
||||||
|
|
||||||
|
snap_points_[i] = obj->time();
|
||||||
|
snap_points_[i+selected_.size()] = obj->time_range().out();
|
||||||
}
|
}
|
||||||
|
|
||||||
drag_mouse_start_ = view_->mapToScene(event->pos());
|
drag_mouse_start_ = view_->mapToScene(event->pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SnapPoints(rational *movement)
|
||||||
|
{
|
||||||
|
if (Core::instance()->snapping() && view_->GetSnapService()) {
|
||||||
|
view_->GetSnapService()->SnapPoint(snap_points_, movement, snap_mask_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unsnap()
|
||||||
|
{
|
||||||
|
if (view_->GetSnapService()) {
|
||||||
|
view_->GetSnapService()->HideSnaps();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DragMove(QMouseEvent *event, const QString &tip_format = QString())
|
void DragMove(QMouseEvent *event, const QString &tip_format = QString())
|
||||||
{
|
{
|
||||||
rational time_diff = view_->SceneToTimeNoGrid(view_->mapToScene(event->pos()).x() - drag_mouse_start_.x());
|
rational time_diff = view_->SceneToTimeNoGrid(view_->mapToScene(event->pos()).x() - drag_mouse_start_.x());
|
||||||
|
|
||||||
|
// Snap points
|
||||||
|
SnapPoints(&time_diff);
|
||||||
|
|
||||||
// Validate movement
|
// Validate movement
|
||||||
for (size_t i=0; i<selected_.size(); i++) {
|
for (size_t i=0; i<selected_.size(); i++) {
|
||||||
rational proposed_time = dragging_.at(i) + time_diff;
|
rational proposed_time = dragging_.at(i) + time_diff;
|
||||||
@@ -186,11 +214,13 @@ public:
|
|||||||
loop = false;
|
loop = false;
|
||||||
while (sel->has_sibling_at_time(proposed_time)) {
|
while (sel->has_sibling_at_time(proposed_time)) {
|
||||||
proposed_time += adj;
|
proposed_time += adj;
|
||||||
|
Unsnap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proposed_time < 0) {
|
if (proposed_time < 0) {
|
||||||
// Prevent any object from going below zero
|
// Prevent any object from going below zero
|
||||||
proposed_time = 0;
|
proposed_time = 0;
|
||||||
|
Unsnap();
|
||||||
|
|
||||||
// Setting our proposed time to zero may (re)introduce a conflict that we just avoided
|
// Setting our proposed time to zero may (re)introduce a conflict that we just avoided
|
||||||
// with the sibling check above, so we request it to happen again. To avoid a negative
|
// with the sibling check above, so we request it to happen again. To avoid a negative
|
||||||
@@ -230,6 +260,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
dragging_.clear();
|
dragging_.clear();
|
||||||
|
Unsnap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RubberBandStart(QMouseEvent *event)
|
void RubberBandStart(QMouseEvent *event)
|
||||||
@@ -325,6 +356,7 @@ private:
|
|||||||
std::vector<T*> selected_;
|
std::vector<T*> selected_;
|
||||||
|
|
||||||
std::vector<rational> dragging_;
|
std::vector<rational> dragging_;
|
||||||
|
std::vector<rational> snap_points_;
|
||||||
|
|
||||||
T *initial_drag_item_;
|
T *initial_drag_item_;
|
||||||
|
|
||||||
@@ -336,6 +368,8 @@ private:
|
|||||||
QPoint rubberband_start_;
|
QPoint rubberband_start_;
|
||||||
std::vector<T*> rubberband_preselected_;
|
std::vector<T*> rubberband_preselected_;
|
||||||
|
|
||||||
|
TimeBasedWidget::SnapMask snap_mask_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,11 +23,13 @@
|
|||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
|
||||||
#include "common/autoscroll.h"
|
#include "common/autoscroll.h"
|
||||||
|
#include "common/range.h"
|
||||||
#include "common/timecodefunctions.h"
|
#include "common/timecodefunctions.h"
|
||||||
#include "config/config.h"
|
#include "config/config.h"
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "dialog/markerproperties/markerpropertiesdialog.h"
|
#include "dialog/markerproperties/markerpropertiesdialog.h"
|
||||||
#include "node/project/sequence/sequence.h"
|
#include "node/project/sequence/sequence.h"
|
||||||
|
#include "widget/timeruler/timeruler.h"
|
||||||
#include "widget/timelinewidget/undo/timelineundoworkarea.h"
|
#include "widget/timelinewidget/undo/timelineundoworkarea.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
@@ -41,6 +43,7 @@ TimeBasedWidget::TimeBasedWidget(bool ruler_text_visible, bool ruler_cache_statu
|
|||||||
{
|
{
|
||||||
ruler_ = new TimeRuler(ruler_text_visible, ruler_cache_status_visible, this);
|
ruler_ = new TimeRuler(ruler_text_visible, ruler_cache_status_visible, this);
|
||||||
ConnectTimelineView(ruler_, true);
|
ConnectTimelineView(ruler_, true);
|
||||||
|
ruler()->SetSnapService(this);
|
||||||
|
|
||||||
scrollbar_ = new ResizableTimelineScrollBar(Qt::Horizontal, this);
|
scrollbar_ = new ResizableTimelineScrollBar(Qt::Horizontal, this);
|
||||||
connect(scrollbar_, &ResizableScrollBar::ResizeBegan, this, &TimeBasedWidget::ScrollBarResizeBegan);
|
connect(scrollbar_, &ResizableScrollBar::ResizeBegan, this, &TimeBasedWidget::ScrollBarResizeBegan);
|
||||||
@@ -693,4 +696,155 @@ bool TimeBasedWidget::eventFilter(QObject *object, QEvent *event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SnapData {
|
||||||
|
rational time;
|
||||||
|
rational movement;
|
||||||
|
};
|
||||||
|
|
||||||
|
void AttemptSnap(std::vector<SnapData> &snap_data,
|
||||||
|
const std::vector<double>& screen_pt,
|
||||||
|
double compare_pt,
|
||||||
|
const std::vector<rational>& start_times,
|
||||||
|
const rational& compare_time)
|
||||||
|
{
|
||||||
|
const qreal kSnapRange = 10; // FIXME: Hardcoded number
|
||||||
|
|
||||||
|
for (size_t i=0;i<screen_pt.size();i++) {
|
||||||
|
// Attempt snapping to clip out point
|
||||||
|
if (InRange(screen_pt.at(i), compare_pt, kSnapRange)) {
|
||||||
|
snap_data.push_back({compare_time, compare_time - start_times.at(i)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TimeBasedWidget::SnapPoint(const std::vector<rational> &start_times, rational *movement, SnapMask snap_points)
|
||||||
|
{
|
||||||
|
std::vector<double> screen_pt(start_times.size());
|
||||||
|
|
||||||
|
for (size_t i=0; i<start_times.size(); i++) {
|
||||||
|
screen_pt[i] = TimeToScene(start_times.at(i) + *movement);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SnapData> potential_snaps;
|
||||||
|
|
||||||
|
if (snap_points & kSnapToPlayhead) {
|
||||||
|
rational playhead_abs_time = GetTime();
|
||||||
|
qreal playhead_pos = TimeToScene(playhead_abs_time);
|
||||||
|
AttemptSnap(potential_snaps, screen_pt, playhead_pos, start_times, playhead_abs_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((snap_points & kSnapToClips) && GetSnapBlocks()) {
|
||||||
|
for (auto it=GetSnapBlocks()->cbegin(); it!=GetSnapBlocks()->cend(); it++) {
|
||||||
|
Block *b = *it;
|
||||||
|
|
||||||
|
qreal rect_left = TimeToScene(b->in());
|
||||||
|
qreal rect_right = TimeToScene(b->out());
|
||||||
|
|
||||||
|
// Attempt snapping to clip in point
|
||||||
|
AttemptSnap(potential_snaps, screen_pt, rect_left, start_times, b->in());
|
||||||
|
|
||||||
|
// Attempt snapping to clip out point
|
||||||
|
AttemptSnap(potential_snaps, screen_pt, rect_right, start_times, b->out());
|
||||||
|
|
||||||
|
if (snap_points & kSnapToMarkers) {
|
||||||
|
// Snap to clip markers too
|
||||||
|
if (ClipBlock *clip = dynamic_cast<ClipBlock*>(b)) {
|
||||||
|
if (clip->connected_viewer()) {
|
||||||
|
TimelineMarkerList *markers = clip->connected_viewer()->GetTimelinePoints()->markers();
|
||||||
|
for (auto jt=markers->cbegin(); jt!=markers->cend(); jt++) {
|
||||||
|
TimelineMarker *marker = *jt;
|
||||||
|
|
||||||
|
TimeRange marker_range = marker->time_range() + clip->in() - clip->media_in();
|
||||||
|
|
||||||
|
qreal marker_in_screen = TimeToScene(marker_range.in());
|
||||||
|
qreal marker_out_screen = TimeToScene(marker_range.out());
|
||||||
|
|
||||||
|
AttemptSnap(potential_snaps, screen_pt, marker_in_screen, start_times, marker_range.in());
|
||||||
|
AttemptSnap(potential_snaps, screen_pt, marker_out_screen, start_times, marker_range.out());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((snap_points & kSnapToMarkers) && ruler()->GetTimelinePoints()) {
|
||||||
|
for (auto it=ruler()->GetTimelinePoints()->markers()->cbegin(); it!=ruler()->GetTimelinePoints()->markers()->cend(); it++) {
|
||||||
|
TimelineMarker* m = *it;
|
||||||
|
|
||||||
|
qreal marker_pos = TimeToScene(m->time_range().in());
|
||||||
|
AttemptSnap(potential_snaps, 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());
|
||||||
|
AttemptSnap(potential_snaps, screen_pt, marker_pos, start_times, m->time_range().out());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((snap_points & kSnapToKeyframes) && GetSnapKeyframes()) {
|
||||||
|
for (auto it=GetSnapKeyframes()->cbegin(); it!=GetSnapKeyframes()->cend(); it++) {
|
||||||
|
const QVector<NodeKeyframe*> &keys = (*it)->GetKeyframes();
|
||||||
|
for (auto jt=keys.cbegin(); jt!=keys.cend(); jt++) {
|
||||||
|
NodeKeyframe *key = *jt;
|
||||||
|
|
||||||
|
auto ignore = GetSnapIgnoreKeyframes();
|
||||||
|
if (ignore && std::find(ignore->cbegin(), ignore->cend(), key) != ignore->cend()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal key_scene_pt = TimeToScene(key->time());
|
||||||
|
|
||||||
|
AttemptSnap(potential_snaps, screen_pt, key_scene_pt, start_times, key->time());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (potential_snaps.empty()) {
|
||||||
|
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 (size_t 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
|
||||||
|
std::vector<rational> snap_times;
|
||||||
|
foreach (const SnapData& d, potential_snaps) {
|
||||||
|
if (d.movement == *movement) {
|
||||||
|
snap_times.push_back(d.time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowSnaps(snap_times);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeBasedWidget::ShowSnaps(const std::vector<rational> ×)
|
||||||
|
{
|
||||||
|
foreach (TimeBasedView* view, timeline_views_) {
|
||||||
|
view->EnableSnap(times);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeBasedWidget::HideSnaps()
|
||||||
|
{
|
||||||
|
foreach (TimeBasedView* view, timeline_views_) {
|
||||||
|
view->DisableSnap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,13 +25,15 @@
|
|||||||
|
|
||||||
#include "node/output/viewer/viewer.h"
|
#include "node/output/viewer/viewer.h"
|
||||||
#include "timeline/timelinecommon.h"
|
#include "timeline/timelinecommon.h"
|
||||||
|
#include "widget/keyframeview/keyframeviewinputconnection.h"
|
||||||
#include "widget/resizablescrollbar/resizabletimelinescrollbar.h"
|
#include "widget/resizablescrollbar/resizabletimelinescrollbar.h"
|
||||||
#include "widget/timebased/timescaledobject.h"
|
#include "widget/timebased/timescaledobject.h"
|
||||||
#include "widget/timelinewidget/view/timelineview.h"
|
#include "widget/timelinewidget/view/timelineview.h"
|
||||||
#include "widget/timeruler/timeruler.h"
|
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
|
class TimeRuler;
|
||||||
|
|
||||||
class TimeBasedWidget : public TimelineScaledWidget
|
class TimeBasedWidget : public TimelineScaledWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -54,6 +56,22 @@ public:
|
|||||||
|
|
||||||
virtual bool eventFilter(QObject* object, QEvent* event) override;
|
virtual bool eventFilter(QObject* object, QEvent* event) override;
|
||||||
|
|
||||||
|
using SnapMask = uint32_t;
|
||||||
|
enum SnapPoints {
|
||||||
|
kSnapToClips = 0x1,
|
||||||
|
kSnapToPlayhead = 0x2,
|
||||||
|
kSnapToMarkers = 0x4,
|
||||||
|
kSnapToKeyframes = 0x8,
|
||||||
|
kSnapAll = UINT32_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Snaps point `start_point` that is moving by `movement` to currently existing clips
|
||||||
|
*/
|
||||||
|
bool SnapPoint(const std::vector<rational> &start_times, rational *movement, SnapMask snap_points = kSnapAll);
|
||||||
|
void ShowSnaps(const std::vector<rational> ×);
|
||||||
|
void HideSnaps();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void SetTime(const rational &time);
|
void SetTime(const rational &time);
|
||||||
|
|
||||||
@@ -119,6 +137,10 @@ protected:
|
|||||||
|
|
||||||
void PassWheelEventsToScrollBar(QObject* object);
|
void PassWheelEventsToScrollBar(QObject* object);
|
||||||
|
|
||||||
|
virtual const QVector<Block*> *GetSnapBlocks() const { return nullptr; }
|
||||||
|
virtual const QVector<KeyframeViewInputConnection*> *GetSnapKeyframes() const { return nullptr; }
|
||||||
|
virtual const std::vector<NodeKeyframe*> *GetSnapIgnoreKeyframes() const { return nullptr; }
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
/**
|
/**
|
||||||
* @brief Slot to center the horizontal scroll bar on the playhead's current position
|
* @brief Slot to center the horizontal scroll bar on the playhead's current position
|
||||||
@@ -141,7 +163,7 @@ signals:
|
|||||||
void ConnectedNodeChanged(ViewerOutput* old, ViewerOutput* now);
|
void ConnectedNodeChanged(ViewerOutput* old, ViewerOutput* now);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set either in or out point to the current playhead
|
* @brief Set either in or out point to the current playhead
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "common/rational.h"
|
#include "common/rational.h"
|
||||||
|
#include "node/block/block.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@
|
|||||||
#include "widget/menu/menu.h"
|
#include "widget/menu/menu.h"
|
||||||
#include "widget/menu/menushared.h"
|
#include "widget/menu/menushared.h"
|
||||||
#include "widget/nodeview/nodeviewundo.h"
|
#include "widget/nodeview/nodeviewundo.h"
|
||||||
|
#include "widget/timeruler/timeruler.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
@@ -82,7 +83,6 @@ TimelineWidget::TimelineWidget(QWidget *parent) :
|
|||||||
ruler_and_time_layout->addWidget(timecode_label_);
|
ruler_and_time_layout->addWidget(timecode_label_);
|
||||||
|
|
||||||
ruler_and_time_layout->addWidget(ruler());
|
ruler_and_time_layout->addWidget(ruler());
|
||||||
ruler()->SetSnapService(this);
|
|
||||||
|
|
||||||
// Create list of TimelineViews - these MUST correspond to the ViewType enum
|
// 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);
|
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)
|
void TimelineWidget::UpdateViewports(const Track::Type &type)
|
||||||
{
|
{
|
||||||
if (type == Track::kNone) {
|
if (type == Track::kNone) {
|
||||||
@@ -1573,13 +1566,6 @@ QVector<Block *> TimelineWidget::GetBlocksInGlobalRect(const QPoint &p1, const Q
|
|||||||
return blocks_in_rect;
|
return blocks_in_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineWidget::HideSnaps()
|
|
||||||
{
|
|
||||||
foreach (TimelineAndTrackView* tview, views_) {
|
|
||||||
tview->view()->DisableSnap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray TimelineWidget::SaveSplitterState() const
|
QByteArray TimelineWidget::SaveSplitterState() const
|
||||||
{
|
{
|
||||||
return view_splitter_->saveState();
|
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());
|
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()
|
void TimelineWidget::SetSplitterSizesCommand::redo()
|
||||||
{
|
{
|
||||||
old_sizes_ = splitter_->sizes();
|
old_sizes_ = splitter_->sizes();
|
||||||
|
|||||||
@@ -31,7 +31,6 @@
|
|||||||
#include "timeline/timelinecommon.h"
|
#include "timeline/timelinecommon.h"
|
||||||
#include "timelineandtrackview.h"
|
#include "timelineandtrackview.h"
|
||||||
#include "widget/slider/rationalslider.h"
|
#include "widget/slider/rationalslider.h"
|
||||||
#include "widget/snapservice/snapservice.h"
|
|
||||||
#include "widget/timebased/timebasedwidget.h"
|
#include "widget/timebased/timebasedwidget.h"
|
||||||
#include "widget/timelinewidget/timelinewidgetselections.h"
|
#include "widget/timelinewidget/timelinewidgetselections.h"
|
||||||
#include "widget/timelinewidget/tool/import.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
|
* Encapsulates TimelineViews, TimeRulers, and scrollbars for a complete widget to manipulate Timelines
|
||||||
*/
|
*/
|
||||||
class TimelineWidget : public TimeBasedWidget, public SnapService
|
class TimelineWidget : public TimeBasedWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -113,10 +112,6 @@ public:
|
|||||||
return selected_blocks_;
|
return selected_blocks_;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool SnapPoint(QVector<rational> start_times, rational *movement, int snap_points = kSnapAll) override;
|
|
||||||
|
|
||||||
virtual void HideSnaps() override;
|
|
||||||
|
|
||||||
QByteArray SaveSplitterState() const;
|
QByteArray SaveSplitterState() const;
|
||||||
|
|
||||||
void RestoreSplitterState(const QByteArray& state);
|
void RestoreSplitterState(const QByteArray& state);
|
||||||
@@ -276,6 +271,8 @@ protected:
|
|||||||
virtual void ConnectNodeEvent(ViewerOutput* n) override;
|
virtual void ConnectNodeEvent(ViewerOutput* n) override;
|
||||||
virtual void DisconnectNodeEvent(ViewerOutput* n) override;
|
virtual void DisconnectNodeEvent(ViewerOutput* n) override;
|
||||||
|
|
||||||
|
virtual const QVector<Block*> *GetSnapBlocks() const override { return &added_blocks_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVector<Timeline::EditToInfo> GetEditToInfo(const rational &playhead_time, Timeline::MovementMode mode);
|
QVector<Timeline::EditToInfo> GetEditToInfo(const rational &playhead_time, Timeline::MovementMode mode);
|
||||||
|
|
||||||
@@ -283,8 +280,6 @@ private:
|
|||||||
|
|
||||||
void EditTo(Timeline::MovementMode mode);
|
void EditTo(Timeline::MovementMode mode);
|
||||||
|
|
||||||
void ShowSnap(const QVector<rational>& times);
|
|
||||||
|
|
||||||
void UpdateViewports(const Track::Type& type = Track::kNone);
|
void UpdateViewports(const Track::Type& type = Track::kNone);
|
||||||
|
|
||||||
QVector<Block*> GetBlocksInGlobalRect(const QPoint &p1, const QPoint &p2);
|
QVector<Block*> GetBlocksInGlobalRect(const QPoint &p1, const QPoint &p2);
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ void AddTool::MousePress(TimelineViewMouseEvent *event)
|
|||||||
ghost_->SetTrack(track);
|
ghost_->SetTrack(track);
|
||||||
parent()->AddGhost(ghost_);
|
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->SetMediaIn(ghost_in);
|
||||||
ghost->SetTrack(Track::Reference(track_type, track_offsets.at(track_type)));
|
ghost->SetTrack(Track::Reference(track_type, track_offsets.at(track_type)));
|
||||||
|
|
||||||
snap_points_.append(ghost->GetIn());
|
snap_points_.push_back(ghost->GetIn());
|
||||||
snap_points_.append(ghost->GetOut());
|
snap_points_.push_back(ghost->GetOut());
|
||||||
|
|
||||||
// Increment track count for this track type
|
// Increment track count for this track type
|
||||||
track_offsets[track_type]++;
|
track_offsets[track_type]++;
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include "pointer.h"
|
#include "pointer.h"
|
||||||
#include "widget/nodeview/nodeviewundo.h"
|
#include "widget/nodeview/nodeviewundo.h"
|
||||||
#include "widget/timelinewidget/undo/timelineundopointer.h"
|
#include "widget/timelinewidget/undo/timelineundopointer.h"
|
||||||
|
#include "widget/timeruler/timeruler.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
@@ -793,14 +794,14 @@ void PointerTool::AddGhostInternal(TimelineViewGhostItem* ghost, Timeline::Movem
|
|||||||
// Prepare snap points (optimizes snapping for later)
|
// Prepare snap points (optimizes snapping for later)
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case Timeline::kMove:
|
case Timeline::kMove:
|
||||||
snap_points_.append(ghost->GetIn());
|
snap_points_.push_back(ghost->GetIn());
|
||||||
snap_points_.append(ghost->GetOut());
|
snap_points_.push_back(ghost->GetOut());
|
||||||
break;
|
break;
|
||||||
case Timeline::kTrimIn:
|
case Timeline::kTrimIn:
|
||||||
snap_points_.append(ghost->GetIn());
|
snap_points_.push_back(ghost->GetIn());
|
||||||
break;
|
break;
|
||||||
case Timeline::kTrimOut:
|
case Timeline::kTrimOut:
|
||||||
snap_points_.append(ghost->GetOut());
|
snap_points_.push_back(ghost->GetOut());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ protected:
|
|||||||
|
|
||||||
void InsertGapsAtGhostDestination(MultiUndoCommand* command);
|
void InsertGapsAtGhostDestination(MultiUndoCommand* command);
|
||||||
|
|
||||||
QVector<rational> snap_points_;
|
std::vector<rational> snap_points_;
|
||||||
|
|
||||||
bool dragging_;
|
bool dragging_;
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ void TransitionTool::MousePress(TimelineViewMouseEvent *event)
|
|||||||
|
|
||||||
parent()->AddGhost(ghost_);
|
parent()->AddGhost(ghost_);
|
||||||
|
|
||||||
snap_points_.append(transition_start_point);
|
snap_points_.push_back(transition_start_point);
|
||||||
|
|
||||||
// Set the drag start point
|
// Set the drag start point
|
||||||
drag_start_point_ = event->GetFrame();
|
drag_start_point_ = event->GetFrame();
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ SeekableWidget::SeekableWidget(QWidget* parent) :
|
|||||||
|
|
||||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
setFocusPolicy(Qt::ClickFocus);
|
setFocusPolicy(Qt::ClickFocus);
|
||||||
|
|
||||||
|
selection_manager_.SetSnapMask(TimeBasedWidget::kSnapAll & ~TimeBasedWidget::kSnapToMarkers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SeekableWidget::ConnectTimelinePoints(TimelinePoints *points)
|
void SeekableWidget::ConnectTimelinePoints(TimelinePoints *points)
|
||||||
@@ -212,11 +214,6 @@ void SeekableWidget::focusOutEvent(QFocusEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelinePoints *SeekableWidget::timeline_points() const
|
|
||||||
{
|
|
||||||
return timeline_points_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SeekableWidget::DeselectAllMarkers()
|
void SeekableWidget::DeselectAllMarkers()
|
||||||
{
|
{
|
||||||
selection_manager_.ClearSelection();
|
selection_manager_.ClearSelection();
|
||||||
@@ -262,7 +259,7 @@ void SeekableWidget::SeekToScenePoint(qreal scene)
|
|||||||
|
|
||||||
GetSnapService()->SnapPoint({playhead_time},
|
GetSnapService()->SnapPoint({playhead_time},
|
||||||
&movement,
|
&movement,
|
||||||
SnapService::kSnapAll & ~SnapService::kSnapToPlayhead);
|
TimeBasedWidget::kSnapAll & ~TimeBasedWidget::kSnapToPlayhead);
|
||||||
|
|
||||||
playhead_time += movement;
|
playhead_time += movement;
|
||||||
}
|
}
|
||||||
@@ -290,7 +287,7 @@ void SeekableWidget::SelectionManagerDeselectEvent(void *obj)
|
|||||||
|
|
||||||
void SeekableWidget::DrawTimelinePoints(QPainter* p, int marker_bottom)
|
void SeekableWidget::DrawTimelinePoints(QPainter* p, int marker_bottom)
|
||||||
{
|
{
|
||||||
if (!timeline_points()) {
|
if (!GetTimelinePoints()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,22 +297,22 @@ void SeekableWidget::DrawTimelinePoints(QPainter* p, int marker_bottom)
|
|||||||
selection_manager_.ClearDrawnObjects();
|
selection_manager_.ClearDrawnObjects();
|
||||||
|
|
||||||
// Draw in/out workarea
|
// Draw in/out workarea
|
||||||
if (timeline_points()->workarea()->enabled()) {
|
if (GetTimelinePoints()->workarea()->enabled()) {
|
||||||
int workarea_left = qMax(qreal(lim_left), TimeToScene(timeline_points()->workarea()->in()));
|
int workarea_left = qMax(qreal(lim_left), TimeToScene(GetTimelinePoints()->workarea()->in()));
|
||||||
int workarea_right;
|
int workarea_right;
|
||||||
|
|
||||||
if (timeline_points()->workarea()->out() == TimelineWorkArea::kResetOut) {
|
if (GetTimelinePoints()->workarea()->out() == TimelineWorkArea::kResetOut) {
|
||||||
workarea_right = lim_right;
|
workarea_right = lim_right;
|
||||||
} else {
|
} else {
|
||||||
workarea_right = qMin(qreal(lim_right), TimeToScene(timeline_points()->workarea()->out()));
|
workarea_right = qMin(qreal(lim_right), TimeToScene(GetTimelinePoints()->workarea()->out()));
|
||||||
}
|
}
|
||||||
|
|
||||||
p->fillRect(workarea_left, 0, workarea_right - workarea_left, height(), palette().highlight());
|
p->fillRect(workarea_left, 0, workarea_right - workarea_left, height(), palette().highlight());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw markers
|
// Draw markers
|
||||||
if (marker_bottom > 0 && !timeline_points()->markers()->empty()) {
|
if (marker_bottom > 0 && !GetTimelinePoints()->markers()->empty()) {
|
||||||
for (auto it=timeline_points()->markers()->cbegin(); it!=timeline_points()->markers()->cend(); it++) {
|
for (auto it=GetTimelinePoints()->markers()->cbegin(); it!=GetTimelinePoints()->markers()->cend(); it++) {
|
||||||
TimelineMarker* marker = *it;
|
TimelineMarker* marker = *it;
|
||||||
|
|
||||||
int marker_right = TimeToScene(marker->time_range().out());
|
int marker_right = TimeToScene(marker->time_range().out());
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
#include "common/rational.h"
|
#include "common/rational.h"
|
||||||
#include "timeline/timelinepoints.h"
|
#include "timeline/timelinepoints.h"
|
||||||
#include "widget/menu/menu.h"
|
#include "widget/menu/menu.h"
|
||||||
#include "widget/snapservice/snapservice.h"
|
|
||||||
#include "widget/timebased/timebasedviewselectionmanager.h"
|
#include "widget/timebased/timebasedviewselectionmanager.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
@@ -43,6 +42,7 @@ public:
|
|||||||
return horizontalScrollBar()->value();
|
return horizontalScrollBar()->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimelinePoints* GetTimelinePoints() const { return timeline_points_; }
|
||||||
void ConnectTimelinePoints(TimelinePoints* points);
|
void ConnectTimelinePoints(TimelinePoints* points);
|
||||||
|
|
||||||
bool IsDraggingPlayhead() const
|
bool IsDraggingPlayhead() const
|
||||||
@@ -81,8 +81,6 @@ protected:
|
|||||||
|
|
||||||
void DrawTimelinePoints(QPainter *p, int marker_bottom = 0);
|
void DrawTimelinePoints(QPainter *p, int marker_bottom = 0);
|
||||||
|
|
||||||
TimelinePoints* timeline_points() const;
|
|
||||||
|
|
||||||
void DrawPlayhead(QPainter* p, int x, int y);
|
void DrawPlayhead(QPainter* p, int x, int y);
|
||||||
|
|
||||||
inline const int& text_height() const {
|
inline const int& text_height() const {
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ void TimeRuler::drawForeground(QPainter *p, const QRectF &rect)
|
|||||||
|
|
||||||
// Draw timeline points if connected
|
// Draw timeline points if connected
|
||||||
int marker_height = TimelineMarker::GetMarkerHeight(p->fontMetrics());
|
int marker_height = TimelineMarker::GetMarkerHeight(p->fontMetrics());
|
||||||
if (timeline_points()) {
|
if (GetTimelinePoints()) {
|
||||||
DrawTimelinePoints(p, marker_height);
|
DrawTimelinePoints(p, marker_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
#include "viewerpreventsleep.h"
|
#include "viewerpreventsleep.h"
|
||||||
#include "widget/menu/menu.h"
|
#include "widget/menu/menu.h"
|
||||||
#include "window/mainwindow/mainwindow.h"
|
#include "window/mainwindow/mainwindow.h"
|
||||||
|
#include "widget/timeruler/timeruler.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user