speedduration: more or less done now

This commit is contained in:
itsmattkc
2021-08-01 14:18:22 -07:00
parent bd94a934a3
commit 3593d70f34
4 changed files with 67 additions and 49 deletions
@@ -22,8 +22,11 @@
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QMessageBox>
#include "core.h"
#include "widget/nodeparamview/nodeparamviewundo.h"
#include "widget/timelinewidget/undo/timelineundopointer.h"
namespace olive {
@@ -105,7 +108,13 @@ SpeedDurationDialog::SpeedDurationDialog(const QVector<ClipBlock *> &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<GapBlock*>(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_);
}
}
+1 -24
View File
@@ -25,6 +25,7 @@
#include <QDialog>
#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<ClipBlock*> &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;
+22 -1
View File
@@ -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<ClipBlock*>(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<ClipBlock*>(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)
{
@@ -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<NodeInputPair, ArrayUI> array_ui_;
QHash<NodeInputPair, CollapseButton*> 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