From bc0f01d9a36f1993820cf28d82d18b00469759a8 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 4 Dec 2019 20:10:42 +1100 Subject: [PATCH] make nodes more const friendly and prepare their functions for stateless work Since the nodes won't be holding any rendering data themselves in this system, we may as well enforce some level of non-write access by setting all the functions to const. They were already const-friendly, they just weren't labelled as such. --- app/node/blend/alphaover/alphaover.cpp | 10 +- app/node/blend/alphaover/alphaover.h | 10 +- app/node/blend/blend.cpp | 8 +- app/node/blend/blend.h | 8 +- app/node/block/block.cpp | 34 ++--- app/node/block/block.h | 28 ++--- app/node/block/clip/clip.cpp | 23 ++-- app/node/block/clip/clip.h | 16 +-- app/node/block/gap/gap.cpp | 10 +- app/node/block/gap/gap.h | 10 +- app/node/color/opacity/opacity.cpp | 16 +-- app/node/color/opacity/opacity.h | 16 +-- app/node/distort/transform/transform.cpp | 41 +++--- app/node/distort/transform/transform.h | 12 +- app/node/generator/solid/solid.cpp | 14 +-- app/node/generator/solid/solid.h | 14 +-- app/node/input/media/audio/audio.cpp | 19 ++- app/node/input/media/audio/audio.h | 12 +- app/node/input/media/video/video.cpp | 16 +-- app/node/input/media/video/video.h | 16 +-- app/node/node.cpp | 68 ++++------ app/node/node.h | 61 ++++----- app/node/output/timeline/timeline.cpp | 54 ++++---- app/node/output/timeline/timeline.h | 26 ++-- app/node/output/track/track.cpp | 43 +++---- app/node/output/track/track.h | 25 ++-- app/node/output/viewer/viewer.cpp | 13 +- app/node/output/viewer/viewer.h | 10 +- app/node/value.cpp | 153 +++++++++++++++++++++++ app/node/value.h | 65 ++++++++++ 30 files changed, 505 insertions(+), 346 deletions(-) create mode 100644 app/node/value.cpp create mode 100644 app/node/value.h diff --git a/app/node/blend/alphaover/alphaover.cpp b/app/node/blend/alphaover/alphaover.cpp index 69b429648..4956cd189 100644 --- a/app/node/blend/alphaover/alphaover.cpp +++ b/app/node/blend/alphaover/alphaover.cpp @@ -25,27 +25,27 @@ AlphaOverBlend::AlphaOverBlend() } -Node *AlphaOverBlend::copy() +Node *AlphaOverBlend::copy() const { return new AlphaOverBlend(); } -QString AlphaOverBlend::Name() +QString AlphaOverBlend::Name() const { return tr("Alpha Over"); } -QString AlphaOverBlend::id() +QString AlphaOverBlend::id() const { return "org.olivevideoeditor.Olive.alphaoverblend"; } -QString AlphaOverBlend::Description() +QString AlphaOverBlend::Description() const { return tr("A blending node that composites one texture over another using its alpha channel."); } -QString AlphaOverBlend::Code(NodeOutput *output) +QString AlphaOverBlend::Code(NodeOutput *output) const { if (output == texture_output()) { return "#version 110" diff --git a/app/node/blend/alphaover/alphaover.h b/app/node/blend/alphaover/alphaover.h index 77b81aac7..a6fb0af27 100644 --- a/app/node/blend/alphaover/alphaover.h +++ b/app/node/blend/alphaover/alphaover.h @@ -28,13 +28,13 @@ class AlphaOverBlend : public BlendNode public: AlphaOverBlend(); - virtual Node* copy() override; + virtual Node* copy() const override; - virtual QString Name() override; - virtual QString id() override; - virtual QString Description() override; + virtual QString Name() const override; + virtual QString id() const override; + virtual QString Description() const override; - virtual QString Code(NodeOutput* output) override; + virtual QString Code(NodeOutput* output) const override; protected: diff --git a/app/node/blend/blend.cpp b/app/node/blend/blend.cpp index cbd279e8e..7f06eb196 100644 --- a/app/node/blend/blend.cpp +++ b/app/node/blend/blend.cpp @@ -34,22 +34,22 @@ BlendNode::BlendNode() AddParameter(texture_output_); } -QString BlendNode::Category() +QString BlendNode::Category() const { return tr("Blend"); } -NodeInput *BlendNode::base_input() +NodeInput *BlendNode::base_input() const { return base_input_; } -NodeInput *BlendNode::blend_input() +NodeInput *BlendNode::blend_input() const { return blend_input_; } -NodeOutput *BlendNode::texture_output() +NodeOutput *BlendNode::texture_output() const { return texture_output_; } diff --git a/app/node/blend/blend.h b/app/node/blend/blend.h index 9f4e1ba96..bd65f9310 100644 --- a/app/node/blend/blend.h +++ b/app/node/blend/blend.h @@ -28,13 +28,13 @@ class BlendNode : public Node public: BlendNode(); - virtual QString Category() override; + virtual QString Category() const override; - NodeInput* base_input(); + NodeInput* base_input() const; - NodeInput* blend_input(); + NodeInput* blend_input() const; - NodeOutput* texture_output(); + NodeOutput* texture_output() const; private: NodeInput* base_input_; diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp index 989c8b037..90718dd8b 100644 --- a/app/node/block/block.cpp +++ b/app/node/block/block.cpp @@ -33,17 +33,17 @@ Block::Block() : AddParameter(buffer_output_); } -QString Block::Category() +QString Block::Category() const { return tr("Block"); } -const rational &Block::in() +const rational &Block::in() const { return in_point_; } -const rational &Block::out() +const rational &Block::out() const { return out_point_; } @@ -58,7 +58,7 @@ void Block::set_out(const rational &out) out_point_ = out; } -const rational& Block::length() +const rational& Block::length() const { return length_; } @@ -109,27 +109,17 @@ void Block::set_next(Block *next) next_ = next; } -QVariant Block::Value(NodeOutput *output) -{ - if (output == block_output_) { - // Simply set the output value to a pointer to this Block - return PtrToValue(this); - } - - return 0; -} - -NodeOutput *Block::buffer_output() +NodeOutput *Block::buffer_output() const { return buffer_output_; } -NodeOutput *Block::block_output() +NodeOutput *Block::block_output() const { return block_output_; } -const rational &Block::media_in() +const rational &Block::media_in() const { return media_in_; } @@ -151,7 +141,7 @@ void Block::set_media_in(const rational &media_in) } } -const QString &Block::block_name() +const QString &Block::block_name() const { return block_name_; } @@ -161,7 +151,7 @@ void Block::set_block_name(const QString &name) block_name_ = name; } -rational Block::SequenceToMediaTime(const rational &sequence_time) +rational Block::SequenceToMediaTime(const rational &sequence_time) const { // These constants are not considered "values" per se, so we don't modify them if (sequence_time == RATIONAL_MIN || sequence_time == RATIONAL_MAX) { @@ -171,7 +161,7 @@ rational Block::SequenceToMediaTime(const rational &sequence_time) return sequence_time - in() + media_in(); } -rational Block::MediaToSequenceTime(const rational &media_time) +rational Block::MediaToSequenceTime(const rational &media_time) const { // These constants are not considered "values" per se, so we don't modify them if (media_time == RATIONAL_MIN || media_time == RATIONAL_MAX) { @@ -181,7 +171,7 @@ rational Block::MediaToSequenceTime(const rational &media_time) return media_time - media_in() + in(); } -void Block::CopyParameters(Block *source, Block *dest) +void Block::CopyParameters(const Block *source, Block *dest) { dest->set_block_name(source->block_name()); dest->set_length(source->length()); @@ -233,7 +223,7 @@ bool Block::HasLinks() return !linked_clips_.isEmpty(); } -bool Block::IsBlock() +bool Block::IsBlock() const { return true; } diff --git a/app/node/block/block.h b/app/node/block/block.h index 5451ee947..c52ff5cc7 100644 --- a/app/node/block/block.h +++ b/app/node/block/block.h @@ -45,16 +45,16 @@ public: kTrack }; - virtual Type type() = 0; + virtual Type type() const = 0; - virtual QString Category() override; + virtual QString Category() const override; - const rational& in(); - const rational& out(); + const rational& in() const; + const rational& out() const; void set_in(const rational& in); void set_out(const rational& out); - const rational &length(); + const rational &length() const; void set_length(const rational &length); void set_length_and_media_in(const rational &length); @@ -63,13 +63,13 @@ public: void set_previous(Block* previous); void set_next(Block* next); - NodeOutput* buffer_output(); - NodeOutput* block_output(); + NodeOutput* buffer_output() const; + NodeOutput* block_output() const; - const rational& media_in(); + const rational& media_in() const; void set_media_in(const rational& media_in); - const QString& block_name(); + const QString& block_name() const; void set_block_name(const QString& name); static void Link(Block* a, Block* b); @@ -79,9 +79,7 @@ public: const QVector& linked_clips(); bool HasLinks(); - virtual bool IsBlock() override; - - virtual QVariant Value(NodeOutput* output) override; + virtual bool IsBlock() const override; public slots: @@ -96,11 +94,11 @@ signals: void LengthChanged(const rational& length); protected: - rational SequenceToMediaTime(const rational& sequence_time); + rational SequenceToMediaTime(const rational& sequence_time) const; - rational MediaToSequenceTime(const rational& media_time); + rational MediaToSequenceTime(const rational& media_time) const; - static void CopyParameters(Block* source, Block* dest); + static void CopyParameters(const Block *source, Block* dest); Block* previous_; Block* next_; diff --git a/app/node/block/clip/clip.cpp b/app/node/block/clip/clip.cpp index d3b8d0db9..7d9541bf8 100644 --- a/app/node/block/clip/clip.cpp +++ b/app/node/block/clip/clip.cpp @@ -27,7 +27,7 @@ ClipBlock::ClipBlock() AddParameter(texture_input_); } -Node *ClipBlock::copy() +Node *ClipBlock::copy() const { ClipBlock* c = new ClipBlock(); @@ -36,27 +36,27 @@ Node *ClipBlock::copy() return c; } -Block::Type ClipBlock::type() +Block::Type ClipBlock::type() const { return kClip; } -QString ClipBlock::Name() +QString ClipBlock::Name() const { return tr("Clip"); } -QString ClipBlock::id() +QString ClipBlock::id() const { return "org.olivevideoeditor.Olive.clip"; } -QString ClipBlock::Description() +QString ClipBlock::Description() const { return tr("A time-based node that represents a media source."); } -NodeInput *ClipBlock::texture_input() +NodeInput *ClipBlock::texture_input() const { return texture_input_; } @@ -79,7 +79,7 @@ void ClipBlock::InvalidateCache(const rational &start_range, const rational &end } } -TimeRange ClipBlock::InputTimeAdjustment(NodeInput *input, const TimeRange &input_time) +TimeRange ClipBlock::InputTimeAdjustment(NodeInput *input, const TimeRange &input_time) const { if (input == texture_input_) { return TimeRange(SequenceToMediaTime(input_time.in()), SequenceToMediaTime(input_time.out())); @@ -88,11 +88,8 @@ TimeRange ClipBlock::InputTimeAdjustment(NodeInput *input, const TimeRange &inpu return Block::InputTimeAdjustment(input, input_time); } -QVariant ClipBlock::Value(NodeOutput *output) +NodeValueTable ClipBlock::Value(const NodeValueDatabase &value) const { - if (output == buffer_output()) { - // We just pass through the texture here, the renderer should have gotten the correct time from InputTimeAdjustment - return texture_input()->value(); - } - return Block::Value(output); + // We just pass through the data here, the renderer should have gotten the correct time from InputTimeAdjustment + return value.Merge(); } diff --git a/app/node/block/clip/clip.h b/app/node/block/clip/clip.h index 908ce8017..c1fb3c440 100644 --- a/app/node/block/clip/clip.h +++ b/app/node/block/clip/clip.h @@ -32,21 +32,21 @@ class ClipBlock : public Block public: ClipBlock(); - virtual Node* copy() override; + virtual Node* copy() const override; - virtual Type type() override; + virtual Type type() const override; - virtual QString Name() override; - virtual QString id() override; - virtual QString Description() override; + virtual QString Name() const override; + virtual QString id() const override; + virtual QString Description() const override; - NodeInput* texture_input(); + NodeInput* texture_input() const; virtual void InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from = nullptr) override; - virtual TimeRange InputTimeAdjustment(NodeInput* input, const TimeRange& input_time) override; + virtual TimeRange InputTimeAdjustment(NodeInput* input, const TimeRange& input_time) const override; - virtual QVariant Value(NodeOutput* output) override; + virtual NodeValueTable Value(const NodeValueDatabase& value) const override; private: NodeInput* texture_input_; diff --git a/app/node/block/gap/gap.cpp b/app/node/block/gap/gap.cpp index c6c17a3e8..0b625ffdc 100644 --- a/app/node/block/gap/gap.cpp +++ b/app/node/block/gap/gap.cpp @@ -24,7 +24,7 @@ GapBlock::GapBlock() { } -Node *GapBlock::copy() +Node *GapBlock::copy() const { GapBlock* c = new GapBlock(); @@ -33,22 +33,22 @@ Node *GapBlock::copy() return c; } -Block::Type GapBlock::type() +Block::Type GapBlock::type() const { return kGap; } -QString GapBlock::Name() +QString GapBlock::Name() const { return tr("Gap"); } -QString GapBlock::id() +QString GapBlock::id() const { return "org.olivevideoeditor.Olive.gap"; } -QString GapBlock::Description() +QString GapBlock::Description() const { return tr("A time-based node that represents an empty space."); } diff --git a/app/node/block/gap/gap.h b/app/node/block/gap/gap.h index ceede3ceb..c98f415e9 100644 --- a/app/node/block/gap/gap.h +++ b/app/node/block/gap/gap.h @@ -32,13 +32,13 @@ class GapBlock : public Block public: GapBlock(); - virtual Node * copy() override; + virtual Node * copy() const override; - virtual Type type() override; + virtual Type type() const override; - virtual QString Name() override; - virtual QString id() override; - virtual QString Description() override; + virtual QString Name() const override; + virtual QString id() const override; + virtual QString Description() const override; private: diff --git a/app/node/color/opacity/opacity.cpp b/app/node/color/opacity/opacity.cpp index 25f4bb7c1..33400fd3b 100644 --- a/app/node/color/opacity/opacity.cpp +++ b/app/node/color/opacity/opacity.cpp @@ -37,27 +37,27 @@ OpacityNode::OpacityNode() AddParameter(texture_output_); } -Node *OpacityNode::copy() +Node *OpacityNode::copy() const { return new OpacityNode(); } -QString OpacityNode::Name() +QString OpacityNode::Name() const { return tr("Opacity"); } -QString OpacityNode::Category() +QString OpacityNode::Category() const { return tr("Color"); } -QString OpacityNode::Description() +QString OpacityNode::Description() const { return tr("Adjust an image's opacity."); } -QString OpacityNode::id() +QString OpacityNode::id() const { return "org.olivevideoeditor.Olive.opacity"; } @@ -67,7 +67,7 @@ void OpacityNode::Retranslate() opacity_input_->set_name(tr("Opacity")); } -QString OpacityNode::Code(NodeOutput *output) +QString OpacityNode::Code(NodeOutput *output) const { if (output == texture_output()) { return "#version 110" @@ -85,12 +85,12 @@ QString OpacityNode::Code(NodeOutput *output) return Node::Code(output); } -NodeInput *OpacityNode::texture_input() +NodeInput *OpacityNode::texture_input() const { return texture_input_; } -NodeOutput *OpacityNode::texture_output() +NodeOutput *OpacityNode::texture_output() const { return texture_output_; } diff --git a/app/node/color/opacity/opacity.h b/app/node/color/opacity/opacity.h index 9570372e9..12587e629 100644 --- a/app/node/color/opacity/opacity.h +++ b/app/node/color/opacity/opacity.h @@ -29,21 +29,21 @@ class OpacityNode : public Node public: OpacityNode(); - virtual Node* copy() override; + virtual Node* copy() const override; - virtual QString Name() override; - virtual QString Category() override; - virtual QString Description() override; + virtual QString Name() const override; + virtual QString Category() const override; + virtual QString Description() const override; - virtual QString id() override; + virtual QString id() const override; virtual void Retranslate() override; - virtual QString Code(NodeOutput* output) override; + virtual QString Code(NodeOutput* output) const override; - NodeInput* texture_input(); + NodeInput* texture_input() const; - NodeOutput* texture_output(); + NodeOutput* texture_output() const; private: NodeInput* opacity_input_; diff --git a/app/node/distort/transform/transform.cpp b/app/node/distort/transform/transform.cpp index 1b5078587..7af53fc2e 100644 --- a/app/node/distort/transform/transform.cpp +++ b/app/node/distort/transform/transform.cpp @@ -46,27 +46,27 @@ TransformDistort::TransformDistort() AddParameter(matrix_output_); } -Node *TransformDistort::copy() +Node *TransformDistort::copy() const { return new TransformDistort(); } -QString TransformDistort::Name() +QString TransformDistort::Name() const { return tr("Transform"); } -QString TransformDistort::id() +QString TransformDistort::id() const { return "org.olivevideoeditor.Olive.transform"; } -QString TransformDistort::Category() +QString TransformDistort::Category() const { return tr("Distort"); } -QString TransformDistort::Description() +QString TransformDistort::Description() const { return tr("Apply transformations to position, rotation, and scale."); } @@ -84,26 +84,25 @@ void TransformDistort::Retranslate() anchor_input_->set_name(tr("Anchor Point")); } -QVariant TransformDistort::Value(NodeOutput *output) +NodeValueTable TransformDistort::Value(const NodeValueDatabase &value) const { - if (output == matrix_output_) { - QMatrix4x4 mat; + QMatrix4x4 mat; - // Position translate - QVector2D pos = position_input_->value().value(); - mat.translate(pos); + // Position translate + QVector2D pos = value[position_input_].Get(NodeParam::kVec2).value(); + mat.translate(pos); - // Rotation - mat.rotate(rotation_input_->value().toFloat(), 0, 0, 1); + // Rotation + mat.rotate(value[rotation_input_].Get(NodeParam::kFloat).toFloat(), 0, 0, 1); - // Scale - mat.scale(scale_input_->value().value()*0.01f); + // Scale + mat.scale(value[scale_input_].Get(NodeParam::kVec2).value()*0.01f); - // Anchor Point - mat.translate(-anchor_input_->value().value()); + // Anchor Point + mat.translate(-value[anchor_input_].Get(NodeParam::kVec2).value()); - return mat; - } - - return 0; + // Push matrix output + NodeValueTable output = value.Merge(); + output.Push(NodeParam::kMatrix, mat); + return output; } diff --git a/app/node/distort/transform/transform.h b/app/node/distort/transform/transform.h index 988cd6233..ea9e30cd2 100644 --- a/app/node/distort/transform/transform.h +++ b/app/node/distort/transform/transform.h @@ -29,18 +29,18 @@ class TransformDistort : public Node public: TransformDistort(); - virtual Node* copy() override; + virtual Node* copy() const override; - virtual QString Name() override; - virtual QString id() override; - virtual QString Category() override; - virtual QString Description() override; + virtual QString Name() const override; + virtual QString id() const override; + virtual QString Category() const override; + virtual QString Description() const override; NodeOutput* matrix_output(); virtual void Retranslate() override; - virtual QVariant Value(NodeOutput *output) override; + virtual NodeValueTable Value(const NodeValueDatabase& value) const override; private: NodeInput* position_input_; diff --git a/app/node/generator/solid/solid.cpp b/app/node/generator/solid/solid.cpp index 643ab36d7..8352cc7b6 100644 --- a/app/node/generator/solid/solid.cpp +++ b/app/node/generator/solid/solid.cpp @@ -31,37 +31,37 @@ SolidGenerator::SolidGenerator() : AddParameter(texture_output_); } -Node *SolidGenerator::copy() +Node *SolidGenerator::copy() const { return new SolidGenerator(); } -QString SolidGenerator::Name() +QString SolidGenerator::Name() const { return tr("Solid"); } -QString SolidGenerator::id() +QString SolidGenerator::id() const { return "org.olivevideoeditor.Olive.solidgenerator"; } -QString SolidGenerator::Category() +QString SolidGenerator::Category() const { return tr("Generator"); } -QString SolidGenerator::Description() +QString SolidGenerator::Description() const { return tr("Generate a solid color."); } -NodeOutput *SolidGenerator::texture_output() +NodeOutput *SolidGenerator::texture_output() const { return texture_output_; } -QString SolidGenerator::Code(NodeOutput *output) +QString SolidGenerator::Code(NodeOutput *output) const { if (output == texture_output()) { // FIXME: Not color managed diff --git a/app/node/generator/solid/solid.h b/app/node/generator/solid/solid.h index b8d76af45..bc31cad2d 100644 --- a/app/node/generator/solid/solid.h +++ b/app/node/generator/solid/solid.h @@ -34,16 +34,16 @@ class SolidGenerator : public Node public: SolidGenerator(); - virtual Node* copy() override; + virtual Node* copy() const override; - virtual QString Name() override; - virtual QString id() override; - virtual QString Category() override; - virtual QString Description() override; + virtual QString Name() const override; + virtual QString id() const override; + virtual QString Category() const override; + virtual QString Description() const override; - NodeOutput* texture_output(); + NodeOutput* texture_output() const; - virtual QString Code(NodeOutput* output) override; + virtual QString Code(NodeOutput* output) const override; private: NodeInput* color_input_; diff --git a/app/node/input/media/audio/audio.cpp b/app/node/input/media/audio/audio.cpp index 9dcddb700..5b9b5e4f0 100644 --- a/app/node/input/media/audio/audio.cpp +++ b/app/node/input/media/audio/audio.cpp @@ -6,27 +6,27 @@ AudioInput::AudioInput() AddParameter(samples_output_); } -Node *AudioInput::copy() +Node *AudioInput::copy() const { return new AudioInput(); } -QString AudioInput::Name() +QString AudioInput::Name() const { return tr("Audio Input"); } -QString AudioInput::id() +QString AudioInput::id() const { return "org.olivevideoeditor.Olive.audioinput"; } -QString AudioInput::Category() +QString AudioInput::Category() const { return tr("Input"); } -QString AudioInput::Description() +QString AudioInput::Description() const { return tr("Import an audio footage stream."); } @@ -36,12 +36,7 @@ NodeOutput *AudioInput::samples_output() return samples_output_; } -QVariant AudioInput::Value(NodeOutput *output) +NodeValueTable AudioInput::Value(const NodeValueDatabase &value) const { - if (output == samples_output_) { - // Simple passthrough from footage input - return footage_input_->value(); - } - - return MediaInput::Value(output); + return value[footage_input_]; } diff --git a/app/node/input/media/audio/audio.h b/app/node/input/media/audio/audio.h index f8ae6a15d..646dc2b48 100644 --- a/app/node/input/media/audio/audio.h +++ b/app/node/input/media/audio/audio.h @@ -8,17 +8,17 @@ class AudioInput : public MediaInput public: AudioInput(); - virtual Node* copy() override; + virtual Node* copy() const override; - virtual QString Name() override; - virtual QString id() override; - virtual QString Category() override; - virtual QString Description() override; + virtual QString Name() const override; + virtual QString id() const override; + virtual QString Category() const override; + virtual QString Description() const override; NodeOutput* samples_output(); protected: - virtual QVariant Value(NodeOutput* output) override; + virtual NodeValueTable Value(const NodeValueDatabase& value) const override; private: NodeOutput* samples_output_; diff --git a/app/node/input/media/video/video.cpp b/app/node/input/media/video/video.cpp index a6ccb6f16..5e2483a71 100644 --- a/app/node/input/media/video/video.cpp +++ b/app/node/input/media/video/video.cpp @@ -18,27 +18,27 @@ VideoInput::VideoInput() AddParameter(texture_output_); } -Node *VideoInput::copy() +Node *VideoInput::copy() const { return new VideoInput(); } -QString VideoInput::Name() +QString VideoInput::Name() const { return tr("Video Input"); } -QString VideoInput::id() +QString VideoInput::id() const { return "org.olivevideoeditor.Olive.videoinput"; } -QString VideoInput::Category() +QString VideoInput::Category() const { return tr("Input"); } -QString VideoInput::Description() +QString VideoInput::Description() const { return tr("Import a video footage stream."); } @@ -48,17 +48,17 @@ void VideoInput::Release() MediaInput::Release(); } -NodeInput *VideoInput::matrix_input() +NodeInput *VideoInput::matrix_input() const { return matrix_input_; } -NodeOutput *VideoInput::texture_output() +NodeOutput *VideoInput::texture_output() const { return texture_output_; } -QString VideoInput::Code(NodeOutput *output) +QString VideoInput::Code(NodeOutput *output) const { if (output == texture_output()) { return "#version 110\n" diff --git a/app/node/input/media/video/video.h b/app/node/input/media/video/video.h index d722454a4..0a5589feb 100644 --- a/app/node/input/media/video/video.h +++ b/app/node/input/media/video/video.h @@ -11,20 +11,20 @@ class VideoInput : public MediaInput public: VideoInput(); - virtual Node* copy() override; + virtual Node* copy() const override; - virtual QString Name() override; - virtual QString id() override; - virtual QString Category() override; - virtual QString Description() override; + virtual QString Name() const override; + virtual QString id() const override; + virtual QString Category() const override; + virtual QString Description() const override; virtual void Release() override; - NodeInput* matrix_input(); + NodeInput* matrix_input() const; - NodeOutput* texture_output(); + NodeOutput* texture_output() const; - virtual QString Code(NodeOutput* output) override; + virtual QString Code(NodeOutput* output) const override; //virtual void Hash(QCryptographicHash *hash, NodeOutput* from, const rational &time) override; diff --git a/app/node/node.cpp b/app/node/node.cpp index 3732adc50..13d9a7ebe 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -45,13 +45,13 @@ Node::~Node() } } -QString Node::Category() +QString Node::Category() const { // Return an empty category for any nodes that don't use one return QString(); } -QString Node::Description() +QString Node::Description() const { // Return an empty string by default return QString(); @@ -85,11 +85,11 @@ void Node::AddParameter(NodeParam *param) } } -QVariant Node::Value(NodeOutput *output) +NodeValueTable Node::Value(const NodeValueDatabase &value) const { - Q_UNUSED(output) + Q_UNUSED(value) - return QVariant(); + return NodeValueTable(); } void Node::InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from) @@ -99,7 +99,7 @@ void Node::InvalidateCache(const rational &start_range, const rational &end_rang SendInvalidateCache(start_range, end_range); } -TimeRange Node::InputTimeAdjustment(NodeInput *input, const TimeRange &input_time) +TimeRange Node::InputTimeAdjustment(NodeInput *input, const TimeRange &input_time) const { Q_UNUSED(input) @@ -156,26 +156,6 @@ void Node::UnlockUserInput() user_input_lock_.unlock(); } -void Node::LockProcessing() -{ - processing_lock_.lock(); -} - -void Node::UnlockProcessing() -{ - processing_lock_.unlock(); -} - -bool Node::IsProcessingLocked() -{ - if (processing_lock_.tryLock()) { - processing_lock_.unlock(); - return false; - } else { - return true; - } -} - void Node::CopyInputs(Node *source, Node *destination, bool include_connections) { Q_ASSERT(source->id() == destination->id()); @@ -232,7 +212,7 @@ void Node::DuplicateConnectionsBetweenLists(const QList &source, const Q } } -bool Node::CanBeDeleted() +bool Node::CanBeDeleted() const { return can_be_deleted_; } @@ -242,12 +222,12 @@ void Node::SetCanBeDeleted(bool s) can_be_deleted_ = s; } -bool Node::IsBlock() +bool Node::IsBlock() const { return false; } -bool Node::IsTrack() +bool Node::IsTrack() const { return false; } @@ -278,12 +258,12 @@ NodeOutput *Node::LastProcessedOutput() return o; } -const QList& Node::parameters() +const QList& Node::parameters() const { return params_; } -int Node::IndexOfParameter(NodeParam *param) +int Node::IndexOfParameter(NodeParam *param) const { return params_.indexOf(param); } @@ -296,7 +276,7 @@ int Node::IndexOfParameter(NodeParam *param) * TRUE to recursively traverse each node for a complete dependency graph. FALSE to return only the immediate * dependencies. */ -void GetDependenciesInternal(Node* n, QList& list, bool traverse) { +void GetDependenciesInternal(const Node* n, QList& list, bool traverse) { foreach (NodeParam* p, n->parameters()) { if (p->type() == NodeParam::kInput) { Node* connected = static_cast(p)->get_connected_node(); @@ -312,7 +292,7 @@ void GetDependenciesInternal(Node* n, QList& list, bool traverse) { } } -QList Node::GetDependencies() +QList Node::GetDependencies() const { QList node_list; @@ -321,7 +301,7 @@ QList Node::GetDependencies() return node_list; } -QList Node::GetExclusiveDependencies() +QList Node::GetExclusiveDependencies() const { QList deps = GetDependencies(); @@ -356,7 +336,7 @@ QList Node::GetExclusiveDependencies() return deps; } -QList Node::GetImmediateDependencies() +QList Node::GetImmediateDependencies() const { QList node_list; @@ -365,14 +345,14 @@ QList Node::GetImmediateDependencies() return node_list; } -QString Node::Code(NodeOutput *output) +QString Node::Code(NodeOutput *output) const { Q_UNUSED(output) return QString(); } -NodeParam *Node::GetParameterWithID(const QString &id) +NodeParam *Node::GetParameterWithID(const QString &id) const { foreach (NodeParam* param, params_) { if (param->id() == id) { @@ -383,7 +363,7 @@ NodeParam *Node::GetParameterWithID(const QString &id) return nullptr; } -bool Node::OutputsTo(Node *n) +bool Node::OutputsTo(Node *n) const { foreach (NodeParam* param, params_) { if (param->type() == NodeParam::kOutput) { @@ -400,22 +380,22 @@ bool Node::OutputsTo(Node *n) return false; } -bool Node::HasInputs() +bool Node::HasInputs() const { return HasParamOfType(NodeParam::kInput, false); } -bool Node::HasOutputs() +bool Node::HasOutputs() const { return HasParamOfType(NodeParam::kOutput, false); } -bool Node::HasConnectedInputs() +bool Node::HasConnectedInputs() const { return HasParamOfType(NodeParam::kInput, true); } -bool Node::HasConnectedOutputs() +bool Node::HasConnectedOutputs() const { return HasParamOfType(NodeParam::kOutput, true); } @@ -432,7 +412,7 @@ QVariant Node::PtrToValue(void *ptr) return reinterpret_cast(ptr); } -bool Node::HasParamWithID(const QString &id) +bool Node::HasParamWithID(const QString &id) const { foreach (NodeParam* p, params_) { @@ -445,7 +425,7 @@ bool Node::HasParamWithID(const QString &id) return false; } -bool Node::HasParamOfType(NodeParam::Type type, bool must_be_connected) +bool Node::HasParamOfType(NodeParam::Type type, bool must_be_connected) const { foreach (NodeParam* p, params_) { if (p->type() == type diff --git a/app/node/node.h b/app/node/node.h index c47cb449c..1f4593307 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -30,6 +30,7 @@ #include "node/input.h" #include "node/inputarray.h" #include "node/output.h" +#include "node/value.h" /** * @brief A single processing unit that can be connected with others to create intricate processing systems @@ -59,7 +60,7 @@ public: * By default, the clone will NOT have the values and connections of the original node. The caller is responsible for * copying that data with functions like CopyInputs() as copies may be done for different reasons. */ - virtual Node* copy() = 0; + virtual Node* copy() const = 0; /** * @brief Return the name of the node @@ -67,7 +68,7 @@ public: * This is the node's name shown to the user. This must be overridden by subclasses, and preferably run through the * translator. */ - virtual QString Name() = 0; + virtual QString Name() const = 0; /** * @brief Return the unique identifier of the node @@ -76,7 +77,7 @@ public: * completely unique to this node, and preferably in bundle identifier format (e.g. "org.company.Name"). This string * should NOT be translated. */ - virtual QString id() = 0; + virtual QString id() const = 0; /** * @brief Return the category this node is in (optional for subclassing, but recommended) @@ -86,7 +87,7 @@ public: * interpreted as an empty string category. This value should be run through a translator as its largely user * oriented. */ - virtual QString Category(); + virtual QString Category() const; /** * @brief Return a description of this node's purpose (optional for subclassing, but recommended) @@ -94,7 +95,7 @@ public: * A short (1-2 sentence) description of what this node should do to help the user understand its purpose. This should * be run through a translator. */ - virtual QString Description(); + virtual QString Description() const; /** * @brief Signals the Node that it won't be used for a while and can deallocate some memory @@ -109,18 +110,18 @@ public: /** * @brief Return a list of NodeParams */ - const QList& parameters(); + const QList& parameters() const; /** * @brief Return the index of a parameter * @return Parameter index or -1 if this parameter is not part of this Node */ - int IndexOfParameter(NodeParam* param); + int IndexOfParameter(NodeParam* param) const; /** * @brief Return a list of all Nodes that this Node's inputs are connected to (does not include this Node) */ - QList GetDependencies(); + QList GetDependencies() const; /** * @brief Returns a list of Nodes that this Node is dependent on, provided no other Nodes are dependent on them @@ -128,47 +129,47 @@ public: * * Similar to GetDependencies(), but excludes any Nodes that are used outside the dependency graph of this Node. */ - QList GetExclusiveDependencies(); + QList GetExclusiveDependencies() const; /** * @brief Retrieve immediate dependencies (only nodes that are directly connected to the inputs of this one) */ - QList GetImmediateDependencies(); + QList GetImmediateDependencies() const; /** * @brief Generate OpenCL hardware accelerated code for this Node */ - virtual QString Code(NodeOutput* output); + virtual QString Code(NodeOutput* output) const; /** * @brief Returns the parameter with the specified ID (or nullptr if it doesn't exist) */ - NodeParam* GetParameterWithID(const QString& id); + NodeParam* GetParameterWithID(const QString& id) const; /** * @brief Returns whether this Node outputs data to the Node `n` in any way */ - bool OutputsTo(Node* n); + bool OutputsTo(Node* n) const; /** * @brief Return whether this Node has input parameters */ - bool HasInputs(); + bool HasInputs() const; /** * @brief Return whether this Node has output parameters */ - bool HasOutputs(); + bool HasOutputs() const; /** * @brief Return whether this Node has input parameters and at least one of them is connected */ - bool HasConnectedInputs(); + bool HasConnectedInputs() const; /** * @brief Return whether this Node has output parameters and at least one of them is connected */ - bool HasConnectedOutputs(); + bool HasConnectedOutputs() const; /** * @brief Severs all input and output connections @@ -197,7 +198,7 @@ public: */ virtual void InvalidateCache(const rational& start_range, const rational& end_range, NodeInput* from = nullptr); - virtual TimeRange InputTimeAdjustment(NodeInput* input, const TimeRange& input_time); + virtual TimeRange InputTimeAdjustment(NodeInput* input, const TimeRange& input_time) const; /** * @brief User input lock prevents any user changes while a graph is being rendered @@ -205,13 +206,6 @@ public: void LockUserInput(); void UnlockUserInput(); - /** - * @brief Processing lock prevents more than one thread trying to process a Node at once - */ - void LockProcessing(); - void UnlockProcessing(); - bool IsProcessingLocked(); - /** * @brief Copies inputs from from Node to another including connections * @@ -227,7 +221,7 @@ public: /** * @brief Return whether this Node can be deleted or not */ - bool CanBeDeleted(); + bool CanBeDeleted() const; /** * @brief Set whether this Node can be deleted in the UI or not @@ -240,7 +234,7 @@ public: * You shouldn't ever need to override this since all derivatives of Block will automatically have this set to true. * It's just a more convenient way of checking than dynamic_casting. */ - virtual bool IsBlock(); + virtual bool IsBlock() const; /** * @brief Returns whether this Node is a "Track" type or not @@ -248,7 +242,7 @@ public: * You shouldn't ever need to override this since all derivatives of Track will automatically have this set to true. * It's just a more convenient way of checking than dynamic_casting. */ - virtual bool IsTrack(); + virtual bool IsTrack() const; /** * @brief The main processing function @@ -263,12 +257,12 @@ public: * 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 QVariant Value(NodeOutput* output); + virtual NodeValueTable Value(const NodeValueDatabase& value) const; /** * @brief Return whether a parameter with ID `id` has already been added to this Node */ - bool HasParamWithID(const QString& id); + bool HasParamWithID(const QString& id) const; protected: /** @@ -318,7 +312,7 @@ signals: void EdgeRemoved(NodeEdgePtr edge); private: - bool HasParamOfType(NodeParam::Type type, bool must_be_connected); + bool HasParamOfType(NodeParam::Type type, bool must_be_connected) const; void ConnectInput(NodeInput* input); @@ -341,11 +335,6 @@ private: */ QMutex user_input_lock_; - /** - * @brief Used for thread safety between multiple threads - */ - QMutex processing_lock_; - /** * @brief Internal variable for whether this Node can be deleted or not */ diff --git a/app/node/output/timeline/timeline.cpp b/app/node/output/timeline/timeline.cpp index 852ec0eac..d08bf07e6 100644 --- a/app/node/output/timeline/timeline.cpp +++ b/app/node/output/timeline/timeline.cpp @@ -35,7 +35,6 @@ TimelineOutput::TimelineOutput() for (int i=0;iset_data_type(NodeParam::kTrack); AddParameter(track_input); track_inputs_.replace(i, track_input); @@ -53,58 +52,61 @@ TimelineOutput::TimelineOutput() AddParameter(length_output_); } -Node *TimelineOutput::copy() +Node *TimelineOutput::copy() const { return new TimelineOutput(); } -QString TimelineOutput::Name() +QString TimelineOutput::Name() const { return tr("Timeline"); } -QString TimelineOutput::id() +QString TimelineOutput::id() const { return "org.olivevideoeditor.Olive.timeline"; } -QString TimelineOutput::Category() +QString TimelineOutput::Category() const { return tr("Output"); } -QString TimelineOutput::Description() +QString TimelineOutput::Description() const { return tr("Node for communicating between a Timeline panel and the node graph."); } -QVector TimelineOutput::Tracks() -{ - return track_cache_; -} - -NodeOutput *TimelineOutput::length_output() -{ - return length_output_; -} - -const rational &TimelineOutput::timeline_length() +const rational &TimelineOutput::length() const { return length_; } -const rational &TimelineOutput::Timebase() +const QVector& TimelineOutput::Tracks() const +{ + return track_cache_; +} + +NodeOutput *TimelineOutput::length_output() const +{ + return length_output_; +} + +const rational &TimelineOutput::timeline_length() const +{ + return length_; +} + +const rational &TimelineOutput::timebase() const { return timebase_; } -QVariant TimelineOutput::Value(NodeOutput *output) +NodeValueTable TimelineOutput::Value(const NodeValueDatabase &value) const { - if (output == length_output_) { - return QVariant::fromValue(length_); - } - - return 0; + NodeValueTable table = value.Merge(); + table.Push(NodeParam::kRational, QVariant::fromValue(length())); + return table; } void TimelineOutput::UpdateTrackCache() @@ -150,12 +152,12 @@ void TimelineOutput::SetTimebase(const rational &timebase) emit TimebaseChanged(timebase_); } -NodeInput *TimelineOutput::track_input(TrackType type) +NodeInput *TimelineOutput::track_input(TrackType type) const { return track_inputs_.at(type); } -TrackList *TimelineOutput::track_list(TrackType type) +TrackList *TimelineOutput::track_list(TrackType type) const { return track_lists_.at(type); } diff --git a/app/node/output/timeline/timeline.h b/app/node/output/timeline/timeline.h index 5f9364709..35fd00184 100644 --- a/app/node/output/timeline/timeline.h +++ b/app/node/output/timeline/timeline.h @@ -37,24 +37,26 @@ class TimelineOutput : public Node public: TimelineOutput(); - virtual Node* copy() override; + virtual Node* copy() const override; - virtual QString Name() override; - virtual QString id() override; - virtual QString Category() override; - virtual QString Description() override; + virtual QString Name() const override; + virtual QString id() const override; + virtual QString Category() const override; + virtual QString Description() const override; - QVector Tracks(); + const rational& length() const; - NodeInput* track_input(TrackType type); + const QVector &Tracks() const; - TrackList* track_list(TrackType type); + NodeInput* track_input(TrackType type) const; - NodeOutput* length_output(); + TrackList* track_list(TrackType type) const; - const rational& timeline_length(); + NodeOutput* length_output() const; - const rational& Timebase(); + const rational& timeline_length() const; + + const rational& timebase() const; void SetTimebase(const rational &timebase); @@ -69,7 +71,7 @@ signals: void TrackRemoved(TrackOutput* track); protected: - virtual QVariant Value(NodeOutput* output) override; + virtual NodeValueTable Value(const NodeValueDatabase& value) const override; private: QVector track_inputs_; diff --git a/app/node/output/track/track.cpp b/app/node/output/track/track.cpp index 6b894f73a..fd742fe5a 100644 --- a/app/node/output/track/track.cpp +++ b/app/node/output/track/track.cpp @@ -37,7 +37,6 @@ TrackOutput::TrackOutput() : connect(block_input_, SIGNAL(SizeChanged(int)), this, SLOT(BlockListSizeChanged(int))); track_input_ = new NodeInput("track_in"); - track_input_->set_data_type(NodeParam::kTrack); track_input_->set_dependent(false); AddParameter(track_input_); @@ -55,32 +54,32 @@ const TrackType& TrackOutput::track_type() return track_type_; } -Block::Type TrackOutput::type() +Block::Type TrackOutput::type() const { return kTrack; } -Block *TrackOutput::copy() +Block *TrackOutput::copy() const { return new TrackOutput(); } -QString TrackOutput::Name() +QString TrackOutput::Name() const { return tr("Track"); } -QString TrackOutput::id() +QString TrackOutput::id() const { return "org.olivevideoeditor.Olive.track"; } -QString TrackOutput::Category() +QString TrackOutput::Category() const { return tr("Output"); } -QString TrackOutput::Description() +QString TrackOutput::Description() const { return tr("Node for representing and processing a single array of Blocks sorted by time. Also represents the end of " "a Sequence."); @@ -98,7 +97,8 @@ void TrackOutput::SetIndex(const int &index) TrackOutput *TrackOutput::next_track() { - return ValueToPtr(track_input_->get_realtime_value_of_connected_output()); + // FIXME: Re-do this without dynamic_cast at some point + return dynamic_cast(track_input_->get_connected_node()); } NodeInput *TrackOutput::track_input() @@ -111,7 +111,7 @@ NodeOutput* TrackOutput::track_output() return track_output_; } -Block *TrackOutput::BlockContainingTime(const rational &time) +Block *TrackOutput::BlockContainingTime(const rational &time) const { foreach (Block* block, block_cache_) { if (block->in() < time && block->out() > time) { @@ -124,7 +124,7 @@ Block *TrackOutput::BlockContainingTime(const rational &time) return nullptr; } -Block *TrackOutput::NearestBlockBefore(const rational &time) +Block *TrackOutput::NearestBlockBefore(const rational &time) const { foreach (Block* block, block_cache_) { // Blocks are sorted by time, so the first Block who's out point is at/after this time is the correct Block @@ -133,10 +133,10 @@ Block *TrackOutput::NearestBlockBefore(const rational &time) } } - return this; + return nullptr; } -Block *TrackOutput::NearestBlockAfter(const rational &time) +Block *TrackOutput::NearestBlockAfter(const rational &time) const { foreach (Block* block, block_cache_) { // Blocks are sorted by time, so the first Block after this time is the correct Block @@ -145,10 +145,10 @@ Block *TrackOutput::NearestBlockAfter(const rational &time) } } - return this; + return nullptr; } -const QVector &TrackOutput::Blocks() +const QVector &TrackOutput::Blocks() const { return block_cache_; } @@ -163,17 +163,6 @@ void TrackOutput::InvalidateCache(const rational &start_range, const rational &e Node::InvalidateCache(start_range, end_range, from); } -QVariant TrackOutput::Value(NodeOutput *output) -{ - if (output == track_output_) { - // Set track output correctly - return PtrToValue(this); - } - - // Run default node processing - return Block::Value(output); -} - void TrackOutput::InsertBlockBefore(Block* block, Block* after) { InsertBlockAtIndex(block, block_cache_.indexOf(after)); @@ -301,12 +290,12 @@ TrackOutput *TrackOutput::TrackFromBlock(Block *block) return nullptr; } -const rational &TrackOutput::track_length() +const rational &TrackOutput::track_length() const { return track_length_; } -bool TrackOutput::IsTrack() +bool TrackOutput::IsTrack() const { return true; } diff --git a/app/node/output/track/track.h b/app/node/output/track/track.h index b16698007..798c3ef35 100644 --- a/app/node/output/track/track.h +++ b/app/node/output/track/track.h @@ -36,14 +36,14 @@ public: const TrackType& track_type(); void set_track_type(const TrackType& track_type); - virtual Type type() override; + virtual Type type() const override; - virtual Block* copy() override; + virtual Block* copy() const override; - virtual QString Name() override; - virtual QString id() override; - virtual QString Category() override; - virtual QString Description() override; + virtual QString Name() const override; + virtual QString id() const override; + virtual QString Category() const override; + virtual QString Description() const override; const int& Index(); void SetIndex(const int& index); @@ -54,13 +54,13 @@ public: NodeOutput* track_output(); - Block* BlockContainingTime(const rational& time); + Block* BlockContainingTime(const rational& time) const; - Block* NearestBlockBefore(const rational& time); + Block* NearestBlockBefore(const rational& time) const; - Block* NearestBlockAfter(const rational& time); + Block* NearestBlockAfter(const rational& time) const; - const QVector& Blocks(); + const QVector& Blocks() const; virtual void InvalidateCache(const rational& start_range, const rational& end_range, NodeInput* from = nullptr) override; @@ -124,9 +124,9 @@ public: static TrackOutput* TrackFromBlock(Block* block); - const rational& track_length(); + const rational& track_length() const; - virtual bool IsTrack() override; + virtual bool IsTrack() const override; signals: /** @@ -145,7 +145,6 @@ signals: void TrackLengthChanged(); protected: - virtual QVariant Value(NodeOutput* output) override; private: void UpdateInOutFrom(int index); diff --git a/app/node/output/viewer/viewer.cpp b/app/node/output/viewer/viewer.cpp index f9a8ef6a7..9962fafc9 100644 --- a/app/node/output/viewer/viewer.cpp +++ b/app/node/output/viewer/viewer.cpp @@ -35,27 +35,27 @@ ViewerOutput::ViewerOutput() AddParameter(length_input_); } -Node *ViewerOutput::copy() +Node *ViewerOutput::copy() const { return new ViewerOutput(); } -QString ViewerOutput::Name() +QString ViewerOutput::Name() const { return tr("Viewer"); } -QString ViewerOutput::id() +QString ViewerOutput::id() const { return "org.olivevideoeditor.Olive.vieweroutput"; } -QString ViewerOutput::Category() +QString ViewerOutput::Category() const { return tr("Output"); } -QString ViewerOutput::Description() +QString ViewerOutput::Description() const { return tr("Interface between a Viewer panel and the node system."); } @@ -115,7 +115,8 @@ void ViewerOutput::set_audio_params(const AudioParams &audio) rational ViewerOutput::Length() { - return length_input_->get_realtime_value_of_connected_output().value(); + // FIXME: This is pretty messy, there's probably a better way... + return length_input_->get_connected_node()->Value(NodeValueDatabase()).Get(NodeParam::kRational).value(); } void ViewerOutput::DependentEdgeChanged(NodeInput *from) diff --git a/app/node/output/viewer/viewer.h b/app/node/output/viewer/viewer.h index cc524fec1..3570e7a50 100644 --- a/app/node/output/viewer/viewer.h +++ b/app/node/output/viewer/viewer.h @@ -36,12 +36,12 @@ class ViewerOutput : public Node public: ViewerOutput(); - virtual Node* copy() override; + virtual Node* copy() const override; - virtual QString Name() override; - virtual QString id() override; - virtual QString Category() override; - virtual QString Description() override; + virtual QString Name() const override; + virtual QString id() const override; + virtual QString Category() const override; + virtual QString Description() const override; NodeInput* texture_input(); NodeInput* samples_input(); diff --git a/app/node/value.cpp b/app/node/value.cpp new file mode 100644 index 000000000..8c066cf65 --- /dev/null +++ b/app/node/value.cpp @@ -0,0 +1,153 @@ +#include "value.h" + +NodeValueDatabase::NodeValueDatabase() +{ + +} + +NodeValueTable NodeValueDatabase::operator[](const QString &input_id) const +{ + return tables_.value(input_id); +} + +NodeValueTable NodeValueDatabase::operator[](const NodeInput *input) const +{ + return tables_.value(input->id()); +} + +void NodeValueDatabase::Insert(const QString &key, const NodeValueTable &value) +{ + tables_.insert(key, value); +} + +void NodeValueDatabase::Insert(const NodeInput *key, const NodeValueTable &value) +{ + tables_.insert(key->id(), value); +} + +NodeValueTable NodeValueDatabase::Merge() const +{ + if (tables_.size() == 1) { + return tables_.begin().value(); + } + + int row = 0; + + NodeValueTable merged_table; + + QHash::const_iterator iterator; + + // Slipstreams all tables together + // FIXME: I don't actually know if this is the right approach... + for (iterator = tables_.begin();iterator != tables_.end();iterator++) { + const NodeValueTable& table = iterator.value(); + + if (row >= table.Count()) { + continue; + } + + int row_index = table.Count() - 1 - row; + + merged_table.Prepend(table.At(row_index)); + } + + return merged_table; +} + +NodeValue::NodeValue(const NodeParam::DataType &type, const QVariant &data, const QString &tag) : + type_(type), + data_(data), + tag_(tag) +{ +} + +const NodeParam::DataType &NodeValue::type() const +{ + return type_; +} + +const QString &NodeValue::tag() const +{ + return tag_; +} + +const QVariant &NodeValue::data() const +{ + return data_; +} + +NodeValueTable::NodeValueTable() +{ +} + +QVariant NodeValueTable::Get(const NodeParam::DataType &type, const QString &tag) +{ + return GetInternal(type, tag, false); +} + +QVariant NodeValueTable::Take(const NodeParam::DataType &type, const QString &tag) +{ + return GetInternal(type, tag, true); +} + +void NodeValueTable::Push(const NodeValue &value) +{ + values_.append(value); +} + +void NodeValueTable::Push(const NodeParam::DataType &type, const QVariant &data, const QString &tag) +{ + Push(NodeValue(type, data, tag)); +} + +void NodeValueTable::Prepend(const NodeValue &value) +{ + values_.prepend(value); +} + +void NodeValueTable::Prepend(const NodeParam::DataType &type, const QVariant &data, const QString &tag) +{ + Prepend(NodeValue(type, data, tag)); +} + +const NodeValue &NodeValueTable::At(int index) const +{ + return values_.at(index); +} + +int NodeValueTable::Count() const +{ + return values_.size(); +} + +bool NodeValueTable::isEmpty() const +{ + return values_.isEmpty(); +} + +QVariant NodeValueTable::GetInternal(const NodeParam::DataType &type, const QString &tag, bool remove) +{ + int index = -1; + + for (int i=values_.size() - 1;i>=0;i--) { + const NodeValue& v = values_.at(i); + + if (v.type() & type) { + index = i; + + if (tag.isEmpty() || tag == v.tag()) { + break; + } + } + } + + if (index >= 0) { + if (remove) { + values_.removeAt(index); + } + + return values_.at(index).data(); + } + + return QVariant(); +} diff --git a/app/node/value.h b/app/node/value.h new file mode 100644 index 000000000..f9cafa76a --- /dev/null +++ b/app/node/value.h @@ -0,0 +1,65 @@ +#ifndef VALUE_H +#define VALUE_H + +#include + +#include "input.h" + +class NodeValue +{ +public: + NodeValue(const NodeParam::DataType& type, const QVariant& data, const QString& tag = QString()); + + const NodeParam::DataType& type() const; + const QVariant& data() const; + const QString& tag() const; + +private: + NodeParam::DataType type_; + QVariant data_; + QString tag_; + +}; + +class NodeValueTable +{ +public: + NodeValueTable(); + + QVariant Get(const NodeParam::DataType& type, const QString& tag = QString()); + QVariant Take(const NodeParam::DataType& type, const QString& tag = QString()); + void Push(const NodeValue& value); + void Push(const NodeParam::DataType& type, const QVariant& data, const QString& tag = QString()); + void Prepend(const NodeValue& value); + void Prepend(const NodeParam::DataType& type, const QVariant& data, const QString& tag = QString()); + const NodeValue& At(int index) const; + int Count() const; + + bool isEmpty() const; + +private: + QVariant GetInternal(const NodeParam::DataType& type, const QString& tag, bool remove); + + QList values_; + +}; + +class NodeValueDatabase +{ +public: + NodeValueDatabase(); + + NodeValueTable operator[](const QString& input_id) const; + NodeValueTable operator[](const NodeInput* input) const; + + void Insert(const QString& key, const NodeValueTable &value); + void Insert(const NodeInput* key, const NodeValueTable& value); + + NodeValueTable Merge() const; + +private: + QHash tables_; + +}; + +#endif // VALUE_H