From bbef9badc7a1491ab82ce1b9386af94e23105179 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 27 Dec 2019 22:13:00 +1100 Subject: [PATCH] implemented moving keyframes around in the NodeParamView Can now change the time in the parameter panel. --- app/node/input.cpp | 5 +- app/node/output/track/track.cpp | 2 + app/widget/keyframeview/keyframeview.cpp | 87 +++++++++++++++++-- app/widget/keyframeview/keyframeview.h | 16 ++++ app/widget/keyframeview/keyframeviewitem.cpp | 12 +-- app/widget/keyframeview/keyframeviewitem.h | 2 +- .../nodeparamview/nodeparamviewundo.cpp | 8 ++ app/widget/nodeparamview/nodeparamviewundo.h | 1 + 8 files changed, 119 insertions(+), 14 deletions(-) diff --git a/app/node/input.cpp b/app/node/input.cpp index 9d10120e4..e5ee326c8 100644 --- a/app/node/input.cpp +++ b/app/node/input.cpp @@ -262,8 +262,7 @@ void NodeInput::KeyframeTimeChanged() TimeRange original_range = get_range_around_index(keyframe_index); - if ((keyframe_index > 0 && keyframes_.at(keyframe_index - 1)->time() > key->time()) - || (keyframe_index < keyframes_.size() - 1 && keyframes_.at(keyframe_index + 1)->time() < key->time())) { + if (!(original_range.in() < key->time() && original_range.out() > key->time())) { // This keyframe needs resorting, store it and remove it from the list NodeKeyframePtr key_shared_ptr = keyframes_.at(keyframe_index); @@ -273,7 +272,7 @@ void NodeInput::KeyframeTimeChanged() insert_keyframe_internal(key_shared_ptr); // Invalidate new area that the keyframe has been moved to - emit_range_affected_by_keyframe(key_shared_ptr.get()); + emit_time_range(get_range_around_index(FindIndexOfKeyframeFromRawPtr(key))); } // Invalidate entire area surrounding the keyframe (either where it currently is, or where it used to be before it diff --git a/app/node/output/track/track.cpp b/app/node/output/track/track.cpp index b1c33362c..1467ef046 100644 --- a/app/node/output/track/track.cpp +++ b/app/node/output/track/track.cpp @@ -34,6 +34,7 @@ TrackOutput::TrackOutput() : locked_(false) { block_input_ = new NodeInputArray("block_in", NodeParam::kAny); + block_input_->set_is_keyframable(false); AddInput(block_input_); connect(block_input_, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(BlockConnected(NodeEdgePtr))); connect(block_input_, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(BlockDisconnected(NodeEdgePtr))); @@ -111,6 +112,7 @@ void TrackOutput::SetTrackHeight(const int &height) void TrackOutput::Retranslate() { block_input_->set_name(tr("Blocks")); + muted_input_->set_name(tr("Muted")); } const int &TrackOutput::Index() diff --git a/app/widget/keyframeview/keyframeview.cpp b/app/widget/keyframeview/keyframeview.cpp index 0555a132e..d64826f63 100644 --- a/app/widget/keyframeview/keyframeview.cpp +++ b/app/widget/keyframeview/keyframeview.cpp @@ -1,21 +1,23 @@ #include "keyframeview.h" +#include #include -#include "core.h" #include "keyframeviewundo.h" #include "widget/menu/menu.h" #include "widget/menu/menushared.h" +#include "widget/nodeparamview/nodeparamviewundo.h" KeyframeView::KeyframeView(QWidget *parent) : TimelineViewBase(parent) { setBackgroundRole(QPalette::Base); setAlignment(Qt::AlignLeft | Qt::AlignTop); - setDragMode(NoDrag); + setDragMode(RubberBandDrag); setContextMenuPolicy(Qt::CustomContextMenu); connect(this, &KeyframeView::customContextMenuRequested, this, &KeyframeView::ShowContextMenu); + connect(Core::instance(), &Core::ToolChanged, this, &KeyframeView::ApplicationToolChanged); } void KeyframeView::Clear() @@ -52,7 +54,31 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) return; } - QGraphicsView::mousePressEvent(event); + active_tool_ = Core::instance()->tool(); + + rubberBandSelectionMode(); + + if (event->button() == Qt::LeftButton) { + QGraphicsView::mousePressEvent(event); + + if (active_tool_ == Tool::kPointer) { + QGraphicsItem* item_under_cursor = itemAt(event->pos()); + + if (item_under_cursor) { + QList selected_items = scene()->selectedItems(); + + drag_start_ = event->pos(); + + selected_keys_.resize(selected_items.size()); + + for (int i=0;i(selected_items.at(i)); + + selected_keys_.replace(i, {key, key->x(), key->key()->time()}); + } + } + } + } } void KeyframeView::mouseMoveEvent(QMouseEvent *event) @@ -61,7 +87,19 @@ void KeyframeView::mouseMoveEvent(QMouseEvent *event) return; } - QGraphicsView::mouseMoveEvent(event); + if (event->buttons() & Qt::LeftButton) { + QGraphicsView::mouseMoveEvent(event); + + if (active_tool_ == Tool::kPointer && !selected_keys_.isEmpty()) { + int x_diff = event->pos().x() - drag_start_.x(); + + foreach (const KeyframeItemAndTime& keypair, selected_keys_) { + KeyframeViewItem* item = keypair.key; + + item->setX(keypair.item_x + x_diff); + } + } + } } void KeyframeView::mouseReleaseEvent(QMouseEvent *event) @@ -70,7 +108,37 @@ void KeyframeView::mouseReleaseEvent(QMouseEvent *event) return; } - QGraphicsView::mouseReleaseEvent(event); + if (event->button() == Qt::LeftButton) { + QGraphicsView::mouseReleaseEvent(event); + + if (active_tool_ == Tool::kPointer && !selected_keys_.isEmpty()) { + QUndoCommand* command = new QUndoCommand(); + + // Calculate X movement and scaling to timeline time + int x_diff = event->pos().x() - drag_start_.x(); + double x_diff_scaled = static_cast(x_diff) / scale_; + + foreach (const KeyframeItemAndTime& keypair, selected_keys_) { + KeyframeViewItem* item = keypair.key; + + // Calculate the new time for this keyframe + double position = keypair.time.toDouble(); + position += x_diff_scaled; + + // Commit movement + qDebug() << "Moving key to" << rational::fromDouble(position); + + new NodeParamSetKeyframeTimeCommand(item->key(), + rational::fromDouble(position), + keypair.time, + command); + } + + Core::instance()->undo_stack()->push(command); + + selected_keys_.clear(); + } + } } void KeyframeView::ScaleChangedEvent(double scale) @@ -155,3 +223,12 @@ void KeyframeView::ShowContextMenu() } } } + +void KeyframeView::ApplicationToolChanged(Tool::Item tool) +{ + if (tool == Tool::kHand) { + setDragMode(ScrollHandDrag); + } else { + setDragMode(RubberBandDrag); + } +} diff --git a/app/widget/keyframeview/keyframeview.h b/app/widget/keyframeview/keyframeview.h index 1faacab8c..e017d6bc2 100644 --- a/app/widget/keyframeview/keyframeview.h +++ b/app/widget/keyframeview/keyframeview.h @@ -4,6 +4,7 @@ #include #include "common/rational.h" +#include "core.h" #include "keyframeviewitem.h" #include "widget/timelinewidget/view/timelineviewbase.h" @@ -28,10 +29,25 @@ protected: virtual void ScaleChangedEvent(double scale) override; private: + struct KeyframeItemAndTime { + KeyframeViewItem* key; + qreal item_x; + rational time; + }; + QMap item_map_; + Tool::Item active_tool_; + + QPoint drag_start_; + + QVector selected_keys_; + private slots: void ShowContextMenu(); + + void ApplicationToolChanged(Tool::Item tool); + }; #endif // KEYFRAMEVIEW_H diff --git a/app/widget/keyframeview/keyframeviewitem.cpp b/app/widget/keyframeview/keyframeviewitem.cpp index 60cf97970..8a8afacc0 100644 --- a/app/widget/keyframeview/keyframeviewitem.cpp +++ b/app/widget/keyframeview/keyframeviewitem.cpp @@ -16,16 +16,18 @@ KeyframeViewItem::KeyframeViewItem(NodeKeyframePtr key, qreal vcenter, QGraphics keyframe_size_ = QFontMetricsWidth(qApp->fontMetrics(), "Oi"); setFlag(QGraphicsItem::ItemIsSelectable); - connect(key.get(), &NodeKeyframe::TimeChanged, this, &KeyframeViewItem::UpdateRect); + connect(key.get(), &NodeKeyframe::TimeChanged, this, &KeyframeViewItem::UpdatePos); connect(key.get(), &NodeKeyframe::TypeChanged, this, &KeyframeViewItem::Redraw); - UpdateRect(); + setRect(0, 0, keyframe_size_, keyframe_size_); + + UpdatePos(); } void KeyframeViewItem::SetScale(double scale) { scale_ = scale; - UpdateRect(); + UpdatePos(); } NodeKeyframePtr KeyframeViewItem::key() const @@ -65,11 +67,11 @@ void KeyframeViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * } } -void KeyframeViewItem::UpdateRect() +void KeyframeViewItem::UpdatePos() { double x_center = key_->time().toDouble() * scale_; - setRect(x_center - keyframe_size_/2, middle_ - keyframe_size_/2, keyframe_size_, keyframe_size_); + setPos(x_center - keyframe_size_/2, middle_ - keyframe_size_/2); } void KeyframeViewItem::Redraw() diff --git a/app/widget/keyframeview/keyframeviewitem.h b/app/widget/keyframeview/keyframeviewitem.h index 5f0611561..721b6e6b9 100644 --- a/app/widget/keyframeview/keyframeviewitem.h +++ b/app/widget/keyframeview/keyframeviewitem.h @@ -28,7 +28,7 @@ private: int keyframe_size_; private slots: - void UpdateRect(); + void UpdatePos(); void Redraw(); diff --git a/app/widget/nodeparamview/nodeparamviewundo.cpp b/app/widget/nodeparamview/nodeparamviewundo.cpp index c981be51a..f7fa3ca1a 100644 --- a/app/widget/nodeparamview/nodeparamviewundo.cpp +++ b/app/widget/nodeparamview/nodeparamviewundo.cpp @@ -99,6 +99,14 @@ NodeParamSetKeyframeTimeCommand::NodeParamSetKeyframeTimeCommand(NodeKeyframePtr { } +NodeParamSetKeyframeTimeCommand::NodeParamSetKeyframeTimeCommand(NodeKeyframePtr key, const rational &new_time, const rational &old_time, QUndoCommand *parent) : + QUndoCommand(parent), + key_(key), + old_time_(old_time), + new_time_(new_time) +{ +} + void NodeParamSetKeyframeTimeCommand::redo() { key_->set_time(new_time_); diff --git a/app/widget/nodeparamview/nodeparamviewundo.h b/app/widget/nodeparamview/nodeparamviewundo.h index 3691f4f60..2fb41359f 100644 --- a/app/widget/nodeparamview/nodeparamviewundo.h +++ b/app/widget/nodeparamview/nodeparamviewundo.h @@ -51,6 +51,7 @@ private: class NodeParamSetKeyframeTimeCommand : public QUndoCommand { public: NodeParamSetKeyframeTimeCommand(NodeKeyframePtr key, const rational& time, QUndoCommand* parent = nullptr); + NodeParamSetKeyframeTimeCommand(NodeKeyframePtr key, const rational& new_time, const rational& old_time, QUndoCommand* parent = nullptr); virtual void redo() override; virtual void undo() override;