From 4e5db91c17d45f3a2fe56ffc5c5c557e42624b6b Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 25 Jan 2021 11:05:09 +1100 Subject: [PATCH] keyframeviewbase: cleaned up code and show tooltip values in input's desired format --- app/node/audio/pan/pan.cpp | 4 +- app/node/audio/volume/volume.cpp | 4 +- app/node/block/block.cpp | 3 +- app/node/distort/crop/cropdistortnode.cpp | 9 +- app/node/filter/stroke/stroke.cpp | 3 +- app/node/generator/matrix/matrix.cpp | 4 +- app/widget/keyframeview/keyframeviewbase.cpp | 240 ++++++++---------- app/widget/keyframeview/keyframeviewbase.h | 2 - .../nodeparamviewwidgetbridge.cpp | 11 +- app/widget/slider/floatslider.cpp | 15 +- app/widget/slider/floatslider.h | 2 + 11 files changed, 135 insertions(+), 162 deletions(-) diff --git a/app/node/audio/pan/pan.cpp b/app/node/audio/pan/pan.cpp index 6665be2e0..19ada088b 100644 --- a/app/node/audio/pan/pan.cpp +++ b/app/node/audio/pan/pan.cpp @@ -20,6 +20,8 @@ #include "pan.h" +#include "widget/slider/floatslider.h" + namespace olive { PanNode::PanNode() @@ -29,7 +31,7 @@ PanNode::PanNode() panning_input_ = new NodeInput(this, QStringLiteral("panning_in"), NodeValue::kFloat, 0.0); panning_input_->setProperty("min", -1.0); panning_input_->setProperty("max", 1.0); - panning_input_->setProperty("view", QStringLiteral("percent")); + panning_input_->setProperty("view", FloatSlider::kPercentage); } Node *PanNode::copy() const diff --git a/app/node/audio/volume/volume.cpp b/app/node/audio/volume/volume.cpp index 8197f2ec7..8172fdfaa 100644 --- a/app/node/audio/volume/volume.cpp +++ b/app/node/audio/volume/volume.cpp @@ -20,6 +20,8 @@ #include "volume.h" +#include "widget/slider/floatslider.h" + namespace olive { VolumeNode::VolumeNode() @@ -29,7 +31,7 @@ VolumeNode::VolumeNode() volume_input_ = new NodeInput(this, QStringLiteral("volume_in"), NodeValue::kFloat, 1.0); volume_input_->setProperty("min", 0.0); - volume_input_->setProperty("view", QStringLiteral("db")); + volume_input_->setProperty("view", FloatSlider::kDecibel); } Node *VolumeNode::copy() const diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp index 3dada5b15..2787d0974 100644 --- a/app/node/block/block.cpp +++ b/app/node/block/block.cpp @@ -24,6 +24,7 @@ #include "node/output/track/track.h" #include "transition/transition.h" +#include "widget/slider/floatslider.h" namespace olive { @@ -52,7 +53,7 @@ Block::Block() : speed_input_ = new NodeInput(this, QStringLiteral("speed_in"), NodeValue::kFloat); speed_input_->SetStandardValue(1.0); - speed_input_->setProperty("view", QStringLiteral("percent")); + speed_input_->setProperty("view", FloatSlider::kPercentage); // A block's length must be greater than 0 set_length_and_media_out(1); diff --git a/app/node/distort/crop/cropdistortnode.cpp b/app/node/distort/crop/cropdistortnode.cpp index fd9eb23ae..afc323560 100644 --- a/app/node/distort/crop/cropdistortnode.cpp +++ b/app/node/distort/crop/cropdistortnode.cpp @@ -21,6 +21,7 @@ #include "cropdistortnode.h" #include "common/lerp.h" +#include "widget/slider/floatslider.h" namespace olive { @@ -31,22 +32,22 @@ CropDistortNode::CropDistortNode() left_input_ = new NodeInput(this, QStringLiteral("left_in"), NodeValue::kFloat, 0.0); left_input_->setProperty("min", 0.0); left_input_->setProperty("max", 1.0); - left_input_->setProperty("view", QStringLiteral("percent")); + left_input_->setProperty("view", FloatSlider::kPercentage); top_input_ = new NodeInput(this, QStringLiteral("top_in"), NodeValue::kFloat, 0.0); top_input_->setProperty("min", 0.0); top_input_->setProperty("max", 1.0); - top_input_->setProperty("view", QStringLiteral("percent")); + top_input_->setProperty("view", FloatSlider::kPercentage); right_input_ = new NodeInput(this, QStringLiteral("right_in"), NodeValue::kFloat, 0.0); right_input_->setProperty("min", 0.0); right_input_->setProperty("max", 1.0); - right_input_->setProperty("view", QStringLiteral("percent")); + right_input_->setProperty("view", FloatSlider::kPercentage); bottom_input_ = new NodeInput(this, QStringLiteral("bottom_in"), NodeValue::kFloat, 0.0); bottom_input_->setProperty("min", 0.0); bottom_input_->setProperty("max", 1.0); - bottom_input_->setProperty("view", QStringLiteral("percent")); + bottom_input_->setProperty("view", FloatSlider::kPercentage); feather_input_ = new NodeInput(this, QStringLiteral("feather_in"), NodeValue::kFloat, 0.0); feather_input_->setProperty("min", 0.0); diff --git a/app/node/filter/stroke/stroke.cpp b/app/node/filter/stroke/stroke.cpp index 806676c99..70cabe396 100644 --- a/app/node/filter/stroke/stroke.cpp +++ b/app/node/filter/stroke/stroke.cpp @@ -21,6 +21,7 @@ #include "stroke.h" #include "render/color.h" +#include "widget/slider/floatslider.h" namespace olive { @@ -37,7 +38,7 @@ StrokeFilterNode::StrokeFilterNode() radius_input_->setProperty("min", 0.0f); opacity_input_ = new NodeInput(this, QStringLiteral("opacity_in"), NodeValue::kFloat, 1.0f); - opacity_input_->setProperty("view", QStringLiteral("percent")); + opacity_input_->setProperty("view", FloatSlider::kPercentage); opacity_input_->setProperty("min", 0.0f); opacity_input_->setProperty("max", 1.0f); diff --git a/app/node/generator/matrix/matrix.cpp b/app/node/generator/matrix/matrix.cpp index 78c3200f3..ac04b173f 100644 --- a/app/node/generator/matrix/matrix.cpp +++ b/app/node/generator/matrix/matrix.cpp @@ -23,6 +23,8 @@ #include #include +#include "widget/slider/floatslider.h" + namespace olive { MatrixGenerator::MatrixGenerator() @@ -33,7 +35,7 @@ MatrixGenerator::MatrixGenerator() scale_input_ = new NodeInput(this, QStringLiteral("scale_in"), NodeValue::kVec2, QVector2D(1.0f, 1.0f)); scale_input_->setProperty("min", QVector2D(0, 0)); - scale_input_->setProperty("view", QStringLiteral("percent")); + scale_input_->setProperty("view", FloatSlider::kPercentage); scale_input_->setProperty("disabley", true); uniform_scale_input_ = new NodeInput(this, QStringLiteral("uniform_scale_in"), NodeValue::kBoolean, true); diff --git a/app/widget/keyframeview/keyframeviewbase.cpp b/app/widget/keyframeview/keyframeviewbase.cpp index 7e0e0aeb2..b4e5ec4dc 100644 --- a/app/widget/keyframeview/keyframeviewbase.cpp +++ b/app/widget/keyframeview/keyframeviewbase.cpp @@ -194,15 +194,68 @@ void KeyframeViewBase::mouseMoveEvent(QMouseEvent *event) } if (dragging_bezier_point_) { - ProcessBezierDrag(mouse_diff_scaled, - !(event->modifiers() & Qt::ControlModifier), - false); + + // Flip the mouse Y because bezier control points are drawn bottom to top, not top to bottom + mouse_diff_scaled.setY(-mouse_diff_scaled.y()); + + QPointF new_bezier_pos = GenerateBezierControlPosition(dragging_bezier_point_->mode(), + dragging_bezier_point_start_, + mouse_diff_scaled); + + // If the user is NOT holding control, we set the other handle to the exact negative of this handle + QPointF new_opposing_pos; + NodeKeyframe::BezierType opposing_type = NodeKeyframe::get_opposing_bezier_type(dragging_bezier_point_->mode()); + + + if (!(event->modifiers() & Qt::ControlModifier)) { + new_opposing_pos = GenerateBezierControlPosition(opposing_type, + dragging_bezier_point_opposing_start_, + -mouse_diff_scaled); + } else { + new_opposing_pos = dragging_bezier_point_opposing_start_; + } + + dragging_bezier_point_->key()->set_bezier_control(dragging_bezier_point_->mode(), + new_bezier_pos); + + dragging_bezier_point_->key()->set_bezier_control(opposing_type, + new_opposing_pos); + + emit Dragged(qRound(dragging_bezier_point_->x()), qRound(dragging_bezier_point_->y())); + } else if (!selected_keys_.isEmpty()) { + + // Validate movement - ensure no keyframe goes above its max point or below its min point + FloatSlider::DisplayType display_type = FloatSlider::kNormal; + + if (IsYAxisEnabled()) { + foreach (const KeyframeItemAndTime& keypair, selected_keys_) { + NodeInput* input = keypair.key->key()->parent(); + QList properties = input->dynamicPropertyNames(); + + double new_val = keypair.value - mouse_diff_scaled.y(); + double limited = new_val; + + if (properties.contains("min")) { + limited = qMax(limited, input->property("min").toDouble()); + } + + if (properties.contains("max")) { + limited = qMin(limited, input->property("max").toDouble()); + } + + if (limited != new_val) { + mouse_diff_scaled.setY(keypair.value - limited); + } + } + + NodeInput* initial_drag_input = initial_drag_item_->key()->parent(); + if (initial_drag_input->dynamicPropertyNames().contains("view")) { + display_type = static_cast(initial_drag_input->property("view").toInt()); + } + } + foreach (const KeyframeItemAndTime& keypair, selected_keys_) { - //NodeInput* input_parent = keypair.key->key()->parent(); - - //input_parent->blockSignals(true); - rational node_time = GetAdjustedTime(GetTimeTarget(), keypair.key->key()->parent()->parent(), CalculateNewTimeFromScreen(keypair.time, mouse_diff_scaled.x()), @@ -213,12 +266,6 @@ void KeyframeViewBase::mouseMoveEvent(QMouseEvent *event) if (IsYAxisEnabled()) { 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 - //input_parent->blockSignals(false); - - //input_parent->parentNode()->InvalidateVisible(input_parent, input_parent); } // Show information about this keyframe @@ -231,7 +278,7 @@ void KeyframeViewBase::mouseMoveEvent(QMouseEvent *event) if (ok) { tip.append('\n'); - tip.append(QString::number(num_value)); + tip.append(FloatSlider::ValueToString(num_value, display_type, 2, true)); } // Force viewport to update since Qt might try to optimize it out if the keyframe is @@ -243,6 +290,7 @@ void KeyframeViewBase::mouseMoveEvent(QMouseEvent *event) QToolTip::showText(QCursor::pos(), tip); emit Dragged(qRound(initial_drag_item_->x()), qRound(initial_drag_item_->y())); + } } } @@ -258,67 +306,58 @@ void KeyframeViewBase::mouseReleaseEvent(QMouseEvent *event) QGraphicsView::mouseReleaseEvent(event); if (dragging_) { - QPointF mouse_diff_scaled = GetScaledCursorPos(mapToScene(event->pos()) - drag_start_); + if (dragging_bezier_point_) { + QUndoCommand* command = new QUndoCommand(); - if (event->modifiers() & Qt::ShiftModifier) { - // If holding shift, only move one axis - mouse_diff_scaled.setY(0); - } + // Create undo command with the current bezier point and the old one + new KeyframeSetBezierControlPoint(dragging_bezier_point_->key(), + dragging_bezier_point_->mode(), + dragging_bezier_point_->key()->bezier_control(dragging_bezier_point_->mode()), + dragging_bezier_point_start_, + command); - if (!mouse_diff_scaled.isNull()) { - if (dragging_bezier_point_) { - ProcessBezierDrag(mouse_diff_scaled, - !(event->modifiers() & Qt::ControlModifier), - true); + if (!(event->modifiers() & Qt::ControlModifier)) { + auto opposing_type = NodeKeyframe::get_opposing_bezier_type(dragging_bezier_point_->mode()); - dragging_bezier_point_ = nullptr; - } else if (!selected_keys_.isEmpty()) { - QUndoCommand* command = new QUndoCommand(); - - foreach (const KeyframeItemAndTime& keypair, selected_keys_) { - KeyframeViewItem* item = keypair.key; - - keypair.key->key()->parent()->blockSignals(true); - - // Calculate the new time for this keyframe - rational node_time = GetAdjustedTime(GetTimeTarget(), - keypair.key->key()->parent()->parent(), - CalculateNewTimeFromScreen(keypair.time, mouse_diff_scaled.x()), - true); - - - - // 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(), - node_time, - keypair.time, - command); - - // Commit value if we're setting a value - if (IsYAxisEnabled()) { - double new_val = keypair.value - mouse_diff_scaled.y(); - item->key()->set_value(new_val); - new NodeParamSetKeyframeValueCommand(item->key(), - new_val, - keypair.value, - command); - } - - keypair.key->key()->parent()->blockSignals(false); - } - - Core::instance()->undo_stack()->push(command); + new KeyframeSetBezierControlPoint(dragging_bezier_point_->key(), + opposing_type, + dragging_bezier_point_->key()->bezier_control(opposing_type), + dragging_bezier_point_opposing_start_, + command); } + + dragging_bezier_point_ = nullptr; + + Core::instance()->undo_stack()->push(command); + } else if (!selected_keys_.isEmpty()) { + QUndoCommand* command = new QUndoCommand(); + + foreach (const KeyframeItemAndTime& keypair, selected_keys_) { + NodeKeyframe* item = keypair.key->key(); + + // Commit movement + new NodeParamSetKeyframeTimeCommand(item, + item->time(), + keypair.time, + command); + + // Commit value if we're setting a value + if (IsYAxisEnabled()) { + new NodeParamSetKeyframeValueCommand(item, + item->value(), + keypair.value, + command); + } + } + + Core::instance()->undo_stack()->push(command); } selected_keys_.clear(); dragging_ = false; + + QToolTip::hideText(); } } } @@ -380,75 +419,6 @@ QPointF KeyframeViewBase::GenerateBezierControlPosition(const NodeKeyframe::Bezi return new_bezier_pos; } -void KeyframeViewBase::ProcessBezierDrag(QPointF mouse_diff_scaled, bool include_opposing, bool undoable) -{ - // Flip the mouse Y because bezier control points are drawn bottom to top, not top to bottom - mouse_diff_scaled.setY(-mouse_diff_scaled.y()); - - QPointF new_bezier_pos = GenerateBezierControlPosition(dragging_bezier_point_->mode(), - dragging_bezier_point_start_, - mouse_diff_scaled); - - // If the user is NOT holding control, we set the other handle to the exact negative of this handle - QPointF new_opposing_pos; - NodeKeyframe::BezierType opposing_type = NodeKeyframe::get_opposing_bezier_type(dragging_bezier_point_->mode()); - - if (include_opposing) { - new_opposing_pos = GenerateBezierControlPosition(opposing_type, - dragging_bezier_point_opposing_start_, - -mouse_diff_scaled); - } else { - new_opposing_pos = dragging_bezier_point_opposing_start_; - } - - //NodeInput* input_parent = dragging_bezier_point_->key()->parent(); - - if (undoable) { - QUndoCommand* command = new QUndoCommand(); - - // Similar to the code in MouseRelease, we manipulated the signalling earlier and need to set the keys back to their - // original position to allow the input to signal correctly when the undo command is pushed. - - //input_parent->blockSignals(true); - - dragging_bezier_point_->key()->set_bezier_control(dragging_bezier_point_->mode(), - dragging_bezier_point_start_); - - new KeyframeSetBezierControlPoint(dragging_bezier_point_->key(), - dragging_bezier_point_->mode(), - new_bezier_pos, - dragging_bezier_point_start_, - command); - - if (include_opposing) { - dragging_bezier_point_->key()->set_bezier_control(opposing_type, - dragging_bezier_point_opposing_start_); - - new KeyframeSetBezierControlPoint(dragging_bezier_point_->key(), - opposing_type, - new_opposing_pos, - dragging_bezier_point_opposing_start_, - command); - } - - //input_parent->blockSignals(false); - - Core::instance()->undo_stack()->push(command); - } else { - //input_parent->blockSignals(true); - - dragging_bezier_point_->key()->set_bezier_control(dragging_bezier_point_->mode(), - new_bezier_pos); - - dragging_bezier_point_->key()->set_bezier_control(opposing_type, - new_opposing_pos); - - //input_parent->blockSignals(false); - - //input_parent->parentNode()->InvalidateVisible(input_parent, input_parent); - } -} - QPointF KeyframeViewBase::GetScaledCursorPos(const QPointF &cursor_pos) { return QPointF(cursor_pos.x() / GetScale(), diff --git a/app/widget/keyframeview/keyframeviewbase.h b/app/widget/keyframeview/keyframeviewbase.h index 20952dfb9..687e63f45 100644 --- a/app/widget/keyframeview/keyframeviewbase.h +++ b/app/widget/keyframeview/keyframeviewbase.h @@ -83,8 +83,6 @@ private: const QPointF& start_point, const QPointF& scaled_cursor_diff); - void ProcessBezierDrag(QPointF mouse_diff_scaled, bool include_opposing, bool undoable); - QPointF GetScaledCursorPos(const QPointF &cursor_pos); struct KeyframeItemAndTime { diff --git a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp index 6d828f03b..a9e13dc65 100644 --- a/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp +++ b/app/widget/nodeparamview/nodeparamviewwidgetbridge.cpp @@ -650,16 +650,7 @@ void NodeParamViewWidgetBridge::PropertyChanged(const QString &key, const QVaria // Parameters for floats and vectors only if (input_->GetDataType() == NodeValue::kFloat || NodeValue::type_is_vector(input_->GetDataType())) { if (key == QStringLiteral("view")) { - FloatSlider::DisplayType display_type; - - if (value == QStringLiteral("percent")) { - display_type = FloatSlider::kPercentage; - } else if (value == QStringLiteral("db")) { - display_type = FloatSlider::kDecibel; - } else { - // Avoid undefined behavior - return; - } + FloatSlider::DisplayType display_type = static_cast(value.toInt()); foreach (QWidget* w, widgets_) { static_cast(w)->SetDisplayType(display_type); diff --git a/app/widget/slider/floatslider.cpp b/app/widget/slider/floatslider.cpp index c7f5f43e9..8baa4000b 100644 --- a/app/widget/slider/floatslider.cpp +++ b/app/widget/slider/floatslider.cpp @@ -85,11 +85,9 @@ void FloatSlider::SetAutoTrimDecimalPlaces(bool e) ForceLabelUpdate(); } -QString FloatSlider::ValueToString(const QVariant &v) +QString FloatSlider::ValueToString(double val, FloatSlider::DisplayType display, int decimal_places, bool autotrim_decimal_places) { - double val = v.toDouble(); - - switch (display_type_) { + switch (display) { case kNormal: // Do nothing, skip to the return string at the end break; @@ -109,9 +107,9 @@ QString FloatSlider::ValueToString(const QVariant &v) break; } - QString s = QString::number(val, 'f', decimal_places_); + QString s = QString::number(val, 'f', decimal_places); - if (autotrim_decimal_places_) { + if (autotrim_decimal_places) { while (s.endsWith('0') && s.at(s.size() - 2).isDigit()) { s = s.left(s.size() - 1); @@ -121,6 +119,11 @@ QString FloatSlider::ValueToString(const QVariant &v) return s; } +QString FloatSlider::ValueToString(const QVariant &v) +{ + return ValueToString(v.toDouble(), display_type_, decimal_places_, autotrim_decimal_places_); +} + QVariant FloatSlider::StringToValue(const QString &s, bool *ok) { switch (display_type_) { diff --git a/app/widget/slider/floatslider.h b/app/widget/slider/floatslider.h index 69c7eeedf..f7d71d6a9 100644 --- a/app/widget/slider/floatslider.h +++ b/app/widget/slider/floatslider.h @@ -51,6 +51,8 @@ public: void SetAutoTrimDecimalPlaces(bool e); + static QString ValueToString(double val, DisplayType display, int decimal_places, bool autotrim_decimal_places); + protected: virtual QString ValueToString(const QVariant& v) override;