Merge branch 'master' into transition-offsets

This commit is contained in:
itsmattkc
2021-08-02 14:20:56 -07:00
61 changed files with 735 additions and 367 deletions
+109 -46
View File
@@ -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,39 +1085,16 @@ 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()
{
HideSnaps();
@@ -1161,19 +1166,73 @@ void TimelineWidget::UpdateViewTimebases()
void TimelineWidget::NudgeInternal(const rational &amount)
{
MultiUndoCommand *command = new MultiUndoCommand();
if (!selected_blocks_.isEmpty()) {
MultiUndoCommand *command = new MultiUndoCommand();
foreach (Block* b, selected_blocks_) {
command->add_child(new TrackReplaceBlockWithGapCommand(b->track(), b, false));
command->add_child(new TrackPlaceBlockCommand(sequence()->track_list(b->track()->type()), b->track()->Index(), b, b->in() + amount));
foreach (Block* b, selected_blocks_) {
command->add_child(new TrackReplaceBlockWithGapCommand(b->track(), b, false));
command->add_child(new TrackPlaceBlockCommand(sequence()->track_list(b->track()->type()), b->track()->Index(), b, b->in() + amount));
}
// Nudge selections
TimelineWidgetSelections new_sel = GetSelections();
new_sel.ShiftTime(amount);
command->add_child(new TimelineWidget::SetSelectionsCommand(this, new_sel, GetSelections(), true));
Core::instance()->undo_stack()->push(command);
}
}
// Nudge selections
TimelineWidgetSelections new_sel = GetSelections();
new_sel.ShiftTime(amount);
command->add_child(new TimelineWidget::SetSelectionsCommand(this, new_sel, GetSelections(), true));
void TimelineWidget::MoveToPlayheadInternal(bool out)
{
if (GetConnectedNode() && !selected_blocks_.isEmpty()) {
MultiUndoCommand *command = new MultiUndoCommand();
Core::instance()->undo_stack()->pushIfHasChildren(command);
// 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_)));