diff --git a/app/core.cpp b/app/core.cpp index dd0638099..1935335af 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -311,7 +311,7 @@ void Core::CreateNewSequence() // Connect timeline end point to renderer NodeParam::ConnectEdge(tb->length_output(), rp->length_input()); - vo->AttachViewer(olive::panel_focus_manager->MostRecentlyFocused()); + olive::panel_focus_manager->MostRecentlyFocused()->ConnectViewerNode(vo); olive::panel_focus_manager->MostRecentlyFocused()->ConnectTimelineNode(tb); olive::panel_focus_manager->MostRecentlyFocused()->SetGraph(new_sequence.get()); diff --git a/app/node/output/viewer/viewer.cpp b/app/node/output/viewer/viewer.cpp index 87ee9273f..b04399199 100644 --- a/app/node/output/viewer/viewer.cpp +++ b/app/node/output/viewer/viewer.cpp @@ -20,8 +20,7 @@ #include "viewer.h" -ViewerOutput::ViewerOutput() : - attached_viewer_(nullptr) +ViewerOutput::ViewerOutput() { texture_input_ = new NodeInput("tex_out"); texture_input_->add_data_input(NodeInput::kTexture); @@ -48,13 +47,16 @@ QString ViewerOutput::Description() return tr("Interface between a Viewer panel and the node system."); } +const rational &ViewerOutput::Timebase() +{ + return timebase_; +} + void ViewerOutput::SetTimebase(const rational &timebase) { timebase_ = timebase; - if (attached_viewer_ != nullptr) { - attached_viewer_->SetTimebase(timebase_); - } + emit TimebaseChanged(timebase_); } NodeInput *ViewerOutput::texture_input() @@ -62,46 +64,20 @@ NodeInput *ViewerOutput::texture_input() return texture_input_; } -void ViewerOutput::AttachViewer(ViewerPanel *viewer) +RenderTexturePtr ViewerOutput::GetTexture(const rational &time) { - // Disconnect old viewer if there's one attached - if (attached_viewer_ != nullptr) { - disconnect(attached_viewer_, SIGNAL(TimeChanged(const rational&)), this, SLOT(ViewerTimeChanged(const rational&))); - - // Clear any existing texture - attached_viewer_->SetTexture(0); - } - - // FIXME: Currently this attaches to ViewerPanels, but should it attached to Viewers instead? - attached_viewer_ = viewer; - - if (attached_viewer_ != nullptr) { - connect(attached_viewer_, SIGNAL(TimeChanged(const rational&)), this, SLOT(ViewerTimeChanged(const rational&))); - SetTimebase(timebase_); - - // Update the texture - ViewerTimeChanged(attached_viewer_->GetTime()); - } + return texture_input_->get_value(time).value(); } void ViewerOutput::InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from) { Node::InvalidateCache(start_range, end_range, from); - if (attached_viewer_ != nullptr - && (start_range == attached_viewer_->GetTime() || end_range == attached_viewer_->GetTime())) { - // Update any attached viewer - ForceUpdateViewer(); - } + emit TextureChangedBetween(start_range, end_range); SendInvalidateCache(start_range, end_range); } -void ViewerOutput::ForceUpdateViewer() -{ - ViewerTimeChanged(attached_viewer_->GetTime()); -} - QVariant ViewerOutput::Value(NodeOutput *output, const rational &time) { Q_UNUSED(output) @@ -109,16 +85,3 @@ QVariant ViewerOutput::Value(NodeOutput *output, const rational &time) return 0; } - -void ViewerOutput::ViewerTimeChanged(const rational &t) -{ - // Get the texture from whatever Node is currently connected (usually a Renderer of some kind) - RenderTexturePtr current_texture = texture_input_->get_value(t).value(); - - // Send the texture to the Viewer - if (current_texture != nullptr) { - attached_viewer_->SetTexture(current_texture->texture()); - } else { - attached_viewer_->SetTexture(0); - } -} diff --git a/app/node/output/viewer/viewer.h b/app/node/output/viewer/viewer.h index 15ea0a2cd..6d29af9c6 100644 --- a/app/node/output/viewer/viewer.h +++ b/app/node/output/viewer/viewer.h @@ -22,7 +22,6 @@ #define VIEWER_H #include "node/node.h" -#include "panel/viewer/viewer.h" #include "render/rendertexture.h" /** @@ -41,29 +40,28 @@ public: virtual QString Category() override; virtual QString Description() override; + const rational& Timebase(); void SetTimebase(const rational& timebase); NodeInput* texture_input(); - void AttachViewer(ViewerPanel* viewer); + RenderTexturePtr GetTexture(const rational& time); virtual void InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from = nullptr) override; +signals: + void TimebaseChanged(const rational&); + + void TextureChangedBetween(const rational&, const rational&); + protected: virtual QVariant Value(NodeOutput* output, const rational& time) override; private: - void ForceUpdateViewer(); - NodeInput* texture_input_; - ViewerPanel* attached_viewer_; - rational timebase_; -private slots: - void ViewerTimeChanged(const rational& t); - }; #endif // VIEWER_H diff --git a/app/panel/viewer/viewer.cpp b/app/panel/viewer/viewer.cpp index 92c352360..a81ddd682 100644 --- a/app/panel/viewer/viewer.cpp +++ b/app/panel/viewer/viewer.cpp @@ -74,12 +74,22 @@ void ViewerPanel::SetTimebase(const rational &timebase) viewer_->SetTimebase(timebase); } +void ViewerPanel::ConnectViewerNode(ViewerOutput *node) +{ + viewer_->ConnectViewerNode(node); +} + +void ViewerPanel::DisconnectViewerNode() +{ + viewer_->DisconnectViewerNode(); +} + rational ViewerPanel::GetTime() { return viewer_->GetTime(); } -void ViewerPanel::SetTexture(GLuint tex) +void ViewerPanel::SetTexture(RenderTexturePtr tex) { viewer_->SetTexture(tex); } diff --git a/app/panel/viewer/viewer.h b/app/panel/viewer/viewer.h index f0dc4506a..12abcf438 100644 --- a/app/panel/viewer/viewer.h +++ b/app/panel/viewer/viewer.h @@ -50,6 +50,10 @@ public: void SetTimebase(const rational& timebase); + void ConnectViewerNode(ViewerOutput* node); + + void DisconnectViewerNode(); + rational GetTime(); public slots: @@ -60,7 +64,7 @@ public slots: * * @param tex */ - void SetTexture(GLuint tex); + void SetTexture(RenderTexturePtr tex); protected: virtual void changeEvent(QEvent* e) override; diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index ffd012a98..52bb15da9 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -29,7 +29,8 @@ #include "viewersizer.h" ViewerWidget::ViewerWidget(QWidget *parent) : - QWidget(parent) + QWidget(parent), + viewer_node_(nullptr) { // Set up main layout QVBoxLayout* layout = new QVBoxLayout(this); @@ -121,9 +122,40 @@ bool ViewerWidget::IsPlaying() return playback_timer_.isActive(); } -void ViewerWidget::SetTexture(GLuint tex) +void ViewerWidget::ConnectViewerNode(ViewerOutput *node) { - gl_widget_->SetTexture(tex); + if (viewer_node_ != nullptr) { + SetTimebase(0); + + disconnect(viewer_node_, SIGNAL(TimebaseChanged(const rational&)), this, SLOT(SetTimebase(const rational&))); + disconnect(viewer_node_, SIGNAL(TextureChangedBetween(const rational&, const rational&)), this, SLOT(ViewerNodeChangedBetween(const rational&, const rational&))); + } + + viewer_node_ = node; + + // Set texture to new texture (or null if no viewer node is available) + UpdateTextureFromNode(GetTime()); + + if (viewer_node_ != nullptr) { + SetTimebase(viewer_node_->Timebase()); + + connect(viewer_node_, SIGNAL(TimebaseChanged(const rational&)), this, SLOT(SetTimebase(const rational&))); + connect(viewer_node_, SIGNAL(TextureChangedBetween(const rational&, const rational&)), this, SLOT(ViewerNodeChangedBetween(const rational&, const rational&))); + } +} + +void ViewerWidget::DisconnectViewerNode() +{ + ConnectViewerNode(nullptr); +} + +void ViewerWidget::SetTexture(RenderTexturePtr tex) +{ + if (tex == nullptr) { + gl_widget_->SetTexture(0); + } else { + gl_widget_->SetTexture(tex->texture()); + } } void ViewerWidget::UpdateTimeInternal(int64_t i) @@ -132,9 +164,22 @@ void ViewerWidget::UpdateTimeInternal(int64_t i) controls_->SetTime(i); + if (viewer_node_ != nullptr) { + UpdateTextureFromNode(time_set); + } + emit TimeChanged(time_set); } +void ViewerWidget::UpdateTextureFromNode(const rational& time) +{ + if (viewer_node_ == nullptr) { + SetTexture(nullptr); + } else { + SetTexture(viewer_node_->GetTexture(time)); + } +} + void ViewerWidget::RulerTimeChange(int64_t i) { Pause(); @@ -201,6 +246,13 @@ void ViewerWidget::PlaybackTimerUpdate() SetTime(start_timestamp_ + frames_since_start); } +void ViewerWidget::ViewerNodeChangedBetween(const rational &start, const rational &end) +{ + if (GetTime() >= start && GetTime() <= end) { + UpdateTextureFromNode(GetTime()); + } +} + void ViewerWidget::resizeEvent(QResizeEvent *event) { // Set scrollbar page step to the width diff --git a/app/widget/viewer/viewer.h b/app/widget/viewer/viewer.h index ce17aa7d8..899e9a8e4 100644 --- a/app/widget/viewer/viewer.h +++ b/app/widget/viewer/viewer.h @@ -28,6 +28,7 @@ #include #include "common/rational.h" +#include "node/output/viewer/viewer.h" #include "viewerglwidget.h" #include "widget/playbackcontrols/playbackcontrols.h" #include "widget/timeruler/timeruler.h" @@ -45,8 +46,6 @@ public: void SetTimeRulerEnabled(bool enabled); - void SetTimebase(const rational& r); - const double& scale(); rational GetTime(); @@ -59,6 +58,10 @@ public: bool IsPlaying(); + void ConnectViewerNode(ViewerOutput* node); + + void DisconnectViewerNode(); + public slots: /** * @brief Set the texture to draw and draw it @@ -67,7 +70,9 @@ public slots: * * @param tex */ - void SetTexture(GLuint tex); + void SetTexture(RenderTexturePtr tex); + + void SetTimebase(const rational& r); void GoToStart(); @@ -90,6 +95,8 @@ protected: private: void UpdateTimeInternal(int64_t i); + void UpdateTextureFromNode(const rational &time); + ViewerGLWidget* gl_widget_; PlaybackControls* controls_; @@ -107,11 +114,15 @@ private: qint64 start_msec_; int64_t start_timestamp_; + ViewerOutput* viewer_node_; + private slots: void RulerTimeChange(int64_t); void PlaybackTimerUpdate(); + void ViewerNodeChangedBetween(const rational& start, const rational& end); + }; #endif // VIEWER_WIDGET_H