Merge branch 'master' into transition-offsets
This commit is contained in:
@@ -259,7 +259,7 @@ QString Timecode::time_to_timecode(const rational &time, const rational &timebas
|
||||
|
||||
bool Timecode::TimebaseIsDropFrame(const rational &timebase)
|
||||
{
|
||||
return (timebase.numerator() == 1001);
|
||||
return (timebase.numerator() != 1);
|
||||
}
|
||||
|
||||
QString Timecode::TimeToString(int64_t ms)
|
||||
|
||||
@@ -28,6 +28,7 @@ add_subdirectory(preferences)
|
||||
add_subdirectory(progress)
|
||||
add_subdirectory(rendercancel)
|
||||
add_subdirectory(sequence)
|
||||
add_subdirectory(speedduration)
|
||||
add_subdirectory(task)
|
||||
add_subdirectory(text)
|
||||
|
||||
|
||||
@@ -43,9 +43,10 @@ ImageSection::ImageSection(QWidget* parent) :
|
||||
|
||||
layout->addWidget(new QLabel(tr("Frame to Export:")), row, 0);
|
||||
|
||||
frame_slider_ = new TimeSlider();
|
||||
frame_slider_ = new RationalSlider();
|
||||
frame_slider_->SetMinimum(0);
|
||||
frame_slider_->SetValue(0);
|
||||
frame_slider_->SetDisplayType(RationalSlider::kTime);
|
||||
layout->addWidget(frame_slider_, row, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <QCheckBox>
|
||||
|
||||
#include "codecsection.h"
|
||||
#include "widget/slider/timeslider.h"
|
||||
#include "widget/slider/rationalslider.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -44,12 +44,12 @@ public:
|
||||
frame_slider_->SetTimebase(r);
|
||||
}
|
||||
|
||||
int64_t GetTimestamp() const
|
||||
rational GetTime() const
|
||||
{
|
||||
return frame_slider_->GetValue();
|
||||
}
|
||||
|
||||
void SetTimestamp(int64_t t)
|
||||
void SetTime(const rational &t)
|
||||
{
|
||||
frame_slider_->SetValue(t);
|
||||
}
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
private:
|
||||
QCheckBox* image_sequence_checkbox_;
|
||||
|
||||
TimeSlider* frame_slider_;
|
||||
RationalSlider* frame_slider_;
|
||||
|
||||
private slots:
|
||||
void ImageSequenceCheckBoxToggled(bool e);
|
||||
|
||||
@@ -167,7 +167,7 @@ ExportDialog::ExportDialog(ViewerOutput *viewer_node, QWidget *parent) :
|
||||
preview_layout->addWidget(new QLabel(tr("Preview")));
|
||||
preview_viewer_ = new ViewerWidget();
|
||||
preview_viewer_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
connect(preview_viewer_, &ViewerWidget::TimeChanged, video_tab_, &ExportVideoTab::SetTimestamp);
|
||||
connect(preview_viewer_, &ViewerWidget::TimeChanged, video_tab_, &ExportVideoTab::SetTime);
|
||||
preview_layout->addWidget(preview_viewer_);
|
||||
splitter->addWidget(preview_area);
|
||||
|
||||
@@ -527,7 +527,7 @@ ExportParams ExportDialog::GenerateParams() const
|
||||
|
||||
if (ExportCodec::IsCodecAStillImage(video_tab_->GetSelectedCodec()) && !video_tab_->IsImageSequenceSet()) {
|
||||
// Exporting as image without exporting image sequence, only export one frame
|
||||
rational export_time = Timecode::timestamp_to_time(video_tab_->GetStillImageTime(), GetSelectedTimebase());
|
||||
rational export_time = video_tab_->GetStillImageTime();
|
||||
params.set_custom_range(TimeRange(export_time, export_time));
|
||||
} else if (range_combobox_->currentIndex() == kRangeInToOut) {
|
||||
// Assume if this combobox is enabled, workarea is enabled - a check that we make in this dialog's constructor
|
||||
|
||||
@@ -252,12 +252,12 @@ void ExportVideoTab::VideoCodecChanged()
|
||||
qDebug() << "Set default pix fmt" << pix_fmt_;
|
||||
}
|
||||
|
||||
void ExportVideoTab::SetTimestamp(int64_t timestamp)
|
||||
void ExportVideoTab::SetTime(const rational &time)
|
||||
{
|
||||
for (int i=0; i<codec_stack_->count(); i++) {
|
||||
ImageSection* img = dynamic_cast<ImageSection*>(codec_stack_->widget(i));
|
||||
if (img) {
|
||||
img->SetTimestamp(timestamp);
|
||||
img->SetTime(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,9 +45,9 @@ public:
|
||||
|
||||
bool IsImageSequenceSet() const;
|
||||
|
||||
int64_t GetStillImageTime() const
|
||||
rational GetStillImageTime() const
|
||||
{
|
||||
return image_section_->GetTimestamp();
|
||||
return image_section_->GetTime();
|
||||
}
|
||||
|
||||
ExportCodec::Codec GetSelectedCodec() const
|
||||
@@ -138,7 +138,7 @@ public:
|
||||
public slots:
|
||||
void VideoCodecChanged();
|
||||
|
||||
void SetTimestamp(int64_t timestamp);
|
||||
void SetTime(const rational &time);
|
||||
|
||||
signals:
|
||||
void ColorSpaceChanged(const QString& colorspace);
|
||||
|
||||
@@ -43,7 +43,8 @@ KeyframePropertiesDialog::KeyframePropertiesDialog(const QVector<NodeKeyframe*>
|
||||
|
||||
layout->addWidget(new QLabel("Time:"), row, 0);
|
||||
|
||||
time_slider_ = new TimeSlider();
|
||||
time_slider_ = new RationalSlider();
|
||||
time_slider_->SetDisplayType(RationalSlider::kTime);
|
||||
time_slider_->SetTimebase(timebase_);
|
||||
layout->addWidget(time_slider_, row, 1);
|
||||
|
||||
@@ -146,7 +147,7 @@ KeyframePropertiesDialog::KeyframePropertiesDialog(const QVector<NodeKeyframe*>
|
||||
}
|
||||
|
||||
if (all_same_time) {
|
||||
time_slider_->SetValue(Timecode::time_to_timestamp(keys_.first()->time(), timebase_));
|
||||
time_slider_->SetValue(keys_.first()->time());
|
||||
} else {
|
||||
time_slider_->SetTristate();
|
||||
}
|
||||
@@ -196,7 +197,7 @@ void KeyframePropertiesDialog::accept()
|
||||
{
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
|
||||
rational new_time = Timecode::timestamp_to_time(time_slider_->GetValue(), timebase_);
|
||||
rational new_time = time_slider_->GetValue();
|
||||
int new_type = type_select_->currentData().toInt();
|
||||
|
||||
foreach (NodeKeyframe* key, keys_) {
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "node/keyframe.h"
|
||||
#include "widget/slider/floatslider.h"
|
||||
#include "widget/slider/timeslider.h"
|
||||
#include "widget/slider/rationalslider.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -47,7 +47,7 @@ private:
|
||||
|
||||
rational timebase_;
|
||||
|
||||
TimeSlider* time_slider_;
|
||||
RationalSlider* time_slider_;
|
||||
|
||||
QComboBox* type_select_;
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# Olive - Non-Linear Video Editor
|
||||
# Copyright (C) 2021 Olive Team
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
dialog/speedduration/speeddurationdialog.cpp
|
||||
dialog/speedduration/speeddurationdialog.h
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,205 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "speeddurationdialog.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QGridLayout>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "core.h"
|
||||
#include "widget/nodeparamview/nodeparamviewundo.h"
|
||||
#include "widget/timelinewidget/undo/timelineundopointer.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
#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);
|
||||
|
||||
speed_slider_ = new FloatSlider();
|
||||
speed_slider_->SetDisplayType(FloatSlider::kPercentage);
|
||||
connect(speed_slider_, &FloatSlider::ValueChanged, this, &SpeedDurationDialog::SpeedChanged);
|
||||
layout->addWidget(speed_slider_, row, 1);
|
||||
|
||||
row++;
|
||||
|
||||
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++;
|
||||
|
||||
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++;
|
||||
|
||||
QDialogButtonBox *btns = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
btns->setCenterButtons(true);
|
||||
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()
|
||||
{
|
||||
// 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();
|
||||
|
||||
// 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 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 NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(NodeInput(c, ClipBlock::kSpeedInput)), speed_slider_->GetValue()));
|
||||
}
|
||||
}
|
||||
|
||||
// Set duration values
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2021 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef SPEEDDURATIONDIALOG_H
|
||||
#define SPEEDDURATIONDIALOG_H
|
||||
|
||||
#include <QCheckBox>
|
||||
#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"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class SpeedDurationDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SpeedDurationDialog(const QVector<ClipBlock*> &clips, const rational &timebase, QWidget *parent = nullptr);
|
||||
|
||||
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);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SPEEDDURATIONDIALOG_H
|
||||
+1
-1
@@ -2343,7 +2343,7 @@ void NodeSetPositionAsChildCommand::redo()
|
||||
}
|
||||
}
|
||||
|
||||
sub_command_->redo();
|
||||
sub_command_->redo_now();
|
||||
}
|
||||
|
||||
void NodeSetPositionToOffsetOfAnotherNodeCommand::redo()
|
||||
|
||||
+1
-1
@@ -1406,7 +1406,7 @@ protected:
|
||||
|
||||
virtual void undo() override
|
||||
{
|
||||
sub_command_->undo();
|
||||
sub_command_->undo_now();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -168,7 +168,7 @@ void Folder::RemoveElementCommand::redo()
|
||||
}
|
||||
|
||||
if (subcommand_) {
|
||||
subcommand_->redo();
|
||||
subcommand_->redo_now();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ public:
|
||||
virtual void undo() override
|
||||
{
|
||||
if (subcommand_) {
|
||||
subcommand_->undo();
|
||||
subcommand_->undo_now();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -74,9 +74,9 @@ void TimeBasedPanel::SetTimebase(const rational &timebase)
|
||||
widget_->SetTimebase(timebase);
|
||||
}
|
||||
|
||||
void TimeBasedPanel::SetTimestamp(const int64_t ×tamp)
|
||||
void TimeBasedPanel::SetTime(const rational &time)
|
||||
{
|
||||
widget_->SetTimestamp(timestamp);
|
||||
widget_->SetTime(time);
|
||||
}
|
||||
|
||||
void TimeBasedPanel::GoToPrevCut()
|
||||
|
||||
@@ -101,10 +101,10 @@ public:
|
||||
public slots:
|
||||
void SetTimebase(const rational& timebase);
|
||||
|
||||
virtual void SetTimestamp(const int64_t& timestamp);
|
||||
void SetTime(const rational &time);
|
||||
|
||||
signals:
|
||||
void TimeChanged(const int64_t& time);
|
||||
void TimeChanged(const rational& time);
|
||||
|
||||
void TimebaseChanged(const rational& timebase);
|
||||
|
||||
|
||||
@@ -174,6 +174,16 @@ void TimelinePanel::NudgeRight()
|
||||
timeline_widget()->NudgeRight();
|
||||
}
|
||||
|
||||
void TimelinePanel::MoveInToPlayhead()
|
||||
{
|
||||
timeline_widget()->MoveInToPlayhead();
|
||||
}
|
||||
|
||||
void TimelinePanel::MoveOutToPlayhead()
|
||||
{
|
||||
timeline_widget()->MoveOutToPlayhead();
|
||||
}
|
||||
|
||||
void TimelinePanel::InsertFootageAtPlayhead(const QVector<ViewerOutput *> &footage)
|
||||
{
|
||||
timeline_widget()->InsertFootageAtPlayhead(footage);
|
||||
|
||||
@@ -92,13 +92,22 @@ public:
|
||||
|
||||
virtual void NudgeRight() override;
|
||||
|
||||
virtual void MoveInToPlayhead() override;
|
||||
|
||||
virtual void MoveOutToPlayhead() override;
|
||||
|
||||
void ShowSpeedDurationDialogForSelectedClips()
|
||||
{
|
||||
timeline_widget()->ShowSpeedDurationDialogForSelectedClips();
|
||||
}
|
||||
|
||||
void InsertFootageAtPlayhead(const QVector<ViewerOutput *> &footage);
|
||||
|
||||
void OverwriteFootageAtPlayhead(const QVector<ViewerOutput *> &footage);
|
||||
|
||||
const QVector<Block*>& GetSelectedBlocks() const
|
||||
{
|
||||
return static_cast<TimelineWidget*>(GetTimeBasedWidget())->GetSelectedBlocks();
|
||||
return timeline_widget()->GetSelectedBlocks();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@@ -82,9 +82,6 @@ class MultiUndoCommand : public UndoCommand
|
||||
public:
|
||||
MultiUndoCommand();
|
||||
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
virtual Project* GetRelevantProject() const override
|
||||
{
|
||||
return nullptr;
|
||||
@@ -105,6 +102,10 @@ public:
|
||||
return children_[i];
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
std::vector<UndoCommand*> children_;
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ CurveWidget::CurveWidget(QWidget *parent) :
|
||||
QHBoxLayout* top_controls = new QHBoxLayout();
|
||||
|
||||
key_control_ = new NodeParamViewKeyframeControl(false);
|
||||
connect(key_control_, &NodeParamViewKeyframeControl::RequestSetTime, this, &CurveWidget::KeyControlRequestedTimeChanged);
|
||||
connect(key_control_, &NodeParamViewKeyframeControl::RequestSetTime, this, &CurveWidget::SetTimeAndSignal);
|
||||
top_controls->addWidget(key_control_);
|
||||
|
||||
top_controls->addStretch();
|
||||
@@ -156,12 +156,12 @@ void CurveWidget::SetNodes(const QVector<Node *> &nodes)
|
||||
nodes_ = nodes;
|
||||
}
|
||||
|
||||
void CurveWidget::TimeChangedEvent(const int64_t ×tamp)
|
||||
void CurveWidget::TimeChangedEvent(const rational &time)
|
||||
{
|
||||
TimeBasedWidget::TimeChangedEvent(timestamp);
|
||||
TimeBasedWidget::TimeChangedEvent(time);
|
||||
|
||||
view_->SetTime(timestamp);
|
||||
UpdateBridgeTime(timestamp);
|
||||
view_->SetTime(time);
|
||||
UpdateBridgeTime(time);
|
||||
}
|
||||
|
||||
void CurveWidget::TimebaseChangedEvent(const rational &timebase)
|
||||
@@ -211,9 +211,8 @@ void CurveWidget::SetKeyframeButtonCheckedFromType(NodeKeyframe::Type type)
|
||||
hold_button_->setChecked(type == NodeKeyframe::kHold);
|
||||
}
|
||||
|
||||
void CurveWidget::UpdateBridgeTime(const int64_t ×tamp)
|
||||
void CurveWidget::UpdateBridgeTime(const rational &time)
|
||||
{
|
||||
rational time = Timecode::timestamp_to_time(timestamp, view_->timebase());
|
||||
key_control_->SetTime(time);
|
||||
}
|
||||
|
||||
@@ -355,11 +354,6 @@ void CurveWidget::KeyframeTypeButtonTriggered(bool checked)
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
|
||||
void CurveWidget::KeyControlRequestedTimeChanged(const rational &time)
|
||||
{
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(time, view_->timebase()));
|
||||
}
|
||||
|
||||
void CurveWidget::NodeEnabledChanged(Node* n, bool e)
|
||||
{
|
||||
ConnectNode(n, e);
|
||||
|
||||
@@ -61,7 +61,7 @@ public slots:
|
||||
void SetNodes(const QVector<Node *> &nodes);
|
||||
|
||||
protected:
|
||||
virtual void TimeChangedEvent(const int64_t &) override;
|
||||
virtual void TimeChangedEvent(const rational &) override;
|
||||
virtual void TimebaseChangedEvent(const rational &) override;
|
||||
virtual void ScaleChangedEvent(const double &) override;
|
||||
|
||||
@@ -76,7 +76,7 @@ private:
|
||||
|
||||
void SetKeyframeButtonCheckedFromType(NodeKeyframe::Type type);
|
||||
|
||||
void UpdateBridgeTime(const int64_t& timestamp);
|
||||
void UpdateBridgeTime(const rational &time);
|
||||
|
||||
void ConnectNode(Node* node, bool connect);
|
||||
|
||||
@@ -103,8 +103,6 @@ private slots:
|
||||
|
||||
void KeyframeTypeButtonTriggered(bool checked);
|
||||
|
||||
void KeyControlRequestedTimeChanged(const rational& time);
|
||||
|
||||
void NodeEnabledChanged(Node* n, bool e);
|
||||
|
||||
void InputEnabledChanged(const NodeKeyframeTrackReference &ref, bool e);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "common/timecodefunctions.h"
|
||||
#include "panel/panelmanager.h"
|
||||
#include "panel/timeline/timeline.h"
|
||||
#include "window/mainwindow/mainwindow.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -45,6 +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, "Ctrl+R");
|
||||
|
||||
// "In/Out" menu shared items
|
||||
inout_set_in_item_ = Menu::CreateItem(this, "setinpoint", this, &MenuShared::SetInTriggered, "I");
|
||||
@@ -134,6 +136,7 @@ void MenuShared::AddItemsForEditMenu(Menu *m, bool for_clips)
|
||||
if (for_clips) {
|
||||
m->addAction(edit_ripple_delete_item_);
|
||||
m->addAction(edit_split_item_);
|
||||
m->addAction(edit_speedduration_item_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,6 +304,15 @@ void MenuShared::ColorLabelTriggered(int color_index)
|
||||
PanelManager::instance()->CurrentlyFocused()->SetColorLabel(color_index);
|
||||
}
|
||||
|
||||
void MenuShared::SpeedDurationTriggered()
|
||||
{
|
||||
TimelinePanel* timeline = PanelManager::instance()->MostRecentlyFocused<TimelinePanel>();
|
||||
|
||||
if (timeline) {
|
||||
timeline->ShowSpeedDurationDialogForSelectedClips();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuShared::Retranslate()
|
||||
{
|
||||
// "New" menu shared items
|
||||
@@ -317,6 +329,7 @@ void MenuShared::Retranslate()
|
||||
edit_delete_item_->setText(tr("Delete"));
|
||||
edit_ripple_delete_item_->setText(tr("Ripple Delete"));
|
||||
edit_split_item_->setText(tr("Split"));
|
||||
edit_speedduration_item_->setText(tr("Speed/Duration"));
|
||||
|
||||
// "In/Out" menu shared items
|
||||
inout_set_in_item_->setText(tr("Set In Point"));
|
||||
|
||||
@@ -75,6 +75,7 @@ private:
|
||||
QAction* edit_delete_item_;
|
||||
QAction* edit_ripple_delete_item_;
|
||||
QAction* edit_split_item_;
|
||||
QAction* edit_speedduration_item_;
|
||||
|
||||
// "In/Out" menu shared items
|
||||
QAction* inout_set_in_item_;
|
||||
@@ -145,6 +146,8 @@ private slots:
|
||||
|
||||
void ColorLabelTriggered(int color_index);
|
||||
|
||||
void SpeedDurationTriggered();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ NodeParamView::NodeParamView(QWidget *parent) :
|
||||
// Connect ruler and keyframe view together
|
||||
connect(ruler(), &TimeRuler::TimeChanged, keyframe_view_, &KeyframeView::SetTime);
|
||||
connect(keyframe_view_, &KeyframeView::TimeChanged, ruler(), &TimeRuler::SetTime);
|
||||
connect(keyframe_view_, &KeyframeView::TimeChanged, this, &NodeParamView::SetTimestamp);
|
||||
connect(keyframe_view_, &KeyframeView::TimeChanged, this, &NodeParamView::SetTime);
|
||||
connect(keyframe_view_, &KeyframeView::Dragged, this, &NodeParamView::KeyframeViewDragged);
|
||||
|
||||
// Connect keyframe view scaling to this
|
||||
@@ -155,7 +155,7 @@ void NodeParamView::SelectNodes(const QVector<Node *> &nodes)
|
||||
}
|
||||
|
||||
if (items_.size() > original_node_count ) {
|
||||
UpdateItemTime(GetTimestamp());
|
||||
UpdateItemTime(GetTime());
|
||||
|
||||
// Re-arrange keyframes
|
||||
QueueKeyframePositionUpdate();
|
||||
@@ -220,16 +220,16 @@ void NodeParamView::TimebaseChangedEvent(const rational &timebase)
|
||||
item->SetTimebase(timebase);
|
||||
}
|
||||
|
||||
UpdateItemTime(GetTimestamp());
|
||||
UpdateItemTime(GetTime());
|
||||
}
|
||||
|
||||
void NodeParamView::TimeChangedEvent(const int64_t ×tamp)
|
||||
void NodeParamView::TimeChangedEvent(const rational &time)
|
||||
{
|
||||
super::TimeChangedEvent(timestamp);
|
||||
super::TimeChangedEvent(time);
|
||||
|
||||
keyframe_view_->SetTime(timestamp);
|
||||
keyframe_view_->SetTime(time);
|
||||
|
||||
UpdateItemTime(timestamp);
|
||||
UpdateItemTime(time);
|
||||
}
|
||||
|
||||
void NodeParamView::ConnectedNodeChangeEvent(ViewerOutput *n)
|
||||
@@ -252,10 +252,8 @@ void NodeParamView::DeleteSelected()
|
||||
keyframe_view_->DeleteSelected();
|
||||
}
|
||||
|
||||
void NodeParamView::UpdateItemTime(const int64_t ×tamp)
|
||||
void NodeParamView::UpdateItemTime(const rational &time)
|
||||
{
|
||||
rational time = Timecode::timestamp_to_time(timestamp, timebase());
|
||||
|
||||
foreach (NodeParamViewItem* item, items_) {
|
||||
item->SetTime(time);
|
||||
}
|
||||
@@ -306,7 +304,7 @@ void NodeParamView::AddNode(Node *n)
|
||||
connect(n, &Node::KeyframeAdded, keyframe_view_, &KeyframeView::AddKeyframe);
|
||||
connect(n, &Node::KeyframeRemoved, keyframe_view_, &KeyframeView::RemoveKeyframe);
|
||||
|
||||
connect(item, &NodeParamViewItem::RequestSetTime, this, &NodeParamView::ItemRequestedTimeChanged);
|
||||
connect(item, &NodeParamViewItem::RequestSetTime, this, &NodeParamView::SetTimeAndSignal);
|
||||
connect(item, &NodeParamViewItem::RequestSelectNode, this, &NodeParamView::RequestSelectNode);
|
||||
connect(item, &NodeParamViewItem::dockLocationChanged, this, &NodeParamView::QueueKeyframePositionUpdate);
|
||||
connect(item, &NodeParamViewItem::dockLocationChanged, this, &NodeParamView::SignalNodeOrder);
|
||||
@@ -358,11 +356,6 @@ void NodeParamView::RemoveNode(Node *n)
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamView::ItemRequestedTimeChanged(const rational &time)
|
||||
{
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(time, keyframe_view_->timebase()));
|
||||
}
|
||||
|
||||
void NodeParamView::UpdateGlobalScrollBar()
|
||||
{
|
||||
int height_offscreen = param_widget_container_->height() - ruler()->height() + scrollbar()->height();
|
||||
|
||||
@@ -94,12 +94,12 @@ protected:
|
||||
|
||||
virtual void ScaleChangedEvent(const double &) override;
|
||||
virtual void TimebaseChangedEvent(const rational&) override;
|
||||
virtual void TimeChangedEvent(const int64_t &) override;
|
||||
virtual void TimeChangedEvent(const rational &time) override;
|
||||
|
||||
virtual void ConnectedNodeChangeEvent(ViewerOutput* n) override;
|
||||
|
||||
private:
|
||||
void UpdateItemTime(const int64_t ×tamp);
|
||||
void UpdateItemTime(const rational &time);
|
||||
|
||||
void QueueKeyframePositionUpdate();
|
||||
|
||||
@@ -132,8 +132,6 @@ private:
|
||||
Node* focused_node_;
|
||||
|
||||
private slots:
|
||||
void ItemRequestedTimeChanged(const rational& time);
|
||||
|
||||
void UpdateGlobalScrollBar();
|
||||
|
||||
void PinNode(bool pin);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -42,17 +42,12 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void TimeChangedEvent(const int64_t&) override
|
||||
virtual void TimeChangedEvent(const rational &time) override
|
||||
{
|
||||
UpdateView();
|
||||
view_->SetTime(time);
|
||||
}
|
||||
|
||||
private:
|
||||
void UpdateView()
|
||||
{
|
||||
view_->SetTime(GetTime());
|
||||
}
|
||||
|
||||
NodeTableView* view_;
|
||||
|
||||
};
|
||||
|
||||
@@ -431,7 +431,7 @@ void NodeView::keyPressEvent(QKeyEvent *event)
|
||||
|
||||
// We undo the last action which SHOULD be adding the node
|
||||
if (paste_command_) {
|
||||
paste_command_->undo();
|
||||
paste_command_->undo_now();
|
||||
delete paste_command_;
|
||||
paste_command_ = nullptr;
|
||||
}
|
||||
@@ -757,7 +757,7 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event)
|
||||
}
|
||||
}
|
||||
if (set_pos_command->child_count()) {
|
||||
set_pos_command->redo();
|
||||
set_pos_command->redo_now();
|
||||
command->add_child(set_pos_command);
|
||||
} else {
|
||||
delete set_pos_command;
|
||||
@@ -784,7 +784,7 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event)
|
||||
drop_edge_ = nullptr;
|
||||
}
|
||||
if (drop_edge_command->child_count()) {
|
||||
drop_edge_command->redo();
|
||||
drop_edge_command->redo_now();
|
||||
command->add_child(drop_edge_command);
|
||||
} else {
|
||||
delete drop_edge_command;
|
||||
@@ -822,7 +822,7 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event)
|
||||
}
|
||||
|
||||
if (remove_pos_command->child_count()) {
|
||||
remove_pos_command->redo();
|
||||
remove_pos_command->redo_now();
|
||||
command->add_child(remove_pos_command);
|
||||
} else {
|
||||
delete remove_pos_command;
|
||||
@@ -988,7 +988,7 @@ void NodeView::CreateNodeSlot(QAction *action)
|
||||
paste_command_->add_child(new NodeSetPositionCommand(new_node, context, QPointF(0, 0), false));
|
||||
}
|
||||
paste_command_->add_child(new NodeViewAttachNodesToCursor(this, {new_node}));
|
||||
paste_command_->redo();
|
||||
paste_command_->redo_now();
|
||||
|
||||
this->setFocus();
|
||||
}
|
||||
@@ -1673,7 +1673,7 @@ void NodeView::PasteNodesInternal(const QVector<Node *> &duplicate_nodes)
|
||||
// Attach nodes to cursor
|
||||
paste_command_->add_child(new NodeViewAttachNodesToCursor(this, new_nodes));
|
||||
|
||||
paste_command_->redo();
|
||||
paste_command_->redo_now();
|
||||
}
|
||||
|
||||
NodeView::NodeViewAttachNodesToCursor::NodeViewAttachNodesToCursor(NodeView *view, const QVector<Node *> &nodes) :
|
||||
|
||||
@@ -117,7 +117,7 @@ protected:
|
||||
|
||||
virtual void redo() override
|
||||
{
|
||||
command_->redo();
|
||||
command_->redo_now();
|
||||
|
||||
graph_ = node_->parent();
|
||||
node_->setParent(&memory_manager_);
|
||||
@@ -128,7 +128,7 @@ protected:
|
||||
node_->setParent(graph_);
|
||||
graph_ = nullptr;
|
||||
|
||||
command_->undo();
|
||||
command_->undo_now();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -179,12 +179,12 @@ protected:
|
||||
|
||||
virtual void redo() override
|
||||
{
|
||||
command_->redo();
|
||||
command_->redo_now();
|
||||
}
|
||||
|
||||
virtual void undo() override
|
||||
{
|
||||
command_->undo();
|
||||
command_->undo_now();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -174,6 +174,10 @@ public:
|
||||
|
||||
virtual void NudgeRight(){}
|
||||
|
||||
virtual void MoveInToPlayhead(){}
|
||||
|
||||
virtual void MoveOutToPlayhead(){}
|
||||
|
||||
signals:
|
||||
void CloseRequested();
|
||||
|
||||
|
||||
@@ -53,8 +53,9 @@ PlaybackControls::PlaybackControls(QWidget *parent) :
|
||||
lower_left_layout->setSpacing(0);
|
||||
lower_left_layout->setMargin(0);
|
||||
|
||||
cur_tc_lbl_ = new TimeSlider();
|
||||
connect(cur_tc_lbl_, &TimeSlider::ValueChanged, this, &PlaybackControls::TimeChanged);
|
||||
cur_tc_lbl_ = new RationalSlider();
|
||||
cur_tc_lbl_->SetDisplayType(RationalSlider::kTime);
|
||||
connect(cur_tc_lbl_, &RationalSlider::ValueChanged, this, &PlaybackControls::TimeChanged);
|
||||
lower_left_layout->addWidget(cur_tc_lbl_);
|
||||
lower_left_layout->addStretch();
|
||||
|
||||
@@ -179,12 +180,12 @@ void PlaybackControls::SetAudioVideoDragButtonsVisible(bool e)
|
||||
audio_drag_btn_->setVisible(e);
|
||||
}
|
||||
|
||||
void PlaybackControls::SetTime(const int64_t &r)
|
||||
void PlaybackControls::SetTime(const rational &r)
|
||||
{
|
||||
cur_tc_lbl_->SetValue(r);
|
||||
}
|
||||
|
||||
void PlaybackControls::SetEndTime(const int64_t &r)
|
||||
void PlaybackControls::SetEndTime(const rational &r)
|
||||
{
|
||||
if (time_base_.isNull()) {
|
||||
return;
|
||||
@@ -192,7 +193,7 @@ void PlaybackControls::SetEndTime(const int64_t &r)
|
||||
|
||||
end_time_ = r;
|
||||
|
||||
end_tc_lbl_->setText(Timecode::timestamp_to_timecode(end_time_,
|
||||
end_tc_lbl_->setText(Timecode::time_to_timecode(end_time_,
|
||||
time_base_,
|
||||
Core::instance()->GetTimecodeDisplay()));
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "common/rational.h"
|
||||
#include "dragbutton.h"
|
||||
#include "widget/slider/timeslider.h"
|
||||
#include "widget/slider/rationalslider.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -53,9 +53,9 @@ public:
|
||||
void SetAudioVideoDragButtonsVisible(bool e);
|
||||
|
||||
public slots:
|
||||
void SetTime(const int64_t &r);
|
||||
void SetTime(const rational &r);
|
||||
|
||||
void SetEndTime(const int64_t &r);
|
||||
void SetEndTime(const rational &r);
|
||||
|
||||
void ShowPauseButton();
|
||||
|
||||
@@ -100,7 +100,7 @@ signals:
|
||||
|
||||
void VideoPressed();
|
||||
|
||||
void TimeChanged(const int64_t& t);
|
||||
void TimeChanged(const rational& t);
|
||||
|
||||
protected:
|
||||
virtual void changeEvent(QEvent *) override;
|
||||
@@ -111,10 +111,10 @@ private:
|
||||
QWidget* lower_left_container_;
|
||||
QWidget* lower_right_container_;
|
||||
|
||||
TimeSlider* cur_tc_lbl_;
|
||||
RationalSlider* cur_tc_lbl_;
|
||||
QLabel* end_tc_lbl_;
|
||||
|
||||
int64_t end_time_;
|
||||
rational end_time_;
|
||||
|
||||
rational time_base_;
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ const double TimeBasedView::kMaximumScale = 8192;
|
||||
|
||||
TimeBasedView::TimeBasedView(QWidget *parent) :
|
||||
HandMovableView(parent),
|
||||
playhead_(0),
|
||||
playhead_scene_left_(-1),
|
||||
playhead_scene_right_(-1),
|
||||
dragging_playhead_(false),
|
||||
@@ -150,7 +149,7 @@ void TimeBasedView::SetYScale(const double &y_scale)
|
||||
}
|
||||
}
|
||||
|
||||
void TimeBasedView::SetTime(const int64_t time)
|
||||
void TimeBasedView::SetTime(const rational &time)
|
||||
{
|
||||
playhead_ = time;
|
||||
|
||||
@@ -194,11 +193,6 @@ void TimeBasedView::drawForeground(QPainter *painter, const QRectF &rect)
|
||||
}
|
||||
}
|
||||
|
||||
rational TimeBasedView::GetPlayheadTime() const
|
||||
{
|
||||
return Timecode::timestamp_to_time(playhead_, timebase());
|
||||
}
|
||||
|
||||
bool TimeBasedView::PlayheadPress(QMouseEvent *event)
|
||||
{
|
||||
QPointF scene_pos = mapToScene(event->pos());
|
||||
@@ -217,23 +211,16 @@ bool TimeBasedView::PlayheadMove(QMouseEvent *event)
|
||||
}
|
||||
|
||||
QPointF scene_pos = mapToScene(event->pos());
|
||||
rational mouse_time = SceneToTime(scene_pos.x());
|
||||
|
||||
int64_t target_ts = qMax(static_cast<int64_t>(0), Timecode::time_to_timestamp(mouse_time, timebase()));
|
||||
rational mouse_time = qMax(rational(0), SceneToTime(scene_pos.x()));
|
||||
|
||||
if (Core::instance()->snapping() && snap_service_) {
|
||||
rational target_time = Timecode::timestamp_to_time(target_ts, timebase());
|
||||
rational movement;
|
||||
|
||||
snap_service_->SnapPoint({target_time}, &movement, SnapService::kSnapAll & ~SnapService::kSnapToPlayhead);
|
||||
|
||||
if (!movement.isNull()) {
|
||||
target_ts = Timecode::time_to_timestamp(target_time + movement, timebase());
|
||||
}
|
||||
snap_service_->SnapPoint({mouse_time}, &movement, SnapService::kSnapAll & ~SnapService::kSnapToPlayhead);
|
||||
}
|
||||
|
||||
SetTime(target_ts);
|
||||
emit TimeChanged(target_ts);
|
||||
SetTime(mouse_time);
|
||||
emit TimeChanged(mouse_time);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -255,7 +242,7 @@ bool TimeBasedView::PlayheadRelease(QMouseEvent*)
|
||||
|
||||
qreal TimeBasedView::GetPlayheadX()
|
||||
{
|
||||
return TimeToScene(Timecode::timestamp_to_time(playhead_, timebase()));
|
||||
return TimeToScene(playhead_);
|
||||
}
|
||||
|
||||
void TimeBasedView::SetEndTime(const rational &length)
|
||||
|
||||
@@ -56,12 +56,12 @@ public:
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetTime(const int64_t time);
|
||||
void SetTime(const rational &time);
|
||||
|
||||
void SetEndTime(const rational& length);
|
||||
|
||||
signals:
|
||||
void TimeChanged(const int64_t& time);
|
||||
void TimeChanged(const rational& time);
|
||||
|
||||
void ScaleChanged(double scale);
|
||||
|
||||
@@ -78,7 +78,10 @@ protected:
|
||||
|
||||
virtual void ZoomIntoCursorPosition(QWheelEvent *event, double multiplier, const QPointF &cursor_pos) override;
|
||||
|
||||
rational GetPlayheadTime() const;
|
||||
const rational &GetPlayheadTime() const
|
||||
{
|
||||
return playhead_;
|
||||
}
|
||||
|
||||
bool PlayheadPress(QMouseEvent* event);
|
||||
bool PlayheadMove(QMouseEvent* event);
|
||||
@@ -105,7 +108,7 @@ protected slots:
|
||||
private:
|
||||
qreal GetPlayheadX();
|
||||
|
||||
int64_t playhead_;
|
||||
rational playhead_;
|
||||
|
||||
double playhead_scene_left_;
|
||||
double playhead_scene_right_;
|
||||
|
||||
@@ -57,12 +57,7 @@ void TimeBasedWidget::SetScaleAndCenterOnPlayhead(const double &scale)
|
||||
QTimer::singleShot(0, this, &TimeBasedWidget::CenterScrollOnPlayhead);
|
||||
}
|
||||
|
||||
rational TimeBasedWidget::GetTime() const
|
||||
{
|
||||
return Timecode::timestamp_to_time(ruler()->GetTime(), timebase());
|
||||
}
|
||||
|
||||
const int64_t &TimeBasedWidget::GetTimestamp() const
|
||||
const rational &TimeBasedWidget::GetTime() const
|
||||
{
|
||||
return ruler_->GetTime();
|
||||
}
|
||||
@@ -273,8 +268,7 @@ void TimeBasedWidget::resizeEvent(QResizeEvent *event)
|
||||
void TimeBasedWidget::ConnectTimelineView(TimeBasedView *base, bool connect_time_change_event)
|
||||
{
|
||||
if (connect_time_change_event) {
|
||||
connect(base, &TimeBasedView::TimeChanged, this, &TimeBasedWidget::SetTimestamp);
|
||||
connect(base, &TimeBasedView::TimeChanged, this, &TimeBasedWidget::TimeChanged);
|
||||
connect(base, &TimeBasedView::TimeChanged, this, &TimeBasedWidget::SetTimeAndSignal);
|
||||
}
|
||||
|
||||
timeline_views_.append(base);
|
||||
@@ -286,7 +280,7 @@ void TimeBasedWidget::PassWheelEventsToScrollBar(QObject *object)
|
||||
object->installEventFilter(this);
|
||||
}
|
||||
|
||||
void TimeBasedWidget::SetTimestamp(int64_t timestamp)
|
||||
void TimeBasedWidget::SetTime(const rational &time)
|
||||
{
|
||||
if (UserIsDraggingPlayhead()) {
|
||||
// If the user is dragging the playhead, we will simply nudge over and not use autoscroll rules.
|
||||
@@ -306,9 +300,9 @@ void TimeBasedWidget::SetTimestamp(int64_t timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
ruler_->SetTime(timestamp);
|
||||
ruler_->SetTime(time);
|
||||
|
||||
TimeChangedEvent(timestamp);
|
||||
TimeChangedEvent(time);
|
||||
}
|
||||
|
||||
void TimeBasedWidget::SetTimebase(const rational &timebase)
|
||||
@@ -341,20 +335,18 @@ void TimeBasedWidget::GoToPrevCut()
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetTimestamp() == 0) {
|
||||
if (GetTime().isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t closest_cut = 0;
|
||||
rational closest_cut = 0;
|
||||
|
||||
foreach (Track* track, sequence->GetTracks()) {
|
||||
int64_t this_track_closest_cut = 0;
|
||||
rational this_track_closest_cut = 0;
|
||||
|
||||
foreach (Block* block, track->Blocks()) {
|
||||
int64_t block_out_ts = Timecode::time_to_timestamp(block->out(), timebase());
|
||||
|
||||
if (block_out_ts < GetTimestamp()) {
|
||||
this_track_closest_cut = block_out_ts;
|
||||
if (block->out() < GetTime()) {
|
||||
this_track_closest_cut = block->out();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@@ -375,20 +367,18 @@ void TimeBasedWidget::GoToNextCut()
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t closest_cut = INT64_MAX;
|
||||
rational closest_cut = RATIONAL_MAX;
|
||||
|
||||
foreach (Track* track, sequence->GetTracks()) {
|
||||
int64_t this_track_closest_cut = Timecode::time_to_timestamp(track->track_length(), timebase());
|
||||
rational this_track_closest_cut = track->track_length();
|
||||
|
||||
if (this_track_closest_cut <= GetTimestamp()) {
|
||||
this_track_closest_cut = INT64_MAX;
|
||||
if (this_track_closest_cut <= GetTime()) {
|
||||
this_track_closest_cut = RATIONAL_MAX;
|
||||
}
|
||||
|
||||
foreach (Block* block, track->Blocks()) {
|
||||
int64_t block_in_ts = Timecode::time_to_timestamp(block->in(), timebase());
|
||||
|
||||
if (block_in_ts > GetTimestamp()) {
|
||||
this_track_closest_cut = block_in_ts;
|
||||
if (block->in() > GetTime()) {
|
||||
this_track_closest_cut = block->in();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -396,7 +386,7 @@ void TimeBasedWidget::GoToNextCut()
|
||||
closest_cut = qMin(closest_cut, this_track_closest_cut);
|
||||
}
|
||||
|
||||
if (closest_cut < INT64_MAX) {
|
||||
if (closest_cut < RATIONAL_MAX) {
|
||||
SetTimeAndSignal(closest_cut);
|
||||
}
|
||||
}
|
||||
@@ -411,33 +401,43 @@ void TimeBasedWidget::GoToStart()
|
||||
void TimeBasedWidget::PrevFrame()
|
||||
{
|
||||
if (viewer_node_) {
|
||||
SetTimeAndSignal(qMax(static_cast<int64_t>(0), ruler()->GetTime() - 1));
|
||||
rational proposed_time = Timecode::snap_time_to_timebase(GetTime() - timebase(), timebase(), Timecode::kCeil);
|
||||
if (proposed_time == GetTime()) {
|
||||
// Catch rounding error, assume this time is snapped and just subtract a timebase
|
||||
proposed_time -= timebase();
|
||||
}
|
||||
SetTimeAndSignal(qMax(rational(0), proposed_time));
|
||||
}
|
||||
}
|
||||
|
||||
void TimeBasedWidget::NextFrame()
|
||||
{
|
||||
if (viewer_node_) {
|
||||
SetTimeAndSignal(ruler()->GetTime() + 1);
|
||||
rational proposed_time = Timecode::snap_time_to_timebase(GetTime() + timebase(), timebase(), Timecode::kFloor);
|
||||
if (proposed_time == GetTime()) {
|
||||
// Catch rounding error, assume this time is snapped and just add a timebase
|
||||
proposed_time += timebase();
|
||||
}
|
||||
SetTimeAndSignal(proposed_time);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeBasedWidget::GoToEnd()
|
||||
{
|
||||
if (viewer_node_) {
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(viewer_node_->GetLength(), timebase()));
|
||||
SetTimeAndSignal(viewer_node_->GetLength());
|
||||
}
|
||||
}
|
||||
|
||||
void TimeBasedWidget::SetTimeAndSignal(const int64_t &t)
|
||||
void TimeBasedWidget::SetTimeAndSignal(const rational &t)
|
||||
{
|
||||
SetTimestamp(t);
|
||||
SetTime(t);
|
||||
emit TimeChanged(t);
|
||||
}
|
||||
|
||||
void TimeBasedWidget::CenterScrollOnPlayhead()
|
||||
{
|
||||
scrollbar_->setValue(qRound(TimeToScene(Timecode::timestamp_to_time(ruler_->GetTime(), timebase()))) - scrollbar_->width()/2);
|
||||
scrollbar_->setValue(qRound(TimeToScene(ruler_->GetTime())) - scrollbar_->width()/2);
|
||||
}
|
||||
|
||||
void TimeBasedWidget::SetAutoSetTimebase(bool e)
|
||||
@@ -639,7 +639,7 @@ void TimeBasedWidget::GoToIn()
|
||||
{
|
||||
if (GetConnectedNode()) {
|
||||
if (GetConnectedNode()->GetTimelinePoints()->workarea()->enabled()) {
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(GetConnectedNode()->GetTimelinePoints()->workarea()->in(), timebase()));
|
||||
SetTimeAndSignal(GetConnectedNode()->GetTimelinePoints()->workarea()->in());
|
||||
} else {
|
||||
GoToStart();
|
||||
}
|
||||
@@ -650,7 +650,7 @@ void TimeBasedWidget::GoToOut()
|
||||
{
|
||||
if (GetConnectedNode()) {
|
||||
if (GetConnectedNode()->GetTimelinePoints()->workarea()->enabled()) {
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(GetConnectedNode()->GetTimelinePoints()->workarea()->out(), timebase()));
|
||||
SetTimeAndSignal(GetConnectedNode()->GetTimelinePoints()->workarea()->out());
|
||||
} else {
|
||||
GoToEnd();
|
||||
}
|
||||
|
||||
@@ -38,9 +38,7 @@ class TimeBasedWidget : public TimelineScaledWidget
|
||||
public:
|
||||
TimeBasedWidget(bool ruler_text_visible = true, bool ruler_cache_status_visible = false, QWidget* parent = nullptr);
|
||||
|
||||
rational GetTime() const;
|
||||
|
||||
const int64_t& GetTimestamp() const;
|
||||
const rational &GetTime() const;
|
||||
|
||||
void ZoomIn();
|
||||
|
||||
@@ -57,7 +55,7 @@ public:
|
||||
virtual bool eventFilter(QObject* object, QEvent* event) override;
|
||||
|
||||
public slots:
|
||||
void SetTimestamp(int64_t timestamp);
|
||||
void SetTime(const rational &time);
|
||||
|
||||
void SetTimebase(const rational& timebase);
|
||||
|
||||
@@ -94,14 +92,14 @@ public slots:
|
||||
void GoToOut();
|
||||
|
||||
protected slots:
|
||||
void SetTimeAndSignal(const int64_t& t);
|
||||
void SetTimeAndSignal(const rational& t);
|
||||
|
||||
protected:
|
||||
ResizableTimelineScrollBar* scrollbar() const;
|
||||
|
||||
virtual void TimebaseChangedEvent(const rational&) override;
|
||||
|
||||
virtual void TimeChangedEvent(const int64_t&){}
|
||||
virtual void TimeChangedEvent(const rational&){}
|
||||
|
||||
virtual void ScaleChangedEvent(const double &) override;
|
||||
|
||||
@@ -134,7 +132,7 @@ protected slots:
|
||||
static void PageScrollInternal(QScrollBar* bar, int maximum, int screen_position, bool whole_page_scroll);
|
||||
|
||||
signals:
|
||||
void TimeChanged(const int64_t&);
|
||||
void TimeChanged(const rational&);
|
||||
|
||||
void TimebaseChanged(const rational&);
|
||||
|
||||
|
||||
@@ -72,12 +72,12 @@ rational TimeScaledObject::SceneToTime(const double &x, const double &x_scale, c
|
||||
return rational(rounded_x_mvmt * timebase.numerator(), timebase.denominator());
|
||||
}
|
||||
|
||||
double TimeScaledObject::TimeToScene(const rational &time)
|
||||
double TimeScaledObject::TimeToScene(const rational &time) const
|
||||
{
|
||||
return time.toDouble() * scale_;
|
||||
}
|
||||
|
||||
rational TimeScaledObject::SceneToTime(const double &x, bool round)
|
||||
rational TimeScaledObject::SceneToTime(const double &x, bool round) const
|
||||
{
|
||||
return SceneToTime(x, scale_, timebase_, round);
|
||||
}
|
||||
|
||||
@@ -51,8 +51,8 @@ public:
|
||||
static double CalculateScaleFromDimensions(double viewport_sz, double content_sz);
|
||||
static double CalculatePaddingFromDimensionScale(double viewport_sz);
|
||||
|
||||
double TimeToScene(const rational& time);
|
||||
rational SceneToTime(const double &x, bool round = false);
|
||||
double TimeToScene(const rational& time) const;
|
||||
rational SceneToTime(const double &x, bool round = false) const;
|
||||
|
||||
protected:
|
||||
virtual void TimebaseChangedEvent(const rational&){}
|
||||
|
||||
@@ -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"
|
||||
@@ -70,10 +71,11 @@ TimelineWidget::TimelineWidget(QWidget *parent) :
|
||||
QHBoxLayout* ruler_and_time_layout = new QHBoxLayout();
|
||||
vert_layout->addLayout(ruler_and_time_layout);
|
||||
|
||||
timecode_label_ = new TimeSlider();
|
||||
timecode_label_ = new RationalSlider();
|
||||
timecode_label_->SetAlignment(Qt::AlignCenter);
|
||||
timecode_label_->SetDisplayType(RationalSlider::kTime);
|
||||
timecode_label_->setVisible(false);
|
||||
connect(timecode_label_, &TimeSlider::ValueChanged, this, &TimelineWidget::SetTimeAndSignal);
|
||||
connect(timecode_label_, &RationalSlider::ValueChanged, this, &TimelineWidget::SetTimeAndSignal);
|
||||
ruler_and_time_layout->addWidget(timecode_label_);
|
||||
|
||||
ruler_and_time_layout->addWidget(ruler());
|
||||
@@ -135,7 +137,7 @@ TimelineWidget::TimelineWidget(QWidget *parent) :
|
||||
|
||||
connect(view->horizontalScrollBar(), &QScrollBar::valueChanged, ruler(), &TimeRuler::SetScroll);
|
||||
connect(view, &TimelineView::ScaleChanged, this, &TimelineWidget::SetScale);
|
||||
connect(view, &TimelineView::TimeChanged, this, &TimelineWidget::ViewTimestampChanged);
|
||||
connect(view, &TimelineView::TimeChanged, this, &TimelineWidget::SetTimeAndSignal);
|
||||
connect(view, &TimelineView::customContextMenuRequested, this, &TimelineWidget::ShowContextMenu);
|
||||
connect(scrollbar(), &QScrollBar::valueChanged, view->horizontalScrollBar(), &QScrollBar::setValue);
|
||||
connect(view->horizontalScrollBar(), &QScrollBar::valueChanged, scrollbar(), &QScrollBar::setValue);
|
||||
@@ -221,13 +223,13 @@ void TimelineWidget::resizeEvent(QResizeEvent *event)
|
||||
UpdateTimecodeWidthFromSplitters(views_.first()->splitter());
|
||||
}
|
||||
|
||||
void TimelineWidget::TimeChangedEvent(const int64_t& timestamp)
|
||||
void TimelineWidget::TimeChangedEvent(const rational &time)
|
||||
{
|
||||
super::TimeChangedEvent(timestamp);
|
||||
super::TimeChangedEvent(time);
|
||||
|
||||
SetViewTimestamp(timestamp);
|
||||
SetViewTime(time);
|
||||
|
||||
timecode_label_->SetValue(timestamp);
|
||||
timecode_label_->SetValue(time);
|
||||
}
|
||||
|
||||
void TimelineWidget::ScaleChangedEvent(const double &scale)
|
||||
@@ -399,7 +401,7 @@ void TimelineWidget::SplitAtPlayhead()
|
||||
return;
|
||||
}
|
||||
|
||||
rational playhead_time = Timecode::timestamp_to_time(GetTimestamp(), timebase());
|
||||
const rational &playhead_time = GetTime();
|
||||
|
||||
QVector<Block*> selected_blocks = GetSelectedBlocks();
|
||||
|
||||
@@ -692,8 +694,7 @@ void TimelineWidget::DeleteInToOut(bool ripple)
|
||||
false));
|
||||
|
||||
if (ripple) {
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(GetConnectedNode()->GetTimelinePoints()->workarea()->in(),
|
||||
timebase()));
|
||||
SetTimeAndSignal(GetConnectedNode()->GetTimelinePoints()->workarea()->in());
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
@@ -738,6 +739,33 @@ void TimelineWidget::NudgeRight()
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::MoveInToPlayhead()
|
||||
{
|
||||
MoveToPlayheadInternal(false);
|
||||
}
|
||||
|
||||
void TimelineWidget::MoveOutToPlayhead()
|
||||
{
|
||||
MoveToPlayheadInternal(true);
|
||||
}
|
||||
|
||||
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++) {
|
||||
@@ -1057,38 +1085,15 @@ void TimelineWidget::SetUseAudioTimeUnits(bool use)
|
||||
|
||||
// Update timebases
|
||||
UpdateViewTimebases();
|
||||
|
||||
// Force update of the viewer timestamps
|
||||
SetViewTimestamp(GetTimestamp());
|
||||
}
|
||||
|
||||
void TimelineWidget::SetViewTimestamp(const int64_t &ts)
|
||||
void TimelineWidget::SetViewTime(const rational &time)
|
||||
{
|
||||
for (int i=0;i<views_.size();i++) {
|
||||
TimelineAndTrackView* view = views_.at(i);
|
||||
|
||||
if (GetConnectedNode() && use_audio_time_units_ && i == Track::kAudio) {
|
||||
view->view()->SetTime(Timecode::rescale_timestamp(ts,
|
||||
timebase(),
|
||||
GetConnectedNode()->GetAudioParams().sample_rate_as_time_base()));
|
||||
} else {
|
||||
view->view()->SetTime(ts);
|
||||
view->view()->SetTime(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::ViewTimestampChanged(int64_t ts)
|
||||
{
|
||||
if (GetConnectedNode() && use_audio_time_units_ && sender() == views_.at(Track::kAudio)) {
|
||||
ts = Timecode::rescale_timestamp(ts,
|
||||
GetConnectedNode()->GetAudioParams().sample_rate_as_time_base(),
|
||||
timebase());
|
||||
}
|
||||
|
||||
// Update all other views
|
||||
SetTimestamp(ts);
|
||||
emit TimeChanged(ts);
|
||||
}
|
||||
|
||||
void TimelineWidget::ToolChanged()
|
||||
{
|
||||
@@ -1161,6 +1166,7 @@ void TimelineWidget::UpdateViewTimebases()
|
||||
|
||||
void TimelineWidget::NudgeInternal(const rational &amount)
|
||||
{
|
||||
if (!selected_blocks_.isEmpty()) {
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
foreach (Block* b, selected_blocks_) {
|
||||
@@ -1173,7 +1179,60 @@ void TimelineWidget::NudgeInternal(const rational &amount)
|
||||
new_sel.ShiftTime(amount);
|
||||
command->add_child(new TimelineWidget::SetSelectionsCommand(this, new_sel, GetSelections(), true));
|
||||
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::MoveToPlayheadInternal(bool out)
|
||||
{
|
||||
if (GetConnectedNode() && !selected_blocks_.isEmpty()) {
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
// Remove each block from the graph
|
||||
QHash<Track*, rational> earliest_pts;
|
||||
foreach (Block *b, selected_blocks_) {
|
||||
command->add_child(new TrackReplaceBlockWithGapCommand(b->track(), b, false));
|
||||
|
||||
rational r = earliest_pts.value(b->track(), out ? RATIONAL_MIN : RATIONAL_MAX);
|
||||
rational compare = out ? b->out() : b->in();
|
||||
if ((compare < r) == !out) {
|
||||
earliest_pts.insert(b->track(), compare);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Block *b, selected_blocks_) {
|
||||
rational shift_amt = GetTime() - earliest_pts.value(b->track());
|
||||
rational new_in = b->in() + shift_amt;
|
||||
bool can_shift = true;
|
||||
|
||||
if (new_in < 0) {
|
||||
// Handle clips threatening to go below 0
|
||||
rational new_out = new_in + b->length();
|
||||
if (new_out <= 0) {
|
||||
can_shift = false;
|
||||
} else {
|
||||
command->add_child(new BlockResizeWithMediaInCommand(b, new_out));
|
||||
new_in = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_shift) {
|
||||
command->add_child(new TrackPlaceBlockCommand(sequence()->track_list(b->track()->type()), b->track()->Index(), b, new_in));
|
||||
}
|
||||
}
|
||||
|
||||
// Shift selections
|
||||
TimelineWidgetSelections new_sel = GetSelections();
|
||||
for (auto it=new_sel.begin(); it!=new_sel.end(); it++) {
|
||||
rational track_adj = GetTime() - earliest_pts.value(GetTrackFromReference(it.key()), GetTime());
|
||||
if (!track_adj.isNull()) {
|
||||
it.value().shift(track_adj);
|
||||
}
|
||||
}
|
||||
command->add_child(new SetSelectionsCommand(this, new_sel, GetSelections(), true));
|
||||
|
||||
Core::instance()->undo_stack()->push(command);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::SetViewBeamCursor(const TimelineCoordinate &coord)
|
||||
@@ -1359,9 +1418,9 @@ void TimelineWidget::RippleTo(Timeline::MovementMode mode)
|
||||
|
||||
// If we rippled, ump to where new cut is if applicable
|
||||
if (mode == Timeline::kTrimIn) {
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(closest_point_to_playhead, timebase()));
|
||||
SetTimeAndSignal(closest_point_to_playhead);
|
||||
} else if (mode == Timeline::kTrimOut && closest_point_to_playhead == GetTime()) {
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(playhead_time, timebase()));
|
||||
SetTimeAndSignal(playhead_time);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1603,6 +1662,10 @@ void TimelineWidget::RemoveSelection(Block *item)
|
||||
|
||||
void TimelineWidget::SetSelections(const TimelineWidgetSelections &s, bool process_block_changes)
|
||||
{
|
||||
if (selections_ == s) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (process_block_changes) {
|
||||
SignalDeselectedBlocks(GetBlocksInSelection(selections_.Subtracted(s)));
|
||||
SignalSelectedBlocks(GetBlocksInSelection(s.Subtracted(selections_)));
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "node/output/viewer/viewer.h"
|
||||
#include "timeline/timelinecommon.h"
|
||||
#include "timelineandtrackview.h"
|
||||
#include "widget/slider/timeslider.h"
|
||||
#include "widget/slider/rationalslider.h"
|
||||
#include "widget/snapservice/snapservice.h"
|
||||
#include "widget/timebased/timebasedwidget.h"
|
||||
#include "widget/timelinewidget/timelinewidgetselections.h"
|
||||
@@ -95,6 +95,12 @@ public:
|
||||
|
||||
void NudgeRight();
|
||||
|
||||
void MoveInToPlayhead();
|
||||
|
||||
void MoveOutToPlayhead();
|
||||
|
||||
void ShowSpeedDurationDialogForSelectedClips();
|
||||
|
||||
/**
|
||||
* @brief Timelines should always be connected to sequences
|
||||
*/
|
||||
@@ -248,7 +254,7 @@ protected:
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
virtual void TimebaseChangedEvent(const rational &) override;
|
||||
virtual void TimeChangedEvent(const int64_t &) override;
|
||||
virtual void TimeChangedEvent(const rational &time) override;
|
||||
virtual void ScaleChangedEvent(const double &) override;
|
||||
|
||||
virtual void ConnectNodeEvent(ViewerOutput* n) override;
|
||||
@@ -299,7 +305,7 @@ private:
|
||||
|
||||
QVector<TimelineAndTrackView*> views_;
|
||||
|
||||
TimeSlider* timecode_label_;
|
||||
RationalSlider* timecode_label_;
|
||||
|
||||
QVector<Block*> selected_blocks_;
|
||||
|
||||
@@ -317,6 +323,8 @@ private:
|
||||
|
||||
void NudgeInternal(const rational &amount);
|
||||
|
||||
void MoveToPlayheadInternal(bool out);
|
||||
|
||||
private slots:
|
||||
void ViewMousePressed(TimelineViewMouseEvent* event);
|
||||
void ViewMouseMoved(TimelineViewMouseEvent* event);
|
||||
@@ -349,9 +357,7 @@ private slots:
|
||||
|
||||
void SetUseAudioTimeUnits(bool use);
|
||||
|
||||
void SetViewTimestamp(const int64_t& ts);
|
||||
|
||||
void ViewTimestampChanged(int64_t ts);
|
||||
void SetViewTime(const rational &time);
|
||||
|
||||
void ToolChanged();
|
||||
|
||||
|
||||
@@ -131,8 +131,7 @@ void ImportTool::DragMove(TimelineViewMouseEvent *event)
|
||||
|
||||
// Generate tooltip (showing earliest in point of imported clip)
|
||||
rational tooltip_timebase = parent()->GetTimebaseForTrackType(event->GetTrack().type());
|
||||
int64_t earliest_timestamp = Timecode::time_to_timestamp(earliest_ghost, tooltip_timebase);
|
||||
QString tooltip_text = Timecode::timestamp_to_timecode(earliest_timestamp,
|
||||
QString tooltip_text = Timecode::time_to_timecode(earliest_ghost,
|
||||
tooltip_timebase,
|
||||
Core::instance()->GetTimecodeDisplay());
|
||||
|
||||
|
||||
@@ -504,7 +504,7 @@ void PointerTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
|
||||
rational tooltip_timebase = parent()->GetTimebaseForTrackType(drag_start_.GetTrack().type());
|
||||
QToolTip::hideText();
|
||||
QToolTip::showText(QCursor::pos(),
|
||||
Timecode::timestamp_to_timecode(Timecode::time_to_timestamp(time_movement, tooltip_timebase),
|
||||
Timecode::time_to_timecode(time_movement,
|
||||
tooltip_timebase,
|
||||
Core::instance()->GetTimecodeDisplay(),
|
||||
true),
|
||||
|
||||
@@ -58,7 +58,7 @@ void SlipTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
|
||||
rational tooltip_timebase = parent()->GetTimebaseForTrackType(drag_start_.GetTrack().type());
|
||||
QToolTip::hideText();
|
||||
QToolTip::showText(QCursor::pos(),
|
||||
Timecode::timestamp_to_timecode(Timecode::time_to_timestamp(time_movement, tooltip_timebase),
|
||||
Timecode::time_to_timecode(time_movement,
|
||||
tooltip_timebase,
|
||||
Core::instance()->GetTimecodeDisplay(),
|
||||
true),
|
||||
|
||||
@@ -172,12 +172,12 @@ void TimelineAddTrackCommand::redo()
|
||||
position_command_->add_child(new NodeSetPositionAsChildCommand(track_, merge_, timeline_->parent(), 1, 2, true));
|
||||
}
|
||||
}
|
||||
position_command_->redo();
|
||||
position_command_->redo_now();
|
||||
}
|
||||
|
||||
void TimelineAddTrackCommand::undo()
|
||||
{
|
||||
position_command_->undo();
|
||||
position_command_->undo_now();
|
||||
|
||||
// Remove merge if applicable
|
||||
if (merge_) {
|
||||
|
||||
@@ -39,7 +39,7 @@ void BlockSplitCommand::redo()
|
||||
new_block_ = static_cast<Block*>(Node::CopyNodeInGraph(block_, reconnect_tree_command_));
|
||||
}
|
||||
|
||||
reconnect_tree_command_->redo();
|
||||
reconnect_tree_command_->redo_now();
|
||||
|
||||
// Determine our new lengths
|
||||
rational new_length = point_ - block_->in();
|
||||
@@ -97,7 +97,7 @@ void BlockSplitCommand::undo()
|
||||
track->RippleRemoveBlock(new_block());
|
||||
|
||||
// If we ran a reconnect command, disconnect now
|
||||
reconnect_tree_command_->undo();
|
||||
reconnect_tree_command_->undo_now();
|
||||
|
||||
track->EndOperation();
|
||||
}
|
||||
|
||||
@@ -664,12 +664,6 @@ Block *TimelineView::GetItemAtScenePos(const rational &time, int track_index) co
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TimelineView::UserSetTime(const int64_t &time)
|
||||
{
|
||||
SetTime(time);
|
||||
emit TimeChanged(time);
|
||||
}
|
||||
|
||||
void TimelineView::TrackListChanged()
|
||||
{
|
||||
UpdateSceneRect();
|
||||
|
||||
@@ -126,8 +126,6 @@ private:
|
||||
|
||||
int GetHeightOfAllTracks() const;
|
||||
|
||||
void UserSetTime(const int64_t& time);
|
||||
|
||||
void UpdatePlayheadRect();
|
||||
|
||||
QHash<Track::Reference, TimeRangeList>* selections_;
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace olive {
|
||||
|
||||
SeekableWidget::SeekableWidget(QWidget* parent) :
|
||||
TimelineScaledWidget(parent),
|
||||
time_(0),
|
||||
timeline_points_(nullptr),
|
||||
scroll_(0),
|
||||
snap_service_(nullptr),
|
||||
@@ -73,11 +72,6 @@ void SeekableWidget::SetSnapService(SnapService *service)
|
||||
snap_service_ = service;
|
||||
}
|
||||
|
||||
const int64_t &SeekableWidget::GetTime() const
|
||||
{
|
||||
return time_;
|
||||
}
|
||||
|
||||
const int &SeekableWidget::GetScroll() const
|
||||
{
|
||||
return scroll_;
|
||||
@@ -119,7 +113,7 @@ TimelinePoints *SeekableWidget::timeline_points() const
|
||||
return timeline_points_;
|
||||
}
|
||||
|
||||
void SeekableWidget::SetTime(const int64_t &r)
|
||||
void SeekableWidget::SetTime(const rational &r)
|
||||
{
|
||||
time_ = r;
|
||||
|
||||
@@ -133,29 +127,14 @@ void SeekableWidget::SetScroll(int s)
|
||||
update();
|
||||
}
|
||||
|
||||
double SeekableWidget::ScreenToUnitFloat(int screen) const
|
||||
{
|
||||
return (screen + scroll_) / GetScale() / timebase_dbl();
|
||||
}
|
||||
|
||||
int64_t SeekableWidget::ScreenToUnit(int screen) const
|
||||
{
|
||||
return qFloor(ScreenToUnitFloat(screen));
|
||||
}
|
||||
|
||||
int64_t SeekableWidget::ScreenToUnitRounded(int screen) const
|
||||
{
|
||||
return qRound64(ScreenToUnitFloat(screen));
|
||||
}
|
||||
|
||||
int SeekableWidget::UnitToScreen(int64_t unit) const
|
||||
{
|
||||
return qFloor(static_cast<double>(unit) * GetScale() * timebase_dbl()) - scroll_;
|
||||
}
|
||||
|
||||
int SeekableWidget::TimeToScreen(const rational &time) const
|
||||
{
|
||||
return qFloor(time.toDouble() * GetScale()) - scroll_;
|
||||
return qFloor(TimeToScene(time)) - scroll_;
|
||||
}
|
||||
|
||||
rational SeekableWidget::ScreenToTime(int x) const
|
||||
{
|
||||
return qMax(rational(0), SceneToTime(x + scroll_));
|
||||
}
|
||||
|
||||
void SeekableWidget::SeekToScreenPoint(int screen)
|
||||
@@ -164,26 +143,20 @@ void SeekableWidget::SeekToScreenPoint(int screen)
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t timestamp = qMax(static_cast<int64_t>(0), ScreenToUnitRounded(screen));
|
||||
rational playhead_time = ScreenToTime(screen);
|
||||
|
||||
if (Core::instance()->snapping() && snap_service_) {
|
||||
rational playhead_time = Timecode::timestamp_to_time(timestamp, timebase());
|
||||
rational movement;
|
||||
|
||||
snap_service_->SnapPoint({playhead_time},
|
||||
&movement,
|
||||
SnapService::kSnapAll & ~SnapService::kSnapToPlayhead);
|
||||
|
||||
if (!movement.isNull()) {
|
||||
timestamp = Timecode::time_to_timestamp(playhead_time + movement,
|
||||
timebase());
|
||||
}
|
||||
}
|
||||
|
||||
if (timestamp != GetTime()) {
|
||||
SetTime(timestamp);
|
||||
if (playhead_time != GetTime()) {
|
||||
SetTime(playhead_time);
|
||||
|
||||
emit TimeChanged(timestamp);
|
||||
emit TimeChanged(playhead_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,10 @@ class SeekableWidget : public TimelineScaledWidget
|
||||
public:
|
||||
SeekableWidget(QWidget *parent = nullptr);
|
||||
|
||||
const int64_t& GetTime() const;
|
||||
const rational& GetTime() const
|
||||
{
|
||||
return time_;
|
||||
}
|
||||
|
||||
const int& GetScroll() const;
|
||||
|
||||
@@ -48,7 +51,7 @@ public:
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetTime(const int64_t &r);
|
||||
void SetTime(const rational &r);
|
||||
|
||||
void SetScroll(int s);
|
||||
|
||||
@@ -65,14 +68,8 @@ protected:
|
||||
|
||||
TimelinePoints* timeline_points() const;
|
||||
|
||||
double ScreenToUnitFloat(int screen) const;
|
||||
|
||||
int64_t ScreenToUnit(int screen) const;
|
||||
int64_t ScreenToUnitRounded(int screen) const;
|
||||
|
||||
int UnitToScreen(int64_t unit) const;
|
||||
|
||||
int TimeToScreen(const rational& time) const;
|
||||
rational ScreenToTime(int x) const;
|
||||
|
||||
void DrawPlayhead(QPainter* p, int x, int y);
|
||||
|
||||
@@ -88,10 +85,10 @@ signals:
|
||||
/**
|
||||
* @brief Signal emitted whenever the time changes on this ruler, either by user or programmatically
|
||||
*/
|
||||
void TimeChanged(int64_t);
|
||||
void TimeChanged(const rational &time);
|
||||
|
||||
private:
|
||||
int64_t time_;
|
||||
rational time_;
|
||||
|
||||
TimelinePoints* timeline_points_;
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ void TimeRuler::paintEvent(QPaintEvent *)
|
||||
if (text_visible_) {
|
||||
QRect text_rect;
|
||||
Qt::Alignment text_align;
|
||||
QString timecode_str = Timecode::timestamp_to_timecode(ScreenToUnit(i), timebase(), Core::instance()->GetTimecodeDisplay());
|
||||
QString timecode_str = Timecode::time_to_timecode(ScreenToTime(i), timebase(), Core::instance()->GetTimecodeDisplay());
|
||||
int timecode_width = QtUtils::QFontMetricsWidth(fm, timecode_str);
|
||||
int timecode_left;
|
||||
|
||||
@@ -287,7 +287,7 @@ void TimeRuler::paintEvent(QPaintEvent *)
|
||||
}
|
||||
|
||||
// Draw the playhead if it's on screen at the moment
|
||||
int playhead_pos = UnitToScreen(GetTime());
|
||||
int playhead_pos = TimeToScreen(GetTime());
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(PLAYHEAD_COLOR);
|
||||
DrawPlayhead(&p, playhead_pos, line_bottom);
|
||||
|
||||
@@ -100,7 +100,7 @@ void AudioWaveformView::paintEvent(QPaintEvent *event)
|
||||
// Draw playhead
|
||||
p.setPen(PLAYHEAD_COLOR);
|
||||
|
||||
int playhead_x = UnitToScreen(GetTime());
|
||||
int playhead_x = TimeToScreen(GetTime());
|
||||
p.drawLine(playhead_x, 0, playhead_x, height());
|
||||
}
|
||||
|
||||
|
||||
@@ -44,14 +44,14 @@ void FootageViewerWidget::ConnectNodeEvent(ViewerOutput *n)
|
||||
{
|
||||
super::ConnectNodeEvent(n);
|
||||
|
||||
SetTimestamp(cached_timestamps_.value(n, 0));
|
||||
SetTime(cached_timestamps_.value(n, 0));
|
||||
}
|
||||
|
||||
void FootageViewerWidget::DisconnectNodeEvent(ViewerOutput *n)
|
||||
{
|
||||
// Cache timestamp in case this footage is opened again later
|
||||
cached_timestamps_.insert(n, GetTimestamp());
|
||||
SetTimestamp(0);
|
||||
cached_timestamps_.insert(n, GetTime());
|
||||
SetTime(0);
|
||||
|
||||
super::DisconnectNodeEvent(n);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ protected:
|
||||
private:
|
||||
void StartFootageDragInternal(bool enable_video, bool enable_audio);
|
||||
|
||||
QHash<ViewerOutput*, int64_t> cached_timestamps_;
|
||||
QHash<ViewerOutput*, rational> cached_timestamps_;
|
||||
|
||||
private slots:
|
||||
void StartFootageDrag();
|
||||
|
||||
@@ -121,7 +121,7 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
SetScale(48.0);
|
||||
|
||||
// Ensures that seeking on the waveform view updates the time as expected
|
||||
connect(waveform_view_, &AudioWaveformView::TimeChanged, this, &ViewerWidget::TimeChangedFromWaveform);
|
||||
connect(waveform_view_, &AudioWaveformView::TimeChanged, this, &ViewerWidget::SetTimeAndSignal);
|
||||
connect(waveform_view_, &AudioWaveformView::customContextMenuRequested, this, &ViewerWidget::ShowContextMenu);
|
||||
|
||||
connect(&playback_backup_timer_, &QTimer::timeout, this, &ViewerWidget::PlaybackTimerUpdate);
|
||||
@@ -144,30 +144,16 @@ ViewerWidget::~ViewerWidget()
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWidget::TimeChangedEvent(const int64_t &i)
|
||||
void ViewerWidget::TimeChangedEvent(const rational &time)
|
||||
{
|
||||
if (!time_changed_from_timer_) {
|
||||
PauseInternal();
|
||||
}
|
||||
|
||||
controls_->SetTime(i);
|
||||
|
||||
{
|
||||
// Update waveform time
|
||||
qint64 waveform_time;
|
||||
|
||||
if (waveform_view_->timebase() != this->timebase()) {
|
||||
waveform_time = Timecode::rescale_timestamp(i, this->timebase(), waveform_view_->timebase());
|
||||
} else {
|
||||
waveform_time = i;
|
||||
}
|
||||
|
||||
waveform_view_->SetTime(waveform_time);
|
||||
}
|
||||
|
||||
if (GetConnectedNode() && last_time_ != i) {
|
||||
rational time_set = Timecode::timestamp_to_time(i, timebase());
|
||||
controls_->SetTime(time);
|
||||
waveform_view_->SetTime(time);
|
||||
|
||||
if (GetConnectedNode() && last_time_ != time) {
|
||||
if (!IsPlaying()) {
|
||||
UpdateTextureFromNode();
|
||||
|
||||
@@ -178,13 +164,13 @@ void ViewerWidget::TimeChangedEvent(const int64_t &i)
|
||||
display_widget_->ResetFPSTimer();
|
||||
}
|
||||
|
||||
display_widget_->SetTime(time_set);
|
||||
display_widget_->SetTime(time);
|
||||
}
|
||||
|
||||
// Send time to auto-cacher
|
||||
UpdateAutoCacher();
|
||||
|
||||
last_time_ = i;
|
||||
last_time_ = time;
|
||||
}
|
||||
|
||||
void ViewerWidget::ConnectNodeEvent(ViewerOutput *n)
|
||||
@@ -573,14 +559,14 @@ void ViewerWidget::PlayInternal(int speed, bool in_to_out_only)
|
||||
if (speed > 0) {
|
||||
SetTimeAndSignal(0);
|
||||
} else {
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(GetConnectedNode()->GetLength(), timebase()));
|
||||
SetTimeAndSignal(GetConnectedNode()->GetLength());
|
||||
}
|
||||
}
|
||||
|
||||
playback_speed_ = speed;
|
||||
play_in_to_out_only_ = in_to_out_only;
|
||||
|
||||
playback_queue_next_frame_ = ruler()->GetTime();
|
||||
playback_queue_next_frame_ = GetTimestamp();
|
||||
|
||||
controls_->ShowPauseButton();
|
||||
|
||||
@@ -752,7 +738,7 @@ RenderTicketPtr ViewerWidget::GetFrame(const rational &t, bool prioritize)
|
||||
|
||||
void ViewerWidget::FinishPlayPreprocess()
|
||||
{
|
||||
int64_t playback_start_time = ruler()->GetTime();
|
||||
int64_t playback_start_time = GetTimestamp();
|
||||
|
||||
StartAudioOutput();
|
||||
|
||||
@@ -1062,7 +1048,7 @@ void ViewerWidget::Play(bool in_to_out_only)
|
||||
if (GetConnectedNode()
|
||||
&& GetConnectedNode()->GetTimelinePoints()->workarea()->enabled()) {
|
||||
// Jump to in point
|
||||
SetTimeAndSignal(Timecode::time_to_timestamp(GetConnectedNode()->GetTimelinePoints()->workarea()->in(), timebase()));
|
||||
SetTimeAndSignal(GetConnectedNode()->GetTimelinePoints()->workarea()->in());
|
||||
} else {
|
||||
in_to_out_only = false;
|
||||
}
|
||||
@@ -1148,21 +1134,21 @@ void ViewerWidget::TimebaseChangedEvent(const rational &timebase)
|
||||
|
||||
void ViewerWidget::PlaybackTimerUpdate()
|
||||
{
|
||||
int64_t current_time = playback_timer_.GetTimestampNow();
|
||||
rational current_time = Timecode::timestamp_to_time(playback_timer_.GetTimestampNow(), timebase());
|
||||
|
||||
int64_t min_time, max_time;
|
||||
rational min_time, max_time;
|
||||
|
||||
if (play_in_to_out_only_ && GetConnectedNode()->GetTimelinePoints()->workarea()->enabled()) {
|
||||
|
||||
// If "play in to out" is enabled or we're looping AND we have a workarea, only play the workarea
|
||||
min_time = Timecode::time_to_timestamp(GetConnectedNode()->GetTimelinePoints()->workarea()->in(), timebase());
|
||||
max_time = Timecode::time_to_timestamp(GetConnectedNode()->GetTimelinePoints()->workarea()->out(), timebase());
|
||||
min_time = GetConnectedNode()->GetTimelinePoints()->workarea()->in();
|
||||
max_time = GetConnectedNode()->GetTimelinePoints()->workarea()->out();
|
||||
|
||||
} else {
|
||||
|
||||
// Otherwise set the bounds to the range of the sequence
|
||||
min_time = 0;
|
||||
max_time = Timecode::time_to_timestamp(GetConnectedNode()->GetLength(), timebase());
|
||||
max_time = GetConnectedNode()->GetLength();
|
||||
|
||||
}
|
||||
|
||||
@@ -1170,7 +1156,7 @@ void ViewerWidget::PlaybackTimerUpdate()
|
||||
|| (playback_speed_ > 0 && current_time >= max_time)) {
|
||||
|
||||
// Determine which timestamp we tripped
|
||||
int64_t tripped_time;
|
||||
rational tripped_time;
|
||||
|
||||
if (current_time <= min_time) {
|
||||
tripped_time = min_time;
|
||||
@@ -1181,7 +1167,7 @@ void ViewerWidget::PlaybackTimerUpdate()
|
||||
if (Config::Current()[QStringLiteral("Loop")].toBool()) {
|
||||
|
||||
// If we're looping, jump to the other side of the workarea and continue
|
||||
int64_t opposing_time = (tripped_time == min_time) ? max_time : min_time;
|
||||
rational opposing_time = (tripped_time == min_time) ? max_time : min_time;
|
||||
|
||||
// Cache the current speed
|
||||
int current_speed = playback_speed_;
|
||||
@@ -1211,8 +1197,7 @@ void ViewerWidget::PlaybackTimerUpdate()
|
||||
UpdateTextureFromNode();
|
||||
} else if (!windows_.empty()) {
|
||||
// We still run the queue if windows are visible even if our own display widget isn't visible
|
||||
rational t = GetTime();
|
||||
while (!playback_queue_.empty() && playback_queue_.front().timestamp != t) {
|
||||
while (!playback_queue_.empty() && playback_queue_.front().timestamp != GetTime()) {
|
||||
PopOldestFrameFromPlaybackQueue();
|
||||
}
|
||||
}
|
||||
@@ -1239,7 +1224,7 @@ void ViewerWidget::SetViewerPixelAspect(const rational &ratio)
|
||||
void ViewerWidget::LengthChangedSlot(const rational &length)
|
||||
{
|
||||
if (last_length_ != length) {
|
||||
controls_->SetEndTime(Timecode::time_to_timestamp(length, timebase()));
|
||||
controls_->SetEndTime(length);
|
||||
UpdateMinimumScale();
|
||||
|
||||
if (length < last_length_ && GetTime() >= length) {
|
||||
@@ -1296,16 +1281,6 @@ void ViewerWidget::ManualSwitchToWaveform(bool e)
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWidget::TimeChangedFromWaveform(qint64 t)
|
||||
{
|
||||
if (waveform_view_->timebase() != this->timebase()) {
|
||||
// Transform time to our timebase
|
||||
t = Timecode::rescale_timestamp(t, waveform_view_->timebase(), this->timebase());
|
||||
}
|
||||
|
||||
SetTimeAndSignal(t);
|
||||
}
|
||||
|
||||
void ViewerWidget::ViewerShiftedRange(const rational &from, const rational &to)
|
||||
{
|
||||
if (GetTime() >= qMin(from, to)) {
|
||||
|
||||
@@ -149,7 +149,7 @@ signals:
|
||||
|
||||
protected:
|
||||
virtual void TimebaseChangedEvent(const rational &) override;
|
||||
virtual void TimeChangedEvent(const int64_t &) override;
|
||||
virtual void TimeChangedEvent(const rational &time) override;
|
||||
|
||||
virtual void ConnectNodeEvent(ViewerOutput *) override;
|
||||
virtual void DisconnectNodeEvent(ViewerOutput *) override;
|
||||
@@ -167,6 +167,11 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
int64_t GetTimestamp() const
|
||||
{
|
||||
return Timecode::time_to_timestamp(GetTime(), timebase(), Timecode::kFloor);
|
||||
}
|
||||
|
||||
void UpdateTimeInternal(int64_t i);
|
||||
|
||||
void PlayInternal(int speed, bool in_to_out_only);
|
||||
@@ -215,7 +220,7 @@ private:
|
||||
|
||||
QAtomicInt playback_speed_;
|
||||
|
||||
int64_t last_time_;
|
||||
rational last_time_;
|
||||
|
||||
bool color_menu_enabled_;
|
||||
|
||||
@@ -294,8 +299,6 @@ private slots:
|
||||
|
||||
void ManualSwitchToWaveform(bool e);
|
||||
|
||||
void TimeChangedFromWaveform(qint64 t);
|
||||
|
||||
void DragEntered(QDragEnterEvent* event);
|
||||
|
||||
void Dropped(QDropEvent* event);
|
||||
|
||||
@@ -110,6 +110,8 @@ MainMenu::MainMenu(MainWindow *parent) :
|
||||
edit_menu_->addSeparator();
|
||||
edit_nudge_left_item_ = edit_menu_->AddItem("nudgeleft", this, &MainMenu::NudgeLeftTriggered, "Alt+Left");
|
||||
edit_nudge_right_item_ = edit_menu_->AddItem("nudgeright", this, &MainMenu::NudgeRightTriggered, "Alt+Right");
|
||||
edit_move_in_to_playhead_item_ = edit_menu_->AddItem("moveintoplayhead", this, &MainMenu::MoveInToPlayheadTriggered, "[");
|
||||
edit_move_out_to_playhead_item_ = edit_menu_->AddItem("moveouttoplayhead", this, &MainMenu::MoveOutToPlayheadTriggered, "]");
|
||||
edit_menu_->addSeparator();
|
||||
MenuShared::instance()->AddItemsForInOutMenu(edit_menu_);
|
||||
edit_delete_inout_item_ = edit_menu_->AddItem("deleteinout", this, &MainMenu::DeleteInOutTriggered, ";");
|
||||
@@ -550,6 +552,16 @@ void MainMenu::NudgeRightTriggered()
|
||||
PanelManager::instance()->CurrentlyFocused()->NudgeRight();
|
||||
}
|
||||
|
||||
void MainMenu::MoveInToPlayheadTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->MoveInToPlayhead();
|
||||
}
|
||||
|
||||
void MainMenu::MoveOutToPlayheadTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->MoveOutToPlayhead();
|
||||
}
|
||||
|
||||
void MainMenu::ActionSearchTriggered()
|
||||
{
|
||||
ActionSearch as(parentWidget());
|
||||
@@ -677,6 +689,8 @@ void MainMenu::Retranslate()
|
||||
edit_edit_to_out_item_->setText(tr("Edit to Out Point"));
|
||||
edit_nudge_left_item_->setText(tr("Nudge Left"));
|
||||
edit_nudge_right_item_->setText(tr("Nudge Right"));
|
||||
edit_move_in_to_playhead_item_->setText(tr("Move In Point to Playhead"));
|
||||
edit_move_out_to_playhead_item_->setText(tr("Move Out Point to Playhead"));
|
||||
edit_delete_inout_item_->setText(tr("Delete In/Out Point"));
|
||||
edit_ripple_delete_inout_item_->setText(tr("Ripple Delete In/Out Point"));
|
||||
edit_set_marker_item_->setText(tr("Set/Edit Marker"));
|
||||
|
||||
@@ -156,6 +156,8 @@ private slots:
|
||||
|
||||
void NudgeLeftTriggered();
|
||||
void NudgeRightTriggered();
|
||||
void MoveInToPlayheadTriggered();
|
||||
void MoveOutToPlayheadTriggered();
|
||||
|
||||
void ActionSearchTriggered();
|
||||
|
||||
@@ -223,6 +225,8 @@ private:
|
||||
QAction* edit_edit_to_out_item_;
|
||||
QAction* edit_nudge_left_item_;
|
||||
QAction* edit_nudge_right_item_;
|
||||
QAction* edit_move_in_to_playhead_item_;
|
||||
QAction* edit_move_out_to_playhead_item_;
|
||||
QAction* edit_delete_inout_item_;
|
||||
QAction* edit_ripple_delete_inout_item_;
|
||||
QAction* edit_set_marker_item_;
|
||||
|
||||
@@ -102,15 +102,15 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
connect(param_panel_, &ParamPanel::FocusedNodeChanged, sequence_viewer_panel_, &ViewerPanel::SetGizmos);
|
||||
|
||||
// Connect time signals together
|
||||
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, param_panel_, &ParamPanel::SetTimestamp);
|
||||
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, table_panel_, &NodeTablePanel::SetTimestamp);
|
||||
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, curve_panel_, &NodeTablePanel::SetTimestamp);
|
||||
connect(param_panel_, &ParamPanel::TimeChanged, sequence_viewer_panel_, &SequenceViewerPanel::SetTimestamp);
|
||||
connect(param_panel_, &ParamPanel::TimeChanged, table_panel_, &NodeTablePanel::SetTimestamp);
|
||||
connect(param_panel_, &ParamPanel::TimeChanged, curve_panel_, &NodeTablePanel::SetTimestamp);
|
||||
connect(curve_panel_, &ParamPanel::TimeChanged, sequence_viewer_panel_, &SequenceViewerPanel::SetTimestamp);
|
||||
connect(curve_panel_, &ParamPanel::TimeChanged, table_panel_, &NodeTablePanel::SetTimestamp);
|
||||
connect(curve_panel_, &ParamPanel::TimeChanged, param_panel_, &NodeTablePanel::SetTimestamp);
|
||||
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, param_panel_, &ParamPanel::SetTime);
|
||||
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, table_panel_, &NodeTablePanel::SetTime);
|
||||
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, curve_panel_, &NodeTablePanel::SetTime);
|
||||
connect(param_panel_, &ParamPanel::TimeChanged, sequence_viewer_panel_, &SequenceViewerPanel::SetTime);
|
||||
connect(param_panel_, &ParamPanel::TimeChanged, table_panel_, &NodeTablePanel::SetTime);
|
||||
connect(param_panel_, &ParamPanel::TimeChanged, curve_panel_, &NodeTablePanel::SetTime);
|
||||
connect(curve_panel_, &ParamPanel::TimeChanged, sequence_viewer_panel_, &SequenceViewerPanel::SetTime);
|
||||
connect(curve_panel_, &ParamPanel::TimeChanged, table_panel_, &NodeTablePanel::SetTime);
|
||||
connect(curve_panel_, &ParamPanel::TimeChanged, param_panel_, &NodeTablePanel::SetTime);
|
||||
|
||||
// Connect node order signals
|
||||
connect(param_panel_, &ParamPanel::NodeOrderChanged, curve_panel_, &CurvePanel::SetNodes);
|
||||
@@ -564,14 +564,14 @@ TimelinePanel* MainWindow::AppendTimelinePanel()
|
||||
TimelinePanel* panel = AppendPanelInternal<TimelinePanel>(timeline_panels_);
|
||||
|
||||
connect(panel, &PanelWidget::CloseRequested, this, &MainWindow::TimelineCloseRequested);
|
||||
connect(panel, &TimelinePanel::TimeChanged, curve_panel_, &ParamPanel::SetTimestamp);
|
||||
connect(panel, &TimelinePanel::TimeChanged, param_panel_, &ParamPanel::SetTimestamp);
|
||||
connect(panel, &TimelinePanel::TimeChanged, table_panel_, &NodeTablePanel::SetTimestamp);
|
||||
connect(panel, &TimelinePanel::TimeChanged, sequence_viewer_panel_, &SequenceViewerPanel::SetTimestamp);
|
||||
connect(panel, &TimelinePanel::TimeChanged, curve_panel_, &ParamPanel::SetTime);
|
||||
connect(panel, &TimelinePanel::TimeChanged, param_panel_, &ParamPanel::SetTime);
|
||||
connect(panel, &TimelinePanel::TimeChanged, table_panel_, &NodeTablePanel::SetTime);
|
||||
connect(panel, &TimelinePanel::TimeChanged, sequence_viewer_panel_, &SequenceViewerPanel::SetTime);
|
||||
connect(panel, &TimelinePanel::BlockSelectionChanged, this, &MainWindow::TimelinePanelSelectionChanged);
|
||||
connect(param_panel_, &ParamPanel::TimeChanged, panel, &TimelinePanel::SetTimestamp);
|
||||
connect(curve_panel_, &ParamPanel::TimeChanged, panel, &TimelinePanel::SetTimestamp);
|
||||
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, panel, &TimelinePanel::SetTimestamp);
|
||||
connect(param_panel_, &ParamPanel::TimeChanged, panel, &TimelinePanel::SetTime);
|
||||
connect(curve_panel_, &ParamPanel::TimeChanged, panel, &TimelinePanel::SetTime);
|
||||
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, panel, &TimelinePanel::SetTime);
|
||||
|
||||
sequence_viewer_panel_->ConnectTimeBasedPanel(panel);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user