speeddurdialog now sets speed correctly

This commit is contained in:
itsmattkc
2021-08-01 13:34:42 -07:00
parent b20a839332
commit c36efddf86
6 changed files with 211 additions and 19 deletions
@@ -23,18 +23,28 @@
#include <QDialogButtonBox>
#include <QGridLayout>
#include "core.h"
namespace olive {
SpeedDurationDialog::SpeedDurationDialog(const QVector<ClipBlock *> &clips, QWidget *parent) :
QDialog(parent)
#define super QDialog
SpeedDurationDialog::SpeedDurationDialog(const QVector<ClipBlock *> &clips, const rational &timebase, QWidget *parent) :
super(parent),
clips_(clips),
timebase_(timebase)
{
setWindowTitle(tr("Speed/Duration"));
QGridLayout *layout = new QGridLayout(this);
int row = 0;
layout->addWidget(new QLabel(tr("Speed:")), row, 0);
FloatSlider *speed_slider_ = new FloatSlider();
speed_slider_ = new FloatSlider();
speed_slider_->SetDisplayType(FloatSlider::kPercentage);
connect(speed_slider_, &FloatSlider::ValueChanged, this, &SpeedDurationDialog::SpeedChanged);
layout->addWidget(speed_slider_, row, 1);
row++;
@@ -42,11 +52,20 @@ SpeedDurationDialog::SpeedDurationDialog(const QVector<ClipBlock *> &clips, QWid
layout->addWidget(new QLabel(tr("Duration:")), row, 0);
dur_slider_ = new RationalSlider();
dur_slider_->SetTimebase(timebase);
dur_slider_->SetDisplayType(RationalSlider::kTime);
connect(dur_slider_, &RationalSlider::ValueChanged, this, &SpeedDurationDialog::DurationChanged);
layout->addWidget(dur_slider_, row, 1);
row++;
ripple_box_ = new QCheckBox();
link_box_ = new QCheckBox(tr("Link Speed and Duration"));
link_box_->setChecked(true);
layout->addWidget(link_box_, row, 0, 1, 2);
row++;
ripple_box_ = new QCheckBox(tr("Ripple Trailing Clips"));
layout->addWidget(ripple_box_, row, 0, 1, 2);
row++;
@@ -56,6 +75,119 @@ SpeedDurationDialog::SpeedDurationDialog(const QVector<ClipBlock *> &clips, QWid
connect(btns, &QDialogButtonBox::accepted, this, &SpeedDurationDialog::accept);
connect(btns, &QDialogButtonBox::rejected, this, &SpeedDurationDialog::reject);
layout->addWidget(btns, row, 0, 1, 2);
// Determine which speed value to use
start_speed_ = clips.first()->speed();
start_duration_ = clips.first()->length();
for (int i=1; i<clips.size(); i++) {
if (!qIsNaN(start_speed_) && !qFuzzyCompare(start_speed_, clips.at(i)->speed())) {
// Speed differs per clip
start_speed_ = qSNaN();
}
if (start_duration_ != -1 && clips.at(i)->length() != start_duration_) {
start_duration_ = -1;
}
}
if (qIsNaN(start_speed_)) {
speed_slider_->SetTristate();
} else {
speed_slider_->SetValue(start_speed_);
}
if (start_duration_ == -1) {
dur_slider_->SetTristate();
} else {
dur_slider_->SetValue(start_duration_);
}
}
void SpeedDurationDialog::accept()
{
super::accept();
MultiUndoCommand *command = new MultiUndoCommand();
// Set speed values
if (speed_slider_->IsTristate()) {
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())));
}
}
} else {
// Set speeds to value of slider
foreach (ClipBlock *c, clips_) {
command->add_child(new SetSpeedCommand(c, 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_);
}
} else {
new_len = dur_slider_->GetValue();
}
}
}
Core::instance()->undo_stack()->push(command);
}
rational SpeedDurationDialog::GetLengthAdjustment(const rational &original_length, double original_speed, double new_speed, const rational &timebase)
{
return Timecode::snap_time_to_timebase(rational::fromDouble(original_length.toDouble() / new_speed * original_speed), timebase);
}
double SpeedDurationDialog::GetSpeedAdjustment(double original_speed, const rational &original_length, const rational &new_length)
{
return original_speed / new_length.toDouble() * original_length.toDouble();
}
void SpeedDurationDialog::SpeedChanged(double s)
{
if (!link_box_->isChecked()) {
return;
}
if (start_duration_ == -1) {
dur_slider_->SetTristate();
} else {
dur_slider_->SetValue(GetLengthAdjustment(start_duration_, start_speed_, s, timebase_));
}
}
void SpeedDurationDialog::DurationChanged(const rational &r)
{
if (!link_box_->isChecked()) {
return;
}
if (qIsNaN(start_speed_)) {
speed_slider_->SetTristate();
} else {
speed_slider_->SetValue(GetSpeedAdjustment(start_speed_, start_duration_, r));
}
}
void SpeedDurationDialog::SetSpeedCommand::redo()
{
old_speed_ = clip_->speed();
clip_->set_speed(new_speed_);
}
void SpeedDurationDialog::SetSpeedCommand::undo()
{
clip_->set_speed(old_speed_);
}
}
+48 -1
View File
@@ -25,6 +25,7 @@
#include <QDialog>
#include "node/block/clip/clip.h"
#include "undo/undocommand.h"
#include "widget/slider/floatslider.h"
#include "widget/slider/rationalslider.h"
@@ -34,17 +35,63 @@ class SpeedDurationDialog : public QDialog
{
Q_OBJECT
public:
explicit SpeedDurationDialog(const QVector<ClipBlock*> &clips, QWidget *parent = nullptr);
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;
signals:
private:
static rational GetLengthAdjustment(const rational &original_length, double original_speed, double new_speed, const rational &timebase);
static double GetSpeedAdjustment(double original_speed, const rational &original_length, const rational &new_length);
QVector<ClipBlock*> clips_;
FloatSlider *speed_slider_;
RationalSlider *dur_slider_;
QCheckBox *link_box_;
QCheckBox *ripple_box_;
double start_speed_;
rational start_duration_;
rational timebase_;
private slots:
void SpeedChanged(double s);
void DurationChanged(const rational &r);
};
}
+5
View File
@@ -92,6 +92,11 @@ public:
virtual void NudgeRight() override;
void ShowSpeedDurationDialogForSelectedClips()
{
timeline_widget()->ShowSpeedDurationDialogForSelectedClips();
}
void InsertFootageAtPlayhead(const QVector<ViewerOutput *> &footage);
void OverwriteFootageAtPlayhead(const QVector<ViewerOutput *> &footage);
+2 -14
View File
@@ -22,7 +22,6 @@
#include "core.h"
#include "common/timecodefunctions.h"
#include "dialog/speedduration/speeddurationdialog.h"
#include "panel/panelmanager.h"
#include "panel/timeline/timeline.h"
#include "window/mainwindow/mainwindow.h"
@@ -47,7 +46,7 @@ MenuShared::MenuShared()
edit_delete_item_ = Menu::CreateItem(this, "delete", this, &MenuShared::DeleteSelectedTriggered, "Del");
edit_ripple_delete_item_ = Menu::CreateItem(this, "rippledelete", this, &MenuShared::RippleDeleteTriggered, "Shift+Del");
edit_split_item_ = Menu::CreateItem(this, "split", this, &MenuShared::SplitAtPlayheadTriggered, "Ctrl+K");
edit_speedduration_item_ = Menu::CreateItem(this, "speeddur", this, &MenuShared::SpeedDurationTriggered);
edit_speedduration_item_ = Menu::CreateItem(this, "speeddur", this, &MenuShared::SpeedDurationTriggered, "Ctrl+R");
// "In/Out" menu shared items
inout_set_in_item_ = Menu::CreateItem(this, "setinpoint", this, &MenuShared::SetInTriggered, "I");
@@ -310,18 +309,7 @@ void MenuShared::SpeedDurationTriggered()
TimelinePanel* timeline = PanelManager::instance()->MostRecentlyFocused<TimelinePanel>();
if (timeline) {
QVector<Block*> sel = timeline->GetSelectedBlocks();
QVector<ClipBlock*> clips;
foreach (Block *b, sel) {
ClipBlock *c = dynamic_cast<ClipBlock*>(b);
if (c) {
clips.append(c);
}
}
SpeedDurationDialog sdd(clips, Core::instance()->main_window());
sdd.exec();
timeline->ShowSpeedDurationDialogForSelectedClips();
}
}
@@ -30,6 +30,7 @@
#include "common/timecodefunctions.h"
#include "dialog/nodeproperties/nodepropertiesdialog.h"
#include "dialog/sequence/sequence.h"
#include "dialog/speedduration/speeddurationdialog.h"
#include "node/block/transition/transition.h"
#include "tool/add.h"
#include "tool/beam.h"
@@ -738,6 +739,23 @@ void TimelineWidget::NudgeRight()
}
}
void TimelineWidget::ShowSpeedDurationDialogForSelectedClips()
{
QVector<ClipBlock*> clips;
foreach (Block *b, selected_blocks_) {
ClipBlock *c = dynamic_cast<ClipBlock*>(b);
if (c) {
clips.append(c);
}
}
if (!clips.isEmpty()) {
SpeedDurationDialog sdd(clips, timebase(), this);
sdd.exec();
}
}
void TimelineWidget::InsertGapsAt(const rational &earliest_point, const rational &insert_length, MultiUndoCommand *command)
{
for (int i=0;i<Track::kCount;i++) {
@@ -95,6 +95,8 @@ public:
void NudgeRight();
void ShowSpeedDurationDialogForSelectedClips();
/**
* @brief Timelines should always be connected to sequences
*/