diff --git a/app/node/CMakeLists.txt b/app/node/CMakeLists.txt index 8930b3979..6f31b252c 100644 --- a/app/node/CMakeLists.txt +++ b/app/node/CMakeLists.txt @@ -36,6 +36,8 @@ set(OLIVE_SOURCES node/input.cpp node/inputarray.h node/inputarray.cpp + node/inputdragger.h + node/inputdragger.cpp node/keyframe.h node/keyframe.cpp node/node.h diff --git a/app/node/generator/polygon/polygon.cpp b/app/node/generator/polygon/polygon.cpp index f14e4fa55..15441c1f9 100644 --- a/app/node/generator/polygon/polygon.cpp +++ b/app/node/generator/polygon/polygon.cpp @@ -139,12 +139,28 @@ bool PolygonGenerator::GizmoPress(const NodeValueDatabase &db, const QPointF &p, return false; } -void PolygonGenerator::GizmoMove(const QPointF &p, const QVector2D &scale) +void PolygonGenerator::GizmoMove(const QPointF &p, const QVector2D &scale, const rational& time) { QVector2D new_pos = QVector2D(p) / scale; - gizmo_drag_->set_standard_value(new_pos.x(), 0); - gizmo_drag_->set_standard_value(new_pos.y(), 1); + if (!gizmo_x_dragger_.IsStarted()) { + gizmo_x_dragger_.Start(gizmo_drag_, time, 0); + } + + if (!gizmo_y_dragger_.IsStarted()) { + gizmo_y_dragger_.Start(gizmo_drag_, time, 1); + } + + gizmo_x_dragger_.Drag(new_pos.x()); + gizmo_y_dragger_.Drag(new_pos.y()); + + InvalidateVisible(gizmo_drag_, gizmo_drag_); +} + +void PolygonGenerator::GizmoRelease(const QPointF &p) +{ + gizmo_x_dragger_.End(); + gizmo_y_dragger_.End(); } QVector PolygonGenerator::GetGizmoCoordinates(const NodeValueDatabase &db, const QVector2D& scale) const diff --git a/app/node/generator/polygon/polygon.h b/app/node/generator/polygon/polygon.h index cf907cf25..21d4e4106 100644 --- a/app/node/generator/polygon/polygon.h +++ b/app/node/generator/polygon/polygon.h @@ -22,6 +22,7 @@ #define POLYGONGENERATOR_H #include "node/node.h" +#include "node/inputdragger.h" OLIVE_NAMESPACE_ENTER @@ -46,8 +47,8 @@ public: virtual void DrawGizmos(const NodeValueDatabase& db, QPainter *p, const QVector2D &scale) const override; virtual bool GizmoPress(const NodeValueDatabase& db, const QPointF &p, const QVector2D &scale) override; - virtual void GizmoMove(const QPointF &p, const QVector2D &scale) override; - //virtual void GizmoRelease(const QPointF &p) override; + virtual void GizmoMove(const QPointF &p, const QVector2D &scale, const rational &time) override; + virtual void GizmoRelease(const QPointF &p) override; private: QVector GetGizmoCoordinates(const NodeValueDatabase &db, const QVector2D &scale) const; @@ -61,6 +62,9 @@ private: NodeInput* gizmo_drag_; QPointF gizmo_drag_start_; + NodeInputDragger gizmo_x_dragger_; + NodeInputDragger gizmo_y_dragger_; + }; OLIVE_NAMESPACE_EXIT diff --git a/app/node/inputdragger.cpp b/app/node/inputdragger.cpp new file mode 100644 index 000000000..f6e0cb60c --- /dev/null +++ b/app/node/inputdragger.cpp @@ -0,0 +1,118 @@ +/*** + + 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 "inputdragger.h" + +#include "core.h" +#include "node.h" +#include "widget/nodeparamview/nodeparamviewundo.h" + +OLIVE_NAMESPACE_ENTER + +NodeInputDragger::NodeInputDragger() : + input_(nullptr) +{ + +} + +bool NodeInputDragger::IsStarted() const +{ + return input_; +} + +void NodeInputDragger::Start(NodeInput *input, const rational &time, int track) +{ + Q_ASSERT(!input_); + + // Set up new drag + input_ = input; + time_ = time; + track_ = track; + + // Cache current value + start_value_ = input_->get_value_at_time_for_track(time, track); + + // Determine whether we are creating a keyframe or not + if (input_->is_keyframing()) { + dragging_key_ = input_->get_keyframe_at_time_on_track(time, track); + drag_created_key_ = !dragging_key_; + + if (drag_created_key_) { + dragging_key_ = NodeKeyframe::Create(time, + start_value_, + input_->get_best_keyframe_type_for_time(time, track), + track); + + // We disable default signal emitting during the drag + input_->blockSignals(true); + input_->insert_keyframe(dragging_key_); + input_->blockSignals(false); + + emit input_->KeyframeAdded(dragging_key_); + } + } +} + +void NodeInputDragger::Drag(const QVariant& value) +{ + Q_ASSERT(input_); + + end_value_ = value; + + input_->blockSignals(true); + + if (input_->is_keyframing()) { + dragging_key_->set_value(value); + } else { + input_->set_standard_value(value, track_); + } + + input_->blockSignals(false); +} + +void NodeInputDragger::End() +{ + if (!IsStarted()) { + return; + } + + QUndoCommand* command = new QUndoCommand(); + + if (input_->is_keyframing()) { + if (drag_created_key_) { + // We created a keyframe in this process + new NodeParamInsertKeyframeCommand(input_, dragging_key_, true, command); + } + + // We just set a keyframe's value + // We do this even when inserting a keyframe because we don't actually perform an insert in this undo command + // so this will ensure the ValueChanged() signal is sent correctly + new NodeParamSetKeyframeValueCommand(dragging_key_, end_value_, start_value_, command); + } else { + // We just set the standard value + new NodeParamSetStandardValueCommand(input_, track_, end_value_, start_value_, command); + } + + Core::instance()->undo_stack()->push(command); + + input_ = nullptr; +} + +OLIVE_NAMESPACE_EXIT diff --git a/app/node/inputdragger.h b/app/node/inputdragger.h new file mode 100644 index 000000000..f67f163a2 --- /dev/null +++ b/app/node/inputdragger.h @@ -0,0 +1,60 @@ +/*** + + 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 . + +***/ + +#ifndef NODEINPUTDRAGGER_H +#define NODEINPUTDRAGGER_H + +#include "node/input.h" + +OLIVE_NAMESPACE_ENTER + +class NodeInputDragger +{ +public: + NodeInputDragger(); + + bool IsStarted() const; + + void Start(NodeInput* input, const rational& time, int track); + + void Drag(const QVariant &value); + + void End(); + +private: + NodeInput* input_; + + int track_; + + rational time_; + + QVariant start_value_; + + QVariant end_value_; + + NodeKeyframePtr dragging_key_; + + bool drag_created_key_; + +}; + +OLIVE_NAMESPACE_EXIT + +#endif // NODEINPUTDRAGGER_H diff --git a/app/node/node.cpp b/app/node/node.cpp index 7a1b54b1a..2b702bf68 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -296,7 +296,7 @@ bool Node::GizmoPress(const NodeValueDatabase &, const QPointF &, const QVector2 return false; } -void Node::GizmoMove(const QPointF &, const QVector2D &) +void Node::GizmoMove(const QPointF &, const QVector2D &, const rational &) { } diff --git a/app/node/node.h b/app/node/node.h index b97e0fdf1..1f345428b 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -386,7 +386,7 @@ public: virtual void DrawGizmos(const NodeValueDatabase& db, QPainter* p, const QVector2D &scale) const; virtual bool GizmoPress(const NodeValueDatabase& db, const QPointF& p, const QVector2D &scale); - virtual void GizmoMove(const QPointF& p, const QVector2D &scale); + virtual void GizmoMove(const QPointF& p, const QVector2D &scale, const rational &time); virtual void GizmoRelease(const QPointF& p); const QString& GetLabel() const; diff --git a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp index 67778be99..3f9933218 100644 --- a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp +++ b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp @@ -42,9 +42,7 @@ OLIVE_NAMESPACE_ENTER NodeParamViewWidgetBridge::NodeParamViewWidgetBridge(NodeInput *input, QObject *parent) : QObject(parent), - input_(input), - dragging_(false), - drag_created_keyframe_(false) + input_(input) { CreateWidgets(); @@ -227,74 +225,23 @@ void NodeParamViewWidgetBridge::ProcessSlider(SliderBase *slider, const QVariant if (slider->IsDragging()) { // While we're dragging, we block the input's normal signalling and create our own - input_->blockSignals(true); - - if (!dragging_) { - // Set up new drag - dragging_ = true; - - // Cache current value - drag_old_value_ = input_->get_value_at_time_for_track(node_time, slider_track); - - // Determine whether we are creating a keyframe or not - if (input_->is_keyframing()) { - dragging_keyframe_ = input_->get_keyframe_at_time_on_track(node_time, slider_track); - drag_created_keyframe_ = !dragging_keyframe_; - - if (drag_created_keyframe_) { - dragging_keyframe_ = NodeKeyframe::Create(node_time, - value, - input_->get_best_keyframe_type_for_time(node_time, slider_track), - slider_track); - - input_->insert_keyframe(dragging_keyframe_); - - // We re-enable signals temporarily to emit the keyframe added signal - input_->blockSignals(false); - emit input_->KeyframeAdded(dragging_keyframe_); - input_->blockSignals(true); - } - } + if (!dragger_.IsStarted()) { + dragger_.Start(input_, node_time, slider_track); } - if (input_->is_keyframing()) { - dragging_keyframe_->set_value(value); - } else { - input_->set_standard_value(value, slider_track); - } - - input_->blockSignals(false); + dragger_.Drag(value); input_->parentNode()->InvalidateVisible(input_, input_); + } else if (dragger_.IsStarted()) { + + // We were dragging and just stopped + dragger_.Drag(value); + dragger_.End(); + } else { - if (dragging_) { - // We were dragging and just stopped - dragging_ = false; - - QUndoCommand* command = new QUndoCommand(); - - if (input_->is_keyframing()) { - if (drag_created_keyframe_) { - // We created a keyframe in this process - new NodeParamInsertKeyframeCommand(input_, dragging_keyframe_, true, command); - } - - // We just set a keyframe's value - // We do this even when inserting a keyframe because we don't actually perform an insert in this undo command - // so this will ensure the ValueChanged() signal is sent correctly - new NodeParamSetKeyframeValueCommand(dragging_keyframe_, value, drag_old_value_, command); - } else { - // We just set the standard value - new NodeParamSetStandardValueCommand(input_, slider_track, value, drag_old_value_, command); - } - - Core::instance()->undo_stack()->push(command); - - } else { - // No drag was involved, we can just push the value - SetInputValue(value, slider_track); - } + // No drag was involved, we can just push the value + SetInputValue(value, slider_track); } } @@ -529,7 +476,7 @@ rational NodeParamViewWidgetBridge::GetCurrentTimeAsNodeTime() const void NodeParamViewWidgetBridge::InputValueChanged(const TimeRange &range) { - if (!dragging_ && range.in() <= time_ && range.out() >= time_) { + if (!dragger_.IsStarted() && range.in() <= time_ && range.out() >= time_) { // We'll need to update the widgets because the values have changed on our current time UpdateWidgetValues(); } diff --git a/app/widget/nodeparamview/nodeparamviewwidgetbridge.h b/app/widget/nodeparamview/nodeparamviewwidgetbridge.h index 3d385a7bc..245a03171 100644 --- a/app/widget/nodeparamview/nodeparamviewwidgetbridge.h +++ b/app/widget/nodeparamview/nodeparamviewwidgetbridge.h @@ -24,6 +24,7 @@ #include #include "node/input.h" +#include "node/inputdragger.h" #include "widget/slider/sliderbase.h" #include "widget/timetarget/timetarget.h" @@ -60,10 +61,7 @@ private: rational time_; - bool dragging_; - bool drag_created_keyframe_; - QVariant drag_old_value_; - NodeKeyframePtr dragging_keyframe_; + NodeInputDragger dragger_; private slots: void WidgetCallback(); diff --git a/app/widget/viewer/viewerdisplay.cpp b/app/widget/viewer/viewerdisplay.cpp index e901dd6d5..04a5dbc6f 100644 --- a/app/widget/viewer/viewerdisplay.cpp +++ b/app/widget/viewer/viewerdisplay.cpp @@ -191,11 +191,11 @@ void ViewerDisplayWidget::SetTime(const rational &time) void ViewerDisplayWidget::mousePressEvent(QMouseEvent *event) { - if (gizmos_) { - if (gizmos_->GizmoPress(gizmo_db_, event->pos(), QVector2D(GetTexturePosition(size())))) { - gizmo_click_ = true; - return; - } + if (gizmos_ + && gizmos_->GizmoPress(gizmo_db_, event->pos(), QVector2D(GetTexturePosition(size())))) { + gizmo_click_ = true; + gizmo_drag_time_ = GetGizmoTime(); + return; } QOpenGLWidget::mousePressEvent(event); @@ -206,7 +206,7 @@ void ViewerDisplayWidget::mousePressEvent(QMouseEvent *event) void ViewerDisplayWidget::mouseMoveEvent(QMouseEvent *event) { if (gizmo_click_) { - gizmos_->GizmoMove(event->pos(), QVector2D(GetTexturePosition(size()))); + gizmos_->GizmoMove(event->pos(), QVector2D(GetTexturePosition(size())), gizmo_drag_time_); return; } @@ -294,7 +294,7 @@ void ViewerDisplayWidget::paintGL() if (gizmos_) { GizmoTraverser gt; - rational node_time = GetAdjustedTime(GetTimeTarget(), gizmos_, time_, NodeParam::kInput); + rational node_time = GetGizmoTime(); gizmo_db_ = gt.GenerateDatabase(gizmos_, TimeRange(node_time, node_time)); @@ -351,6 +351,11 @@ QPointF ViewerDisplayWidget::GetTexturePosition(const double &x, const double &y y / gizmo_params_.height()); } +rational ViewerDisplayWidget::GetGizmoTime() +{ + return GetAdjustedTime(GetTimeTarget(), gizmos_, time_, NodeParam::kInput); +} + #ifdef Q_OS_LINUX void ViewerDisplayWidget::ShowNouveauWarning() { diff --git a/app/widget/viewer/viewerdisplay.h b/app/widget/viewer/viewerdisplay.h index eb020b9db..996758718 100644 --- a/app/widget/viewer/viewerdisplay.h +++ b/app/widget/viewer/viewerdisplay.h @@ -162,6 +162,8 @@ private: QPointF GetTexturePosition(const QSize& size); QPointF GetTexturePosition(const double& x, const double& y); + rational GetGizmoTime(); + /** * @brief Internal reference to the OpenGL texture to draw. Set in SetTexture() and used in paintGL(). */ @@ -188,11 +190,9 @@ private: ViewerSafeMarginInfo safe_margin_; Node* gizmos_; - NodeValueDatabase gizmo_db_; - + rational gizmo_drag_time_; VideoRenderingParams gizmo_params_; - bool gizmo_click_; rational time_;