multicam: various improvements

This commit is contained in:
itsmattkc
2022-10-01 16:57:46 -07:00
parent e91ae5e4df
commit 14bf515d3f
9 changed files with 142 additions and 110 deletions
+47 -30
View File
@@ -19,6 +19,7 @@
***/
#include "multicamwidget.h"
#include "qshortcut.h"
#include "widget/nodeparamview/nodeparamviewundo.h"
#include "widget/timeruler/timeruler.h"
#include "widget/timelinewidget/undo/timelineundosplit.h"
@@ -48,6 +49,11 @@ MulticamWidget::MulticamWidget(QWidget *parent) :
layout->addWidget(this->ruler());
layout->addWidget(this->scrollbar());
for (int i=0; i<9; i++) {
new QShortcut(QStringLiteral("Ctrl+%1").arg(QString::number(i+1)), this, this, [this, i]{Switch(i, false);});
new QShortcut(QString::number(i+1), this, this, [this, i]{Switch(i, true);});
}
}
void MulticamWidget::SetMulticamNode(MultiCamNode *n)
@@ -77,6 +83,45 @@ void MulticamWidget::DisconnectNodeEvent(ViewerOutput *n)
disconnect(n, &ViewerOutput::PixelAspectChanged, sizer_, &ViewerSizer::SetPixelAspectRatio);
}
void MulticamWidget::Switch(int source, bool split_clip)
{
if (!node_) {
return;
}
MultiUndoCommand *command = new MultiUndoCommand();
MultiCamNode *cam = node_;
ClipBlock *clip = clip_;
if (clip_ && split_clip && clip_->in() < GetTime() && clip_->out() > GetTime()) {
QVector<Block*> blocks;
blocks.append(clip_);
blocks.append(clip_->block_links());
auto split = new BlockSplitPreservingLinksCommand(blocks, {GetTime()});
split->redo_now();
command->add_child(split);
clip = static_cast<ClipBlock*>(split->GetSplit(clip_, 0));
cam = clip->FindMulticam();
}
command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(NodeInput(cam, cam->kCurrentInput)), source));
Core::instance()->undo_stack()->push(command);
if (cam != node_) {
SetMulticamNode(cam);
}
if (clip != clip_) {
SetClip(clip);
}
display_->update();
}
void MulticamWidget::DisplayClicked(const QPoint &p)
{
if (!node_) {
@@ -99,37 +144,9 @@ void MulticamWidget::DisplayClicked(const QPoint &p)
int c = click.x() / (width/multi);
int r = click.y() / (height/multi);
MultiUndoCommand *command = new MultiUndoCommand();
int source = node_->RowsColsToIndex(r, c, rows, cols);
const bool enable_split = true;
MultiCamNode *cam = node_;
ClipBlock *clip = clip_;
if (clip_ && enable_split && clip_->in() < GetTime() && clip_->out() > GetTime()) {
QVector<Block*> blocks;
blocks.append(clip_);
blocks.append(clip_->block_links());
auto split = new BlockSplitPreservingLinksCommand(blocks, {GetTime()});
split->redo_now();
command->add_child(split);
clip = static_cast<ClipBlock*>(split->GetSplit(clip_, 0));
cam = clip->FindMulticam();
}
command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(NodeInput(cam, cam->kCurrentInput)), cam->RowsColsToIndex(r, c, rows, cols)));
Core::instance()->undo_stack()->push(command);
if (cam != node_) {
SetMulticamNode(cam);
}
if (clip != clip_) {
SetClip(clip);
}
Switch(source, true);
}
}
+2
View File
@@ -44,6 +44,8 @@ protected:
virtual void DisconnectNodeEvent(ViewerOutput *n) override;
private:
void Switch(int source, bool split_clip);
ViewerSizer *sizer_;
MulticamDisplay *display_;
+54 -9
View File
@@ -40,6 +40,8 @@
#include "node/block/gap/gap.h"
#include "node/generator/shape/shapenodebase.h"
#include "node/project/project.h"
#include "panel/multicam/multicampanel.h"
#include "panel/panelmanager.h"
#include "render/rendermanager.h"
#include "viewerpreventsleep.h"
#include "widget/audiomonitor/audiomonitor.h"
@@ -75,7 +77,8 @@ ViewerWidget::ViewerWidget(ViewerDisplayWidget *display, QWidget *parent) :
first_requeue_watcher_(nullptr),
enable_audio_scrubbing_(true),
waveform_mode_(kWFAutomatic),
ignore_scrub_(0)
ignore_scrub_(0),
multicam_panel_(nullptr)
{
// Set up main layout
QVBoxLayout* layout = new QVBoxLayout(this);
@@ -604,6 +607,53 @@ void ViewerWidget::SetWaveformMode(WaveformMode wf)
UpdateWaveformViewFromMode();
}
void ViewerWidget::DetectMulticamNode(const rational &time)
{
// Look for multicam node
MultiCamNode *multicam = nullptr;
ClipBlock *clip = nullptr;
// Faster way to do this
if (multicam_panel_ && multicam_panel_->isVisible()) {
if (Sequence *s = dynamic_cast<Sequence*>(GetConnectedNode())) {
// Prefer selected blocks
for (Block *b : timeline_selected_blocks_) {
if (b->range().Contains(time)) {
if ((clip = dynamic_cast<ClipBlock*>(b))) {
if ((multicam = clip->FindMulticam())) {
break;
}
}
}
}
if (!multicam) {
const QVector<Track*> &tracks = s->GetTracks();
for (Track *t : tracks) {
if (t->IsLocked()) {
continue;
}
Block *b = t->NearestBlockBeforeOrAt(time);
if ((clip = dynamic_cast<ClipBlock*>(b))) {
if ((multicam = clip->FindMulticam())) {
break;
}
}
}
}
}
}
if (multicam) {
emit MulticamNodeDetected(GetConnectedNode(), multicam, clip);
auto_cacher()->SetMulticamNode(multicam);
} else {
auto_cacher()->SetMulticamNode(nullptr);
emit MulticamNodeDetected(nullptr, nullptr, nullptr);
}
}
void ViewerWidget::UpdateWaveformViewFromMode()
{
bool prefer_waveform = ShouldForceWaveform();
@@ -790,6 +840,8 @@ void ViewerWidget::UpdateTextureFromNode()
// Clear queue because we want this frame more than any others
auto_cacher_->ClearSingleFrameRenders();
DetectMulticamNode(time);
watcher->SetTicket(GetFrame(time));
} else {
// There is definitely no frame here, we can immediately flip to showing nothing
@@ -799,14 +851,6 @@ void ViewerWidget::UpdateTextureFromNode()
}
}
void ViewerWidget::SetMulticamNode(MultiCamNode *n)
{
auto_cacher()->SetMulticamNode(n);
if (!IsPlaying()) {
UpdateTextureFromNode();
}
}
void ViewerWidget::PlayInternal(int speed, bool in_to_out_only)
{
Q_ASSERT(speed != 0);
@@ -1035,6 +1079,7 @@ RenderTicketWatcher *ViewerWidget::RequestNextFrameForQueue(bool increment)
watcher = new RenderTicketWatcher();
watcher->setProperty("time", QVariant::fromValue(next_time));
DetectMulticamNode(next_time);
connect(watcher, &RenderTicketWatcher::Finished, this, &ViewerWidget::RendererGeneratedFrameForQueue);
queue_watchers_.append(watcher);
watcher->SetTicket(GetFrame(next_time));
+22 -1
View File
@@ -43,6 +43,8 @@
namespace olive {
class MulticamPanel;
/**
* @brief An OpenGL-based viewer widget with playback controls (a PlaybackControls widget).
*/
@@ -109,7 +111,18 @@ public:
playback_devices_.push_back(vw);
}
void SetMulticamNode(MultiCamNode *n);
void SetTimelineSelectedBlocks(const QVector<Block*> &b)
{
timeline_selected_blocks_ = b;
if (!IsPlaying()) {
// If is playing, this will happen by the next frame automatically
DetectMulticamNode(GetTime());
UpdateTextureFromNode();
}
}
void ConnectMulticamPanel(MulticamPanel *p) { multicam_panel_ = p; }
public slots:
void Play(bool in_to_out_only);
@@ -167,6 +180,8 @@ signals:
*/
void ColorManagerChanged(ColorManager* color_manager);
void MulticamNodeDetected(ViewerOutput *viewer, MultiCamNode *n, ClipBlock *clip);
protected:
ViewerWidget(ViewerDisplayWidget *display, QWidget* parent = nullptr);
@@ -256,6 +271,8 @@ private:
void SetWaveformMode(WaveformMode wf);
void DetectMulticamNode(const rational &time);
ViewerSizer* sizer_;
int playback_speed_;
@@ -324,6 +341,10 @@ private:
int ignore_scrub_;
QVector<Block*> timeline_selected_blocks_;
MulticamPanel *multicam_panel_;
private slots:
void PlaybackTimerUpdate();