From 3593d70f347ee0c40631221dd35eff71b5143930 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 1 Aug 2021 14:18:22 -0700 Subject: [PATCH] speedduration: more or less done now --- .../speedduration/speeddurationdialog.cpp | 60 +++++++++++-------- .../speedduration/speeddurationdialog.h | 25 +------- .../nodeparamview/nodeparamviewitem.cpp | 23 ++++++- app/widget/nodeparamview/nodeparamviewitem.h | 8 +++ 4 files changed, 67 insertions(+), 49 deletions(-) diff --git a/app/dialog/speedduration/speeddurationdialog.cpp b/app/dialog/speedduration/speeddurationdialog.cpp index 08a930c6e..f5308e8c3 100644 --- a/app/dialog/speedduration/speeddurationdialog.cpp +++ b/app/dialog/speedduration/speeddurationdialog.cpp @@ -22,8 +22,11 @@ #include #include +#include #include "core.h" +#include "widget/nodeparamview/nodeparamviewundo.h" +#include "widget/timelinewidget/undo/timelineundopointer.h" namespace olive { @@ -105,7 +108,13 @@ SpeedDurationDialog::SpeedDurationDialog(const QVector &clips, cons void SpeedDurationDialog::accept() { - super::accept(); + // We haven't implemented rippling yet, so warn the user + if (ripple_box_->isChecked()) { + // FIXME: Stub + if (QMessageBox::information(this, QString(), tr("Rippling is a stub and will not do anything. Do you wish to continue?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { + return; + } + } MultiUndoCommand *command = new MultiUndoCommand(); @@ -114,33 +123,47 @@ void SpeedDurationDialog::accept() if (link_box_->isChecked() && !dur_slider_->IsTristate()) { // Automatically determine speed from duration foreach (ClipBlock *c, clips_) { - command->add_child(new SetSpeedCommand(c, GetSpeedAdjustment(c->speed(), c->length(), dur_slider_->GetValue()))); + command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(NodeInput(c, ClipBlock::kSpeedInput)), GetSpeedAdjustment(c->speed(), c->length(), dur_slider_->GetValue()))); } } } else { // Set speeds to value of slider foreach (ClipBlock *c, clips_) { - command->add_child(new SetSpeedCommand(c, speed_slider_->GetValue())); + command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(NodeInput(c, ClipBlock::kSpeedInput)), speed_slider_->GetValue())); } } // Set duration values - if (ripple_box_->isChecked()) { - // Determine where and how much we need to ripple - foreach (ClipBlock *c, clips_) { - rational new_len = c->length(); - if (dur_slider_->IsTristate()) { - if (link_box_->isChecked() && !speed_slider_->IsTristate()) { - new_len = GetLengthAdjustment(c->length(), c->speed(), speed_slider_->GetValue(), timebase_); + foreach (ClipBlock *c, clips_) { + rational proposed_length = c->length(); + + if (dur_slider_->IsTristate()) { + if (link_box_->isChecked() && !speed_slider_->IsTristate()) { + proposed_length = GetLengthAdjustment(c->length(), c->speed(), speed_slider_->GetValue(), timebase_); + } + } else { + proposed_length = dur_slider_->GetValue(); + } + + if (proposed_length != c->length()) { + // Clip length should ideally change, but check if there's "room" to do so + if (proposed_length > c->length() && c->next()) { + if (GapBlock *gap = dynamic_cast(c->next())) { + proposed_length = qMin(proposed_length, gap->out() - c->in()); + } else { + proposed_length = c->length(); } - } else { - new_len = dur_slider_->GetValue(); + } + + if (proposed_length != c->length()) { + command->add_child(new BlockTrimCommand(c->track(), c, proposed_length, Timeline::kTrimOut)); } } } - Core::instance()->undo_stack()->push(command); + + super::accept(); } rational SpeedDurationDialog::GetLengthAdjustment(const rational &original_length, double original_speed, double new_speed, const rational &timebase) @@ -179,15 +202,4 @@ void SpeedDurationDialog::DurationChanged(const rational &r) } } -void SpeedDurationDialog::SetSpeedCommand::redo() -{ - old_speed_ = clip_->speed(); - clip_->set_speed(new_speed_); -} - -void SpeedDurationDialog::SetSpeedCommand::undo() -{ - clip_->set_speed(old_speed_); -} - } diff --git a/app/dialog/speedduration/speeddurationdialog.h b/app/dialog/speedduration/speeddurationdialog.h index b6428778b..135f77434 100644 --- a/app/dialog/speedduration/speeddurationdialog.h +++ b/app/dialog/speedduration/speeddurationdialog.h @@ -25,6 +25,7 @@ #include #include "node/block/clip/clip.h" +#include "node/block/gap/gap.h" #include "undo/undocommand.h" #include "widget/slider/floatslider.h" #include "widget/slider/rationalslider.h" @@ -37,30 +38,6 @@ class SpeedDurationDialog : public QDialog public: explicit SpeedDurationDialog(const QVector &clips, const rational &timebase, QWidget *parent = nullptr); - class SetSpeedCommand : public UndoCommand - { - public: - SetSpeedCommand(ClipBlock *clip, double new_speed) : - clip_(clip), - new_speed_(new_speed) - {} - - virtual void redo() override; - - virtual void undo() override; - - virtual Project *GetRelevantProject() const override - { - return clip_->project(); - } - - private: - ClipBlock *clip_; - double new_speed_; - double old_speed_; - - }; - public slots: virtual void accept() override; diff --git a/app/widget/nodeparamview/nodeparamviewitem.cpp b/app/widget/nodeparamview/nodeparamviewitem.cpp index ad01f6ba0..519ae141f 100644 --- a/app/widget/nodeparamview/nodeparamviewitem.cpp +++ b/app/widget/nodeparamview/nodeparamviewitem.cpp @@ -27,6 +27,7 @@ #include "common/qtutils.h" #include "core.h" +#include "dialog/speedduration/speeddurationdialog.h" #include "node/project/sequence/sequence.h" #include "nodeparamviewundo.h" @@ -35,6 +36,7 @@ namespace olive { const int NodeParamViewItemBody::kKeyControlColumn = 10; const int NodeParamViewItemBody::kArrayInsertColumn = kKeyControlColumn-1; const int NodeParamViewItemBody::kArrayRemoveColumn = kArrayInsertColumn-1; +const int NodeParamViewItemBody::kExtraButtonColumn = kKeyControlColumn-1; // 0 is for the array collapse button, 1 is for the main label, widgets start at 2 const int NodeParamViewItemBody::kWidgetStartColumn = 2; @@ -221,7 +223,8 @@ void NodeParamViewItemTitleBar::mouseDoubleClickEvent(QMouseEvent *event) } NodeParamViewItemBody::NodeParamViewItemBody(Node* node, QWidget *parent) : - QWidget(parent) + QWidget(parent), + node_(node) { QGridLayout* root_layout = new QGridLayout(this); @@ -313,6 +316,14 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const connect(remove_element_btn, &NodeParamViewArrayButton::clicked, this, &NodeParamViewItemBody::ArrayRemoveClicked); } + } else if (dynamic_cast(node) && input == ClipBlock::kSpeedInput) { + // Special behavior - this was the most preferable way to do this so we could support multiple + // nodes per item one day + QPushButton *btn = new QPushButton(tr("...")); + btn->setFixedWidth(btn->sizeHint().height()); + connect(btn, &QPushButton::clicked, this, &NodeParamViewItemBody::ShowSpeedDurationDialogForNode); + layout->addWidget(btn, row, kExtraButtonColumn); + ui_objects.extra_btn = btn; } // Create a widget/input bridge for this input @@ -541,6 +552,8 @@ void NodeParamViewItemBody::ToggleArrayExpanded() void NodeParamViewItemBody::SetTimebase(const rational& timebase) { + timebase_ = timebase; + foreach (const InputUI& ui_obj, input_ui_map_) { ui_obj.widget_bridge->SetTimebase(timebase); } @@ -552,11 +565,19 @@ void NodeParamViewItemBody::ReplaceWidgets(const NodeInput &input) PlaceWidgetsFromBridge(ui.layout, ui.widget_bridge, ui.row); } +void NodeParamViewItemBody::ShowSpeedDurationDialogForNode() +{ + // We should only get there if the node is a clip, determined by the dynamic_cast in CreateWidgets + SpeedDurationDialog sdd({static_cast(node_)}, timebase_, this); + sdd.exec(); +} + NodeParamViewItemBody::InputUI::InputUI() : main_label(nullptr), widget_bridge(nullptr), connected_label(nullptr), key_control(nullptr), + extra_btn(nullptr), array_insert_btn(nullptr), array_remove_btn(nullptr) { diff --git a/app/widget/nodeparamview/nodeparamviewitem.h b/app/widget/nodeparamview/nodeparamviewitem.h index b000b6282..f312fa32d 100644 --- a/app/widget/nodeparamview/nodeparamviewitem.h +++ b/app/widget/nodeparamview/nodeparamviewitem.h @@ -111,6 +111,7 @@ private: NodeParamViewKeyframeControl* key_control; QGridLayout* layout; int row; + QPushButton *extra_btn; NodeParamViewArrayButton* array_insert_btn; NodeParamViewArrayButton* array_remove_btn; @@ -124,10 +125,14 @@ private: NodeParamViewArrayButton* append_btn; }; + Node *node_; + QHash array_ui_; QHash array_collapse_buttons_; + rational timebase_; + /** * @brief The column to place the keyframe controls in * @@ -138,6 +143,7 @@ private: static const int kArrayInsertColumn; static const int kArrayRemoveColumn; + static const int kExtraButtonColumn; static const int kWidgetStartColumn; @@ -158,6 +164,8 @@ private slots: void ReplaceWidgets(const NodeInput& input); + void ShowSpeedDurationDialogForNode(); + }; class NodeParamViewItem : public QDockWidget