From 5afe7d523c05885bcbf7e222a617e1cd21fe69ea Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 28 Aug 2019 01:24:50 +1000 Subject: [PATCH] shifted to new dependency structure --- app/node/blend/alphaover/alphaover.cpp | 14 +-- app/node/blend/alphaover/alphaover.h | 2 +- app/node/block/block.cpp | 26 ++-- app/node/block/block.h | 4 +- app/node/block/clip/clip.cpp | 31 ++--- app/node/block/clip/clip.h | 6 +- app/node/generator/solid/solid.cpp | 9 +- app/node/generator/solid/solid.h | 2 +- app/node/input.cpp | 31 +++-- app/node/input.h | 30 ++--- app/node/input/media/media.cpp | 115 ++++++++++-------- app/node/input/media/media.h | 2 +- app/node/node.cpp | 79 ++++++++---- app/node/node.h | 58 ++++++--- app/node/output.cpp | 18 +-- app/node/output.h | 12 +- app/node/output/timeline/timeline.cpp | 14 ++- app/node/output/timeline/timeline.h | 2 +- app/node/output/track/track.cpp | 51 ++++---- app/node/output/track/track.h | 4 +- app/node/output/viewer/viewer.cpp | 33 ++--- app/node/output/viewer/viewer.h | 8 +- app/node/param.cpp | 2 +- app/node/processor/renderer/renderer.cpp | 38 +++--- app/node/processor/renderer/renderer.h | 2 +- app/node/processor/renderer/rendererprobe.cpp | 11 +- .../processor/renderer/rendererthread.cpp | 4 +- 27 files changed, 343 insertions(+), 265 deletions(-) diff --git a/app/node/blend/alphaover/alphaover.cpp b/app/node/blend/alphaover/alphaover.cpp index a7ae036f7..008c425aa 100644 --- a/app/node/blend/alphaover/alphaover.cpp +++ b/app/node/blend/alphaover/alphaover.cpp @@ -22,16 +22,10 @@ QString AlphaOverBlend::Description() return tr("A blending node that composites one texture over another using its alpha channel."); } -void AlphaOverBlend::Process() +QVariant AlphaOverBlend::Value(NodeOutput *param, const rational &time) { - // FIXME: Write Alpha Over Formula + Q_UNUSED(param) + Q_UNUSED(time) - // Note that alpha will always be premultiplied by this point - - - - //GLuint base_tex = base_input_->get_value(time).value(); - - // FIXME: Does nothing - texture_output()->set_value(QVariant::fromValue(blend_input()->get_value().value())); + return 0; } diff --git a/app/node/blend/alphaover/alphaover.h b/app/node/blend/alphaover/alphaover.h index 6b275c520..29896570f 100644 --- a/app/node/blend/alphaover/alphaover.h +++ b/app/node/blend/alphaover/alphaover.h @@ -13,7 +13,7 @@ public: virtual QString Description() override; protected: - virtual void Process() override; + virtual QVariant Value(NodeOutput* param, const rational& time) override; }; #endif // ALPHAOVER_H diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp index 6e8d5cf4f..f426a81a8 100644 --- a/app/node/block/block.cpp +++ b/app/node/block/block.cpp @@ -70,7 +70,7 @@ void Block::set_length(const rational &length) Block *Block::previous() { - return ValueToPtr(previous_input_->get_value()); + return ValueToPtr(previous_input_->get_value(0)); } Block *Block::next() @@ -83,10 +83,16 @@ NodeInput *Block::previous_input() return previous_input_; } -void Block::Process() +QVariant Block::Value(NodeOutput *output, const rational &time) { - // Simply set both output values as a pointer to this object - block_output_->set_value(PtrToValue(this)); + Q_UNUSED(time) + + if (output == block_output_) { + // Simply set the output value to a pointer to this Block + return PtrToValue(this); + } + + return 0; } void Block::EdgeAddedSlot(NodeEdgePtr edge) @@ -174,14 +180,12 @@ void Block::set_media_in(const rational &media_in) } } -QList Block::GetImmediateDependenciesAt(const rational &time) +QList Block::RunDependencies(NodeOutput* param, const rational &time) { + // Base Blocks have no direct dependencies + + Q_UNUSED(param) Q_UNUSED(time) - QList nodes = Node::GetImmediateDependencies(); - - // Swap attached block for current block at this time - nodes.removeAll(previous()); - - return nodes; + return QList(); } diff --git a/app/node/block/block.h b/app/node/block/block.h index af78f52df..06904c61f 100644 --- a/app/node/block/block.h +++ b/app/node/block/block.h @@ -70,7 +70,7 @@ public: /** * @brief Override removes previous input as that is not a direct dependency */ - virtual QList GetImmediateDependenciesAt(const rational &time) override; + virtual QList RunDependencies(NodeOutput* output, const rational &time) override; public slots: /** @@ -102,7 +102,7 @@ signals: void Refreshed(); protected: - virtual void Process() override; + virtual QVariant Value(NodeOutput* output, const rational& time) override; private: NodeInput* previous_input_; diff --git a/app/node/block/clip/clip.cpp b/app/node/block/clip/clip.cpp index 68d09f767..cec0401de 100644 --- a/app/node/block/clip/clip.cpp +++ b/app/node/block/clip/clip.cpp @@ -67,31 +67,26 @@ NodeInput *ClipBlock::texture_input() return texture_input_; } -void ClipBlock::set_time(const rational &time) +rational ClipBlock::SequenceToMediaTime(const rational &sequence_time) { - Node::set_time(time); - - if (texture_input_->IsConnected()) { - // We convert the time given (timeline time) to media time - rational media_time = time - in() + media_in(); - - texture_input_->edges().first()->output()->parent()->set_time(media_time); - } + return sequence_time - in() + media_in(); } -void ClipBlock::Process() +QVariant ClipBlock::Value(NodeOutput* param, const rational& time) { - // Run default node processing - Block::Process(); + QVariant value = Block::Value(param, time); - // Check if we have a renderer instance - if (RendererProcessor::CurrentInstance() != nullptr) { + if (param == texture_output()) { // If the time retrieved is within this block, get texture information - if (time() >= in() && time() < out()) { + if (time >= in() && time < out()) { + // We convert the time given (timeline time) to media time + rational media_time = SequenceToMediaTime(time - in() + media_in()); + // Retrieve texture - texture_output()->set_value(texture_input_->get_value()); - } else { - texture_output()->set_value(0); + return texture_input_->get_value(media_time); } + return 0; } + + return Block::Value(param, time); } diff --git a/app/node/block/clip/clip.h b/app/node/block/clip/clip.h index 19e9a684f..0c76a2506 100644 --- a/app/node/block/clip/clip.h +++ b/app/node/block/clip/clip.h @@ -42,12 +42,12 @@ public: NodeInput* texture_input(); - virtual void set_time(const rational& time) override; - protected: - virtual void Process() override; + virtual QVariant Value(NodeOutput* output, const rational& time) override; private: + rational SequenceToMediaTime(const rational& sequence_time); + NodeInput* texture_input_; }; diff --git a/app/node/generator/solid/solid.cpp b/app/node/generator/solid/solid.cpp index 0d55593df..1dec67dd5 100644 --- a/app/node/generator/solid/solid.cpp +++ b/app/node/generator/solid/solid.cpp @@ -57,8 +57,12 @@ NodeOutput *SolidGenerator::texture_output() return texture_output_; } -void SolidGenerator::Process() +QVariant SolidGenerator::Value(NodeOutput *output, const rational &time) { + Q_UNUSED(output) + Q_UNUSED(time) + + /* // FIXME: Test code if (texture_ == nullptr) { QImage img(1920, 1080, QImage::Format_RGBA8888_Premultiplied); @@ -69,4 +73,7 @@ void SolidGenerator::Process() texture_output_->set_value(texture_->textureId()); // End test code + */ + + return 0; } diff --git a/app/node/generator/solid/solid.h b/app/node/generator/solid/solid.h index 8a2a00683..882fa1e20 100644 --- a/app/node/generator/solid/solid.h +++ b/app/node/generator/solid/solid.h @@ -42,7 +42,7 @@ public: NodeOutput* texture_output(); protected: - virtual void Process() override; + virtual QVariant Value(NodeOutput* output, const rational& time) override; private: NodeInput* color_input_; diff --git a/app/node/input.cpp b/app/node/input.cpp index 66e30f279..5ac9a1ced 100644 --- a/app/node/input.cpp +++ b/app/node/input.cpp @@ -24,8 +24,8 @@ NodeInput::NodeInput(const QString& id) : NodeParam(id), - keyframing_(false), - can_accept_multiple_inputs_(false) + time_(-1), + keyframing_(false) { // Have at least one keyframe/value active at any time keyframes_.append(NodeKeyframe()); @@ -51,26 +51,23 @@ bool NodeInput::can_accept_type(const NodeParam::DataType &data_type) return AreDataTypesCompatible(data_type, inputs_); } -bool NodeInput::can_accept_multiple_inputs() +QVariant NodeInput::get_value(const rational& time) { - return can_accept_multiple_inputs_; -} + if (time_ != time) { + // Retrieve the value + if (!edges_.isEmpty()) { + // One connection - use the output of the connected Node + value_ = edges_.first()->output()->get_value(time); + } -void NodeInput::set_can_accept_multiple_inputs(bool b) -{ - can_accept_multiple_inputs_ = b; -} + // No connections - use the internal value + // FIXME: Re-implement keyframing + value_ = keyframes_.first().value(); -QVariant NodeInput::get_value() -{ - if (!edges_.isEmpty()) { - // One connection - use the output of the connected Node - return edges_.first()->output()->get_value(); + time_ = time; } - // No connections - use the internal value - // FIXME: Re-implement keyframing - return keyframes_.first().value(); + return value_; } void NodeInput::set_value(const QVariant &value) diff --git a/app/node/input.h b/app/node/input.h index 6bde623a2..c33cc0894 100644 --- a/app/node/input.h +++ b/app/node/input.h @@ -54,20 +54,6 @@ public: */ bool can_accept_type(const DataType& data_type); - /** - * @brief Return whether this parameter accepts multiple inputs (false by default) - * - * While an input will usually only accept one connection from an output at any given time, NodeInput does support - * more than one. By default this is false, but can be set to true on any input object. If this is true, get_value() - * returns QList rather than just a QVariant (but casted to QVariant). - */ - bool can_accept_multiple_inputs(); - - /** - * @brief \see can_accept_multiple_inputs(). - */ - void set_can_accept_multiple_inputs(bool b); - /** * @brief Get the value at a given time * @@ -80,7 +66,7 @@ public: * If no output is connected, this will return a user-defined value, either a static value if this input is not * keyframed, or an interpolated value between the keyframes at this time. */ - QVariant get_value(); + QVariant get_value(const rational &time); /** * @brief Set the value at a given time @@ -123,15 +109,21 @@ private: */ QList keyframes_; + /** + * @brief Currently cached value + */ + QVariant value_; + + /** + * @brief Last timecode that a value was requested with + */ + rational time_; + /** * @brief Internal keyframing enabled setting */ bool keyframing_; - /** - * @brief Internal multiple inputs accepted setting - */ - bool can_accept_multiple_inputs_; }; #endif // NODEINPUT_H diff --git a/app/node/input/media/media.cpp b/app/node/input/media/media.cpp index cd517a8cd..03697e2cd 100644 --- a/app/node/input/media/media.cpp +++ b/app/node/input/media/media.cpp @@ -87,71 +87,82 @@ void MediaInput::SetFootage(Footage *f) footage_input_->set_value(PtrToValue(f)); } -void MediaInput::Process() +QVariant MediaInput::Value(NodeOutput *output, const rational &time) { - // Set default texture to no texture - texture_output_->set_value(0); + if (output == texture_output_) { + // Find the current Renderer instance + RenderInstance* renderer = RendererProcessor::CurrentInstance(); - // Find the current Renderer instance - RenderInstance* renderer = RendererProcessor::CurrentInstance(); + // If nothing is available, don't return a texture + if (renderer == nullptr) { + return 0; + } - // If nothing is available, don't return a texture - if (renderer == nullptr) { - return; - } + // Get currently selected Footage + Footage* footage = ValueToPtr(footage_input_->get_value(time)); - // Get currently selected Footage - Footage* footage = ValueToPtr(footage_input_->get_value()); + // If no footage is selected, return nothing + if (footage == nullptr) { + return 0; + } - // If no footage is selected, return nothing - if (footage == nullptr) { - return; - } + // Otherwise try to get frame of footage from decoder - // Otherwise try to get frame of footage from decoder + // Determine which decoder to use + if (decoder_ == nullptr + && (decoder_ = Decoder::CreateFromID(footage->decoder())) == nullptr) { + return 0; + } - // Determine which decoder to use - if (decoder_ == nullptr - && (decoder_ = Decoder::CreateFromID(footage->decoder())) == nullptr) { - return; - } + if (decoder_->stream() == nullptr) { + // FIXME: Hardcoded stream 0 + decoder_->set_stream(footage->stream(0)); + } - if (decoder_->stream() == nullptr) { - // FIXME: Hardcoded stream 0 - decoder_->set_stream(footage->stream(0)); - } + // Get frame from Decoder + FramePtr frame = decoder_->Retrieve(time); - // Get frame from Decoder - FramePtr frame = decoder_->Retrieve(time()); + if (frame == nullptr) { + return 0; + } - if (frame == nullptr) { - return; - } + RenderTexturePtr texture = std::make_shared(); - /*renderer->buffer()->Upload(frame->data()); - - texture_output_->set_value(renderer->buffer()->texture());*/ - - // Convert the frame to the Renderer format -// frame = PixelService::ConvertPixelFormat(frame, olive::PIX_FMT_RGBA16F); - - // Convert the frame to the Renderer color space - //color_service_.ConvertFrame(frame); - - // Upload this frame to the GPU - /*if (buffer_.IsCreated()) { - buffer_.Upload(frame->data()); - } else { - buffer_.Create(QOpenGLContext::currentContext(), + texture->Create(renderer->context(), + renderer->width(), + renderer->height(), static_cast(frame->format()), - frame->width(), - frame->height(), frame->data()); - }*/ - // Draw according to matrix - // BLIT + return QVariant::fromValue(texture); - //texture_output_->set_value(tex_buf_.texture()); - // End test code + /*renderer->buffer()->Upload(frame->data()); + + texture_output_->set_value(renderer->buffer()->texture());*/ + + // Convert the frame to the Renderer format + // frame = PixelService::ConvertPixelFormat(frame, olive::PIX_FMT_RGBA16F); + + // Convert the frame to the Renderer color space + //color_service_.ConvertFrame(frame); + + // Upload this frame to the GPU + /*if (buffer_.IsCreated()) { + buffer_.Upload(frame->data()); + } else { + buffer_.Create(QOpenGLContext::currentContext(), + static_cast(frame->format()), + frame->width(), + frame->height(), + frame->data()); + }*/ + + // Draw according to matrix + // BLIT + + //texture_output_->set_value(tex_buf_.texture()); + // End test code + } + + return 0; } diff --git a/app/node/input/media/media.h b/app/node/input/media/media.h index 1d89d26ec..08b5469cc 100644 --- a/app/node/input/media/media.h +++ b/app/node/input/media/media.h @@ -53,7 +53,7 @@ public: void SetFootage(Footage* f); protected: - virtual void Process() override; + virtual QVariant Value(NodeOutput* output, const rational& time) override; private: NodeInput* footage_input_; diff --git a/app/node/node.cpp b/app/node/node.cpp index d708e9007..ea0686014 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -25,7 +25,7 @@ #include "common/qobjectlistcast.h" Node::Node() : - last_process_time_(-1) + last_processed_time_(-1) { } @@ -90,18 +90,41 @@ void Node::IgnoreCacheInvalidationFrom(NodeInput *input) ignore_invalid_cache_inputs_.append(input); } -void Node::Run() +rational Node::LastProcessedTime() +{ + rational t; + + lock_.lock(); + + t = last_processed_time_; + + lock_.unlock(); + + return t; +} + +NodeOutput *Node::LastProcessedOutput() +{ + NodeOutput* o; + + lock_.lock(); + + o = last_processed_parameter_; + + lock_.unlock(); + + return o; +} + +QVariant Node::Run(NodeOutput* output, const rational& time) { lock_.lock(); - if (last_process_time_ != time_) { - // The results will be the same, so return here - Process(); - - last_process_time_ = time_; - } + QVariant v = Value(output, time); lock_.unlock(); + + return v; } NodeParam *Node::ParamAt(int index) @@ -205,28 +228,18 @@ QList Node::GetImmediateDependencies() return node_list; } -QList Node::GetImmediateDependenciesAt(const rational &time) +QList Node::RunDependencies(NodeOutput *output, const rational &time) { - Q_UNUSED(time) + Q_UNUSED(output) - return GetImmediateDependencies(); -} + QList immediate_deps = GetImmediateDependencies(); + QList run_deps; -const rational &Node::time() -{ - return time_; -} - -void Node::set_time(const rational &t) -{ - time_ = t; - - QList deps = GetImmediateDependencies(); - foreach (Node* d, deps) { - d->set_time(time_); + foreach (Node* dep, immediate_deps) { + run_deps.append(NodeDependency(dep, time)); } - emit TimeChanged(time_); + return run_deps; } bool Node::OutputsTo(Node *n) @@ -267,3 +280,19 @@ bool Node::HasParamWithID(const QString &id) return false; } + +NodeDependency::NodeDependency(Node *node, const rational &time) : + node_(node), + time_(time) +{ +} + +Node *NodeDependency::node() +{ + return node_; +} + +rational NodeDependency::time() +{ + return time_; +} diff --git a/app/node/node.h b/app/node/node.h index 49fa47b76..17c457fb8 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -28,6 +28,18 @@ #include "node/input.h" #include "node/output.h" +class NodeDependency { +public: + NodeDependency(Node* node, const rational& time); + + Node* node(); + rational time(); + +private: + Node* node_; + rational time_; +}; + /** * @brief A single processing unit that can be connected with others to create intricate processing systems * @@ -127,15 +139,19 @@ public: */ QList GetImmediateDependencies(); + /** + * @brief Thread-safe wrapper for Process() + * + * It's recommended to call this directly over Process(), yet in derivatives of Node, override Process(). + */ + QVariant Run(NodeOutput* output, const rational& time); + /** * @brief For nodes that have different dependencies at different times, this function can be used for that purpose * * Only retrieves immmediate dependencies, meaning only nodes that are directly */ - virtual QList GetImmediateDependenciesAt(const rational& time); - - const rational& time(); - virtual void set_time(const rational& t); + virtual QList RunDependencies(NodeOutput* output, const rational& time); /** * @brief Returns whether this Node outputs data to the Node `n` in any way @@ -199,13 +215,20 @@ protected: * corresponding output if it's connected to one. If your node doesn't directly deal with time, the default behavior * of the NodeParam objects will handle everything related to it automatically. */ - virtual void Process() = 0; + virtual QVariant Value(NodeOutput* output, const rational& time) = 0; + + /** + * @brief Retrieve the last timecode Process() was called with + */ + rational LastProcessedTime(); + + /** + * @brief Retrieve the last parameter Process() was called from + */ + NodeOutput* LastProcessedOutput(); public slots: - - void Run(); - signals: /** * @brief Signal emitted when a node is connected to another node (creating an "edge") @@ -225,11 +248,6 @@ signals: */ void EdgeRemoved(NodeEdgePtr edge); - /** - * @brief Signal emitted when the time is set through set_time() - */ - void TimeChanged(const rational& t); - private: /** * @brief Return whether a parameter with ID `id` has already been added to this Node @@ -241,9 +259,19 @@ private: */ QList ignore_invalid_cache_inputs_; - rational last_process_time_; - rational time_; + /** + * @brief The last timecode Process() was called with + */ + rational last_processed_time_; + /** + * @brief The last parameter Process() was called from + */ + NodeOutput* last_processed_parameter_; + + /** + * @brief Used for thread safety in Run() + */ QMutex lock_; }; diff --git a/app/node/output.cpp b/app/node/output.cpp index 5f4f217c3..5afd6cfb3 100644 --- a/app/node/output.cpp +++ b/app/node/output.cpp @@ -23,7 +23,8 @@ #include "node/node.h" NodeOutput::NodeOutput(const QString &id) : - NodeParam(id) + NodeParam(id), + time_(-1) { } @@ -47,16 +48,15 @@ void NodeOutput::set_data_type(const NodeParam::DataType &type) } } -const QVariant &NodeOutput::get_value() +const QVariant &NodeOutput::get_value(const rational& time) { - // Node::Process() should put the correct value in this output - parent()->Run(); + if (time_ != time) { + // Update the value + value_ = parent()->Run(this, time); + + time_ = time; + } // The value should be have been set by this point return value_; } - -void NodeOutput::set_value(const QVariant &value) -{ - value_ = value; -} diff --git a/app/node/output.h b/app/node/output.h index 59d4a4d51..a86559bcd 100644 --- a/app/node/output.h +++ b/app/node/output.h @@ -61,20 +61,14 @@ public: * In many cases for efficiency, the Node can also ignore this request if it knows the output data will not change * (i.e. if the time has not changed from the last Process()). */ - virtual const QVariant& get_value(); - - /** - * @brief Set the current value of this output - * - * Intended to only be set by parent Node objects in their Node::Process() function. Whatever result data is intended - * for use later in the pipeline should be set here (\see get_value()). - */ - virtual void set_value(const QVariant& value); + virtual const QVariant& get_value(const rational &time); private: DataType data_type_; QVariant value_; + + rational time_; }; #endif // NODEOUTPUT_H diff --git a/app/node/output/timeline/timeline.cpp b/app/node/output/timeline/timeline.cpp index 9cfa1f930..c4f365fb2 100644 --- a/app/node/output/timeline/timeline.cpp +++ b/app/node/output/timeline/timeline.cpp @@ -96,8 +96,12 @@ NodeInput *TimelineOutput::track_input() return track_input_; } -void TimelineOutput::Process() +QVariant TimelineOutput::Value(NodeOutput *output, const rational &time) { + Q_UNUSED(output) + Q_UNUSED(time) + + return 0; } int TimelineOutput::GetTrackIndex(TrackOutput *track) @@ -118,7 +122,7 @@ rational TimelineOutput::GetSequenceLength() TrackOutput *TimelineOutput::attached_track() { - return ValueToPtr(track_input_->get_value()); + return ValueToPtr(track_input_->get_value(0)); } void TimelineOutput::AttachTrack(TrackOutput *track) @@ -201,7 +205,7 @@ void TimelineOutput::TrackConnectionRemoved(NodeEdgePtr edge) return; } - DetachTrack(ValueToPtr(edge->output()->get_value())); + DetachTrack(ValueToPtr(edge->output()->get_value(0))); if (attached_timeline_ != nullptr) { attached_timeline_->Clear(); @@ -229,7 +233,7 @@ void TimelineOutput::TrackEdgeAdded(NodeEdgePtr edge) // If this edge pertains to the track's track input, all the tracks just added need attaching if (edge->input() == track->track_input()) { - TrackOutput* added_track = ValueToPtr(edge->output()->get_value()); + TrackOutput* added_track = ValueToPtr(edge->output()->get_value(0)); AttachTrack(added_track); } @@ -242,7 +246,7 @@ void TimelineOutput::TrackEdgeRemoved(NodeEdgePtr edge) // If this edge pertains to the track's track input, all the tracks just added need attaching if (edge->input() == track->track_input()) { - TrackOutput* added_track = ValueToPtr(edge->output()->get_value()); + TrackOutput* added_track = ValueToPtr(edge->output()->get_value(0)); DetachTrack(added_track); } diff --git a/app/node/output/timeline/timeline.h b/app/node/output/timeline/timeline.h index 4f9598ec3..15bcb9817 100644 --- a/app/node/output/timeline/timeline.h +++ b/app/node/output/timeline/timeline.h @@ -46,7 +46,7 @@ public: NodeInput* track_input(); protected: - virtual void Process() override; + virtual QVariant Value(NodeOutput* output, const rational& time) override; private: int GetTrackIndex(TrackOutput* track); diff --git a/app/node/output/track/track.cpp b/app/node/output/track/track.cpp index 02090a1b4..320244239 100644 --- a/app/node/output/track/track.cpp +++ b/app/node/output/track/track.cpp @@ -99,22 +99,19 @@ void TrackOutput::Refresh() Block::Refresh(); } -QList TrackOutput::GetImmediateDependenciesAt(const rational &time) +QList TrackOutput::RunDependencies(NodeOutput* output, const rational &time) { - QList nodes = Node::GetImmediateDependencies(); + QList deps; - ValidateCurrentBlock(time); + if (output == texture_output()) { + ValidateCurrentBlock(time); - // Swap attached block for current block at this time - nodes.removeAll(attached_block()); - if (current_block_ != this) { - nodes.append(current_block_); + if (current_block_ != this) { + deps.append(NodeDependency(current_block_, time)); + } } - // The next track is not a direct dependency (it would only become so through a merge node) - nodes.removeAll(next_track()); - - return nodes; + return deps; } void TrackOutput::GenerateBlockWidgets() @@ -133,7 +130,7 @@ void TrackOutput::DestroyBlockWidgets() TrackOutput *TrackOutput::next_track() { - return ValueToPtr(track_input_->get_value()); + return ValueToPtr(track_input_->get_value(0)); } NodeInput *TrackOutput::track_input() @@ -146,23 +143,27 @@ NodeOutput* TrackOutput::track_output() return track_output_; } -void TrackOutput::Process() +#include "render/rendertexture.h" + +QVariant TrackOutput::Value(NodeOutput *output, const rational &time) { - // Run default node processing - Block::Process(); + if (output == track_output_) { + // Set track output correctly + return PtrToValue(this); + } else if (output == texture_output()) { + ValidateCurrentBlock(time); - // Set track output correctly - track_output_->set_value(PtrToValue(this)); + if (current_block_ != this) { + // At this point, we must have found the correct block so we use its texture output to produce the image + return current_block_->texture_output()->get_value(time); + } - ValidateCurrentBlock(time()); - - if (current_block_ == this) { // No texture is valid - texture_output()->set_value(0); - } else { - // At this point, we must have found the correct block so we use its texture output to produce the image - texture_output()->set_value(current_block_->texture_output()->get_value()); + return 0; } + + // Run default node processing + return Block::Value(output, time); } void TrackOutput::InsertBlockBetweenBlocks(Block *block, Block *before, Block *after) @@ -181,7 +182,7 @@ void TrackOutput::InsertBlockAfter(Block *block, Block *before) Block *TrackOutput::attached_block() { - return ValueToPtr(previous_input()->get_value()); + return ValueToPtr(previous_input()->get_value(0)); } void TrackOutput::PrependBlock(Block *block) diff --git a/app/node/output/track/track.h b/app/node/output/track/track.h index 1482770fa..0cf583c23 100644 --- a/app/node/output/track/track.h +++ b/app/node/output/track/track.h @@ -49,7 +49,7 @@ public: /** * @brief Override swaps "attached block" with "current block" */ - virtual QList GetImmediateDependenciesAt(const rational& time) override; + virtual QList RunDependencies(NodeOutput* param, const rational& time) override; void GenerateBlockWidgets(); @@ -156,7 +156,7 @@ signals: void BlockRemoved(Block* block); protected: - virtual void Process() override; + virtual QVariant Value(NodeOutput* output, const rational& time) override; private: /** diff --git a/app/node/output/viewer/viewer.cpp b/app/node/output/viewer/viewer.cpp index d3b050be1..8199260d6 100644 --- a/app/node/output/viewer/viewer.cpp +++ b/app/node/output/viewer/viewer.cpp @@ -20,7 +20,7 @@ #include "viewer.h" -#include "panel/panelmanager.h" +#include "render/rendertexture.h" ViewerOutput::ViewerOutput() : attached_viewer_(nullptr) @@ -64,17 +64,6 @@ NodeInput *ViewerOutput::texture_input() return texture_input_; } -void ViewerOutput::Process() -{ - if (attached_viewer_ != nullptr) { - // Get the texture from whatever Node is currently connected (usually a Renderer of some kind) - GLuint current_texture = texture_input_->get_value().value(); - - // Send the texture to the Viewer - attached_viewer_->SetTexture(current_texture); - } -} - void ViewerOutput::AttachViewer(ViewerPanel *viewer) { // Disconnect old viewer if there's one attached @@ -94,14 +83,28 @@ void ViewerOutput::AttachViewer(ViewerPanel *viewer) void ViewerOutput::InvalidateCache(const rational &start_range, const rational &end_range) { // Update any attached viewer - Process(); + ViewerTimeChanged(current_time_); Node::InvalidateCache(start_range, end_range); } +QVariant ViewerOutput::Value(NodeOutput *output, const rational &time) +{ + Q_UNUSED(output) + Q_UNUSED(time) + + return 0; +} + void ViewerOutput::ViewerTimeChanged(const rational &t) { - set_time(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(); - Run(); + // Send the texture to the Viewer + if (current_texture != nullptr) { + attached_viewer_->SetTexture(current_texture->texture()); + } + + current_time_ = t; } diff --git a/app/node/output/viewer/viewer.h b/app/node/output/viewer/viewer.h index 44bef687e..ae4b8ddaf 100644 --- a/app/node/output/viewer/viewer.h +++ b/app/node/output/viewer/viewer.h @@ -47,17 +47,21 @@ public: void AttachViewer(ViewerPanel* viewer); virtual void InvalidateCache(const rational &start_range, const rational &end_range) override; -protected: - virtual void Process() override; +protected: + virtual QVariant Value(NodeOutput* output, const rational& time) override; private: + void UpdateViewer(); + NodeInput* texture_input_; ViewerPanel* attached_viewer_; rational timebase_; + rational current_time_; + private slots: void ViewerTimeChanged(const rational& t); diff --git a/app/node/param.cpp b/app/node/param.cpp index da1d53b92..810f0a6b3 100644 --- a/app/node/param.cpp +++ b/app/node/param.cpp @@ -182,7 +182,7 @@ void NodeParam::DisconnectEdge(NodeOutput *output, NodeInput *input) NodeEdgePtr NodeParam::DisconnectForNewOutput(NodeInput *input) { // If the input can only accept one input (the default) and has one already, disconnect it - if (!input->edges_.isEmpty() && !input->can_accept_multiple_inputs()) { + if (!input->edges_.isEmpty()) { NodeEdgePtr edge = input->edges_.first(); DisconnectEdge(edge); diff --git a/app/node/processor/renderer/renderer.cpp b/app/node/processor/renderer/renderer.cpp index 9bb112edc..545b934cf 100644 --- a/app/node/processor/renderer/renderer.cpp +++ b/app/node/processor/renderer/renderer.cpp @@ -73,24 +73,34 @@ void RendererProcessor::SetCacheName(const QString &s) GenerateCacheIDInternal(); } -void RendererProcessor::Process() +QVariant RendererProcessor::Value(NodeOutput* output, const rational& time) { - texture_output_->set_value(0); + if (output == texture_output_) { + if (!texture_input_->IsConnected()) { + // Nothing is connected - nothing to show or render + return 0; + } - if (!texture_input_->IsConnected()) { - // Nothing is connected - nothing to show or render - return; + if (cache_id_.isEmpty()) { + qWarning() << "RendererProcessor has no cache ID"; + return 0; + } + + if (timebase_.isNull()) { + qWarning() << "RendererProcessor has no timebase"; + return 0; + } + + // FIXME: Test code only + return texture_input_->get_value(time); + // End test code } - if (cache_id_.isEmpty()) { - qWarning() << "RendererProcessor has no cache ID"; - return; - } + return 0; + + + - if (timebase_.isNull()) { - qWarning() << "RendererProcessor has no timebase"; - return; - } // This Renderer node relies on a disk cache so this Process() function should be quite fast. Either it returns the // cached frame or it returns nothing. @@ -252,7 +262,7 @@ void RendererProcessor::CacheNext() Node* node_to_cache = texture_input_->edges().first()->output()->parent(); // Set graph time - node_to_cache->set_time(time_to_cache); + //node_to_cache->set_time(time_to_cache); // Run this probe in another thread RenderPath path = RendererProbe::ProbeNode(node_to_cache, threads_.size(), time_to_cache); diff --git a/app/node/processor/renderer/renderer.h b/app/node/processor/renderer/renderer.h index ac56d4ea4..650e4b896 100644 --- a/app/node/processor/renderer/renderer.h +++ b/app/node/processor/renderer/renderer.h @@ -94,7 +94,7 @@ public: NodeOutput* texture_output(); protected: - virtual void Process() override; + virtual QVariant Value(NodeOutput* output, const rational& time) override; private: /** diff --git a/app/node/processor/renderer/rendererprobe.cpp b/app/node/processor/renderer/rendererprobe.cpp index fda34767c..f7e2651f2 100644 --- a/app/node/processor/renderer/rendererprobe.cpp +++ b/app/node/processor/renderer/rendererprobe.cpp @@ -42,7 +42,12 @@ RenderPath RendererProbe::ProbeNode(Node *node, int thread_count, const rational void RendererProbe::TraverseNode(RenderPath& path, Node *node, const rational& time, int thread, int index) { - bool can_take_node = true; + Q_UNUSED(path) + Q_UNUSED(node) + Q_UNUSED(time) + Q_UNUSED(thread) + Q_UNUSED(index) + /*bool can_take_node = true; if (path.ContainsNode(node) >= 0) { if (path.NodeIndex(node) < index) { @@ -61,7 +66,7 @@ void RendererProbe::TraverseNode(RenderPath& path, Node *node, const rational& t path.AddEntry(node, thread, index); } - QList deps = node->GetImmediateDependenciesAt(time); + QList deps = node->RunDependencies(nullptr, time); // Print debugging information foreach (Node* dep, deps) { @@ -77,5 +82,5 @@ void RendererProbe::TraverseNode(RenderPath& path, Node *node, const rational& t int run_thread = (ideal_thread == -1) ? thread : ideal_thread; TraverseNode(path, dep, time, run_thread, next_index); - } + }*/ } diff --git a/app/node/processor/renderer/rendererthread.cpp b/app/node/processor/renderer/rendererthread.cpp index 21654dedb..ef1686174 100644 --- a/app/node/processor/renderer/rendererthread.cpp +++ b/app/node/processor/renderer/rendererthread.cpp @@ -97,9 +97,9 @@ void RendererThread::run() caller_mutex_.unlock(); // Process the Node - for (int i=path_.size()-1;i>=0;i--) { + /*for (int i=path_.size()-1;i>=0;i--) { path_.at(i)->Run(); - } + }*/ emit FinishedPath(); }