diff --git a/app/common/timerange.cpp b/app/common/timerange.cpp index 8ab8c65e2..f25ebc398 100644 --- a/app/common/timerange.cpp +++ b/app/common/timerange.cpp @@ -99,7 +99,9 @@ void TimeRangeList::InsertTimeRange(const TimeRange &range) for (int i=0;i(AV_CH_LAYOUT_STEREO)); // Online/offline settings config_map_["OnlinePixelFormat"] = PixelFormat::PIX_FMT_RGBA32F; diff --git a/app/node/block/clip/clip.cpp b/app/node/block/clip/clip.cpp index f9f4efb38..a6d637889 100644 --- a/app/node/block/clip/clip.cpp +++ b/app/node/block/clip/clip.cpp @@ -64,12 +64,15 @@ void ClipBlock::InvalidateCache(const rational &start_range, const rational &end rational start = MediaToSequenceTime(start_range); rational end = MediaToSequenceTime(end_range); + // Ensure range actually covers this clip's area if (!(end < in() || start > out())) { + // Limit cache invalidation to clip lengths start = qMax(start, in()); end = qMin(end, out()); Node::InvalidateCache(start, end, from); + } } else { // Otherwise, pass signal along normally diff --git a/app/node/input.cpp b/app/node/input.cpp index a401947fa..b86b01a88 100644 --- a/app/node/input.cpp +++ b/app/node/input.cpp @@ -151,6 +151,7 @@ void NodeInput::Load(QXmlStreamReader *reader, QHash& par NodeKeyframePtr key = NodeKeyframe::Create(key_time, key_value, key_type, track); key->set_bezier_control_in(key_in_handle); key->set_bezier_control_out(key_out_handle); + key->set_parent(this); keyframe_tracks_[track].append(key); } } @@ -600,6 +601,7 @@ void NodeInput::remove_keyframe(NodeKeyframePtr key) disconnect(key.get(), &NodeKeyframe::BezierControlOutChanged, this, &NodeInput::KeyframeBezierOutChanged); keyframe_tracks_[key->track()].removeOne(key); + key->set_parent(nullptr); emit KeyframeRemoved(key); emit_time_range(time_affected); @@ -618,7 +620,7 @@ void NodeInput::KeyframeTimeChanged() // This keyframe needs resorting, store it and remove it from the list NodeKeyframePtr key_shared_ptr = keyframe_tracks_.at(key->track()).at(keyframe_index); - keyframe_tracks_.removeAt(keyframe_index); + keyframe_tracks_[key->track()].removeAt(keyframe_index); // Automatically insertion sort insert_keyframe_internal(key_shared_ptr); @@ -698,6 +700,8 @@ void NodeInput::insert_keyframe_internal(NodeKeyframePtr key) { KeyframeTrack& key_track = keyframe_tracks_[key->track()]; + key->set_parent(this); + for (int i=0;i; @@ -114,6 +116,9 @@ public: */ static BezierType get_opposing_bezier_type(BezierType type); + NodeInput* parent() const; + void set_parent(NodeInput* parent); + signals: /** * @brief Signal emitted when this keyframe's time is changed @@ -141,6 +146,8 @@ signals: void BezierControlOutChanged(const QPointF& d); private: + NodeInput* parent_; + rational time_; QVariant value_; diff --git a/app/widget/keyframeview/keyframeviewbase.cpp b/app/widget/keyframeview/keyframeviewbase.cpp index dda412f3c..49f5057f2 100644 --- a/app/widget/keyframeview/keyframeviewbase.cpp +++ b/app/widget/keyframeview/keyframeviewbase.cpp @@ -5,6 +5,7 @@ #include "dialog/keyframeproperties/keyframeproperties.h" #include "keyframeviewundo.h" +#include "node/node.h" #include "widget/menu/menu.h" #include "widget/menu/menushared.h" #include "widget/nodeparamview/nodeparamviewundo.h" @@ -96,6 +97,9 @@ void KeyframeViewBase::mousePressEvent(QMouseEvent *event) for (int i=0;i(selected_items.at(i)); + // Block signals for dragging for now + key->key()->parent()->blockSignals(true); + selected_keys_.replace(i, {key, key->x(), key->key()->time(), key->key()->value().toDouble()}); } } @@ -123,12 +127,17 @@ void KeyframeViewBase::mouseMoveEvent(QMouseEvent *event) false); } else if (!selected_keys_.isEmpty()) { foreach (const KeyframeItemAndTime& keypair, selected_keys_) { - // FIXME: Find some way to do single frame updates as the NodeParamViewWidgetBridge does? keypair.key->key()->set_time(CalculateNewTimeFromScreen(keypair.time, mouse_diff_scaled.x())); if (y_axis_enabled_) { keypair.key->key()->set_value(keypair.value - mouse_diff_scaled.y()); } + + // We emit a custom value changed signal while the keyframe is being dragged so only the currently viewed + // frame gets rendered in this time + keypair.key->key()->parent()->blockSignals(false); + emit keypair.key->key()->parent()->ValueChanged(GetPlayheadTime(), GetPlayheadTime()); + keypair.key->key()->parent()->blockSignals(true); } } } @@ -164,19 +173,29 @@ void KeyframeViewBase::mouseReleaseEvent(QMouseEvent *event) // Calculate the new time for this keyframe rational new_time = CalculateNewTimeFromScreen(keypair.time, mouse_diff_scaled.x()); + + // Commit movement + + // Since we overrode the cache signalling while dragging, we simulate here precisely the change that + // occurred by first setting the keyframe to its original position, and then letting the input handle + // the signalling once the undo command is pushed. + item->key()->set_time(keypair.time); new NodeParamSetKeyframeTimeCommand(item->key(), new_time, keypair.time, command); - // Commit value if we're setting a vaule + // Commit value if we're setting a value if (y_axis_enabled_) { + item->key()->set_value(keypair.value); new NodeParamSetKeyframeValueCommand(item->key(), keypair.value - mouse_diff_scaled.y(), keypair.value, command); } + + keypair.key->key()->parent()->blockSignals(false); } Core::instance()->undo_stack()->push(command); diff --git a/app/widget/timelinewidget/timelinescaledobject.cpp b/app/widget/timelinewidget/timelinescaledobject.cpp index b92361e1e..36b91e4eb 100644 --- a/app/widget/timelinewidget/timelinescaledobject.cpp +++ b/app/widget/timelinewidget/timelinescaledobject.cpp @@ -8,12 +8,12 @@ TimelineScaledObject::TimelineScaledObject() : } -const rational &TimelineScaledObject::timebase() +const rational &TimelineScaledObject::timebase() const { return timebase_; } -const double &TimelineScaledObject::timebase_dbl() +const double &TimelineScaledObject::timebase_dbl() const { return timebase_dbl_; } diff --git a/app/widget/timelinewidget/timelinescaledobject.h b/app/widget/timelinewidget/timelinescaledobject.h index c88d2bada..7a925467e 100644 --- a/app/widget/timelinewidget/timelinescaledobject.h +++ b/app/widget/timelinewidget/timelinescaledobject.h @@ -8,8 +8,8 @@ class TimelineScaledObject public: TimelineScaledObject(); - const rational& timebase(); - const double& timebase_dbl(); + const rational& timebase() const; + const double& timebase_dbl() const; static rational SceneToTime(const double &x, const double& x_scale, const rational& timebase, bool round = false); diff --git a/app/widget/timelinewidget/view/timelineviewbase.cpp b/app/widget/timelinewidget/view/timelineviewbase.cpp index 7f204560c..3fd901855 100644 --- a/app/widget/timelinewidget/view/timelineviewbase.cpp +++ b/app/widget/timelinewidget/view/timelineviewbase.cpp @@ -97,9 +97,9 @@ void TimelineViewBase::drawForeground(QPainter *painter, const QRectF &rect) } } -rational TimelineViewBase::GetPlayheadTime() +rational TimelineViewBase::GetPlayheadTime() const { - return rational(playhead_ * timebase().numerator(), timebase().denominator()); + return Timecode::timestamp_to_time(playhead_, timebase()); } void TimelineViewBase::SetDefaultDragMode(QGraphicsView::DragMode mode) diff --git a/app/widget/timelinewidget/view/timelineviewbase.h b/app/widget/timelinewidget/view/timelineviewbase.h index dfaa12c2f..ce4663614 100644 --- a/app/widget/timelinewidget/view/timelineviewbase.h +++ b/app/widget/timelinewidget/view/timelineviewbase.h @@ -43,7 +43,7 @@ protected: void SetLimitYAxis(bool e); - rational GetPlayheadTime(); + rational GetPlayheadTime() const; void SetDefaultDragMode(DragMode mode); const DragMode& GetDefaultDragMode() const;