shifted to new dependency structure
This commit is contained in:
@@ -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<GLuint>();
|
||||
|
||||
// FIXME: Does nothing
|
||||
texture_output()->set_value(QVariant::fromValue(blend_input()->get_value().value<RenderTexturePtr>()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+15
-11
@@ -70,7 +70,7 @@ void Block::set_length(const rational &length)
|
||||
|
||||
Block *Block::previous()
|
||||
{
|
||||
return ValueToPtr<Block>(previous_input_->get_value());
|
||||
return ValueToPtr<Block>(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<Node *> Block::GetImmediateDependenciesAt(const rational &time)
|
||||
QList<NodeDependency> Block::RunDependencies(NodeOutput* param, const rational &time)
|
||||
{
|
||||
// Base Blocks have no direct dependencies
|
||||
|
||||
Q_UNUSED(param)
|
||||
Q_UNUSED(time)
|
||||
|
||||
QList<Node *> nodes = Node::GetImmediateDependencies();
|
||||
|
||||
// Swap attached block for current block at this time
|
||||
nodes.removeAll(previous());
|
||||
|
||||
return nodes;
|
||||
return QList<NodeDependency>();
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public:
|
||||
/**
|
||||
* @brief Override removes previous input as that is not a direct dependency
|
||||
*/
|
||||
virtual QList<Node *> GetImmediateDependenciesAt(const rational &time) override;
|
||||
virtual QList<NodeDependency> 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_;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
|
||||
+14
-17
@@ -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)
|
||||
|
||||
+11
-19
@@ -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<QVariant> 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<NodeKeyframe> 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
|
||||
|
||||
@@ -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>(footage_input_->get_value(time));
|
||||
|
||||
// Get currently selected Footage
|
||||
Footage* footage = ValueToPtr<Footage>(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<RenderTexture>();
|
||||
|
||||
/*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<olive::PixelFormat>(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<olive::PixelFormat>(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;
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
|
||||
+54
-25
@@ -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 *> Node::GetImmediateDependencies()
|
||||
return node_list;
|
||||
}
|
||||
|
||||
QList<Node *> Node::GetImmediateDependenciesAt(const rational &time)
|
||||
QList<NodeDependency> Node::RunDependencies(NodeOutput *output, const rational &time)
|
||||
{
|
||||
Q_UNUSED(time)
|
||||
Q_UNUSED(output)
|
||||
|
||||
return GetImmediateDependencies();
|
||||
}
|
||||
QList<Node*> immediate_deps = GetImmediateDependencies();
|
||||
QList<NodeDependency> run_deps;
|
||||
|
||||
const rational &Node::time()
|
||||
{
|
||||
return time_;
|
||||
}
|
||||
|
||||
void Node::set_time(const rational &t)
|
||||
{
|
||||
time_ = t;
|
||||
|
||||
QList<Node*> 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_;
|
||||
}
|
||||
|
||||
+43
-15
@@ -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<Node*> 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<Node*> GetImmediateDependenciesAt(const rational& time);
|
||||
|
||||
const rational& time();
|
||||
virtual void set_time(const rational& t);
|
||||
virtual QList<NodeDependency> 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<NodeInput*> 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_;
|
||||
};
|
||||
|
||||
|
||||
+9
-9
@@ -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;
|
||||
}
|
||||
|
||||
+3
-9
@@ -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
|
||||
|
||||
@@ -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<TrackOutput>(track_input_->get_value());
|
||||
return ValueToPtr<TrackOutput>(track_input_->get_value(0));
|
||||
}
|
||||
|
||||
void TimelineOutput::AttachTrack(TrackOutput *track)
|
||||
@@ -201,7 +205,7 @@ void TimelineOutput::TrackConnectionRemoved(NodeEdgePtr edge)
|
||||
return;
|
||||
}
|
||||
|
||||
DetachTrack(ValueToPtr<TrackOutput>(edge->output()->get_value()));
|
||||
DetachTrack(ValueToPtr<TrackOutput>(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<TrackOutput>(edge->output()->get_value());
|
||||
TrackOutput* added_track = ValueToPtr<TrackOutput>(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<TrackOutput>(edge->output()->get_value());
|
||||
TrackOutput* added_track = ValueToPtr<TrackOutput>(edge->output()->get_value(0));
|
||||
|
||||
DetachTrack(added_track);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -99,22 +99,19 @@ void TrackOutput::Refresh()
|
||||
Block::Refresh();
|
||||
}
|
||||
|
||||
QList<Node *> TrackOutput::GetImmediateDependenciesAt(const rational &time)
|
||||
QList<NodeDependency> TrackOutput::RunDependencies(NodeOutput* output, const rational &time)
|
||||
{
|
||||
QList<Node *> nodes = Node::GetImmediateDependencies();
|
||||
QList<NodeDependency> 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<TrackOutput>(track_input_->get_value());
|
||||
return ValueToPtr<TrackOutput>(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<Block>(previous_input()->get_value());
|
||||
return ValueToPtr<Block>(previous_input()->get_value(0));
|
||||
}
|
||||
|
||||
void TrackOutput::PrependBlock(Block *block)
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
/**
|
||||
* @brief Override swaps "attached block" with "current block"
|
||||
*/
|
||||
virtual QList<Node*> GetImmediateDependenciesAt(const rational& time) override;
|
||||
virtual QList<NodeDependency> 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:
|
||||
/**
|
||||
|
||||
@@ -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<GLuint>();
|
||||
|
||||
// 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<RenderTexturePtr>();
|
||||
|
||||
Run();
|
||||
// Send the texture to the Viewer
|
||||
if (current_texture != nullptr) {
|
||||
attached_viewer_->SetTexture(current_texture->texture());
|
||||
}
|
||||
|
||||
current_time_ = t;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
NodeOutput* texture_output();
|
||||
|
||||
protected:
|
||||
virtual void Process() override;
|
||||
virtual QVariant Value(NodeOutput* output, const rational& time) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
||||
@@ -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<Node*> deps = node->GetImmediateDependenciesAt(time);
|
||||
QList<Node*> 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);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user