From a0706a78d8602e43021a50e77bec84adc21c30a5 Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Tue, 7 Sep 2021 15:27:07 -0700 Subject: [PATCH] nodes: implemented core of manual table value selection --- app/node/CMakeLists.txt | 2 + app/node/audio/pan/pan.cpp | 17 ++-- app/node/audio/pan/pan.h | 4 +- app/node/audio/volume/volume.cpp | 13 +-- app/node/audio/volume/volume.h | 4 +- app/node/block/block.cpp | 11 ++- app/node/block/block.h | 4 +- app/node/block/clip/clip.cpp | 17 ++-- app/node/block/clip/clip.h | 4 +- .../crossdissolve/crossdissolvetransition.cpp | 2 +- .../crossdissolve/crossdissolvetransition.h | 2 +- .../diptocolor/diptocolortransition.cpp | 4 +- .../diptocolor/diptocolortransition.h | 2 +- app/node/block/transition/transition.cpp | 28 +++---- app/node/block/transition/transition.h | 6 +- app/node/distort/crop/cropdistortnode.cpp | 44 ++++------ app/node/distort/crop/cropdistortnode.h | 6 +- .../transform/transformdistortnode.cpp | 67 +++++++-------- .../distort/transform/transformdistortnode.h | 10 +-- app/node/filter/blur/blur.cpp | 20 ++--- app/node/filter/blur/blur.h | 2 +- app/node/filter/mosaic/mosaicfilternode.cpp | 14 +--- app/node/filter/mosaic/mosaicfilternode.h | 2 +- app/node/filter/stroke/stroke.cpp | 19 ++--- app/node/filter/stroke/stroke.h | 2 +- app/node/generator/matrix/matrix.cpp | 34 ++++---- app/node/generator/matrix/matrix.h | 4 +- app/node/generator/polygon/polygon.cpp | 11 +-- app/node/generator/polygon/polygon.h | 2 +- app/node/generator/shape/shapenode.cpp | 13 +-- app/node/generator/shape/shapenode.h | 2 +- app/node/generator/solid/solid.cpp | 9 +-- app/node/generator/solid/solid.h | 2 +- app/node/generator/text/text.cpp | 15 +--- app/node/generator/text/text.h | 2 +- app/node/globals.cpp | 25 ++++++ app/node/globals.h | 62 ++++++++++++++ app/node/input/time/timeinput.cpp | 22 +++-- app/node/input/time/timeinput.h | 4 +- app/node/input/value/valuenode.cpp | 9 +-- app/node/input/value/valuenode.h | 2 +- app/node/math/math/math.cpp | 28 +++---- app/node/math/math/math.h | 4 +- app/node/math/math/mathbase.cpp | 42 +++++----- app/node/math/math/mathbase.h | 4 +- app/node/math/merge/merge.cpp | 23 +++--- app/node/math/merge/merge.h | 4 +- app/node/math/trigonometry/trigonometry.cpp | 10 +-- app/node/math/trigonometry/trigonometry.h | 2 +- app/node/node.cpp | 34 ++++---- app/node/node.h | 33 ++++++-- app/node/output/track/track.cpp | 8 +- app/node/output/track/track.h | 2 +- app/node/output/viewer/viewer.cpp | 17 ---- app/node/output/viewer/viewer.h | 3 - app/node/project/footage/footage.cpp | 23 +++--- app/node/project/footage/footage.h | 4 +- app/node/time/timeremap/timeremap.cpp | 7 +- app/node/time/timeremap/timeremap.h | 2 +- app/node/traverser.cpp | 81 +++++++++++++++---- app/node/traverser.h | 13 ++- app/node/value.h | 7 ++ app/node/valuedatabase.h | 22 +++-- app/render/job/acceleratedjob.cpp | 7 -- app/render/job/acceleratedjob.h | 14 +++- app/render/job/samplejob.h | 4 +- app/render/opengl/openglrenderer.cpp | 3 +- app/render/rendermanager.cpp | 2 +- app/render/renderprocessor.cpp | 6 +- app/widget/viewer/viewerdisplay.cpp | 10 +-- app/widget/viewer/viewerdisplay.h | 8 +- 71 files changed, 517 insertions(+), 434 deletions(-) create mode 100644 app/node/globals.cpp create mode 100644 app/node/globals.h diff --git a/app/node/CMakeLists.txt b/app/node/CMakeLists.txt index 97b251f6a..3160a12d0 100644 --- a/app/node/CMakeLists.txt +++ b/app/node/CMakeLists.txt @@ -30,6 +30,8 @@ set(OLIVE_SOURCES ${OLIVE_SOURCES} node/factory.cpp node/factory.h + node/globals.cpp + node/globals.h node/graph.cpp node/graph.h node/inputdragger.cpp diff --git a/app/node/audio/pan/pan.cpp b/app/node/audio/pan/pan.cpp index 5298ce27d..2d8e7c5a4 100644 --- a/app/node/audio/pan/pan.cpp +++ b/app/node/audio/pan/pan.cpp @@ -62,16 +62,13 @@ QString PanNode::Description() const return tr("Adjust the stereo panning of an audio source."); } -NodeValueTable PanNode::Value(const QString &output, NodeValueDatabase &value) const +void PanNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) + Q_UNUSED(globals) // Create a sample job SampleJob job(kSamplesInput, value); - job.InsertValue(this, kPanningInput, value); - - // Push it to our table - NodeValueTable table = value.Merge(); if (job.HasSamples()) { bool push_job = false; @@ -95,18 +92,16 @@ NodeValueTable PanNode::Value(const QString &output, NodeValueDatabase &value) c } if (push_job) { - table.Push(NodeValue::kSampleJob, QVariant::fromValue(job), this); + table->Push(NodeValue::kSampleJob, QVariant::fromValue(job), this); } else { - table.Push(NodeValue::kSamples, QVariant::fromValue(job.samples()), this); + table->Push(NodeValue::kSamples, QVariant::fromValue(job.samples()), this); } } - - return table; } -void PanNode::ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const +void PanNode::ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const { - float pan_val = values[kPanningInput].Get(NodeValue::kFloat).toFloat(); + float pan_val = values[kPanningInput].data().toFloat(); for (int i=0;iaudio_params().channel_count();i++) { output->data(i)[index] = input->data(i)[index]; diff --git a/app/node/audio/pan/pan.h b/app/node/audio/pan/pan.h index eb2945489..deb896a11 100644 --- a/app/node/audio/pan/pan.h +++ b/app/node/audio/pan/pan.h @@ -40,9 +40,9 @@ public: virtual QVector Category() const override; virtual QString Description() const override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; - virtual void ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override; + virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override; virtual void Retranslate() override; diff --git a/app/node/audio/volume/volume.cpp b/app/node/audio/volume/volume.cpp index 143e992d8..8e6d8056d 100644 --- a/app/node/audio/volume/volume.cpp +++ b/app/node/audio/volume/volume.cpp @@ -61,20 +61,21 @@ QString VolumeNode::Description() const return tr("Adjusts the volume of an audio source."); } -NodeValueTable VolumeNode::Value(const QString &output, NodeValueDatabase &value) const +void VolumeNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) - return ValueInternal(value, - kOpMultiply, + return ValueInternal(kOpMultiply, kPairSampleNumber, kSamplesInput, - value[kSamplesInput].TakeWithMeta(NodeValue::kSamples), + value[kSamplesInput], kVolumeInput, - value[kVolumeInput].TakeWithMeta(NodeValue::kFloat)); + value[kVolumeInput], + globals, + table); } -void VolumeNode::ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const +void VolumeNode::ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const { return ProcessSamplesInternal(values, kOpMultiply, kSamplesInput, kVolumeInput, input, output, index); } diff --git a/app/node/audio/volume/volume.h b/app/node/audio/volume/volume.h index 7e1d2e478..24cf9ae9b 100644 --- a/app/node/audio/volume/volume.h +++ b/app/node/audio/volume/volume.h @@ -40,9 +40,9 @@ public: virtual QVector Category() const override; virtual QString Description() const override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; - virtual void ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override; + virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override; virtual void Retranslate() override; diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp index 7fe968bcf..d4b2e9a42 100644 --- a/app/node/block/block.cpp +++ b/app/node/block/block.cpp @@ -100,13 +100,16 @@ void Block::InputValueChangedEvent(const QString &input, int element) } } -bool Block::HashPassthrough(const QString &input, const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const +bool Block::HashPassthrough(const QString &input, const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { if (IsInputConnected(input)) { - rational t = InputTimeAdjustment(input, -1, TimeRange(time, time)).in(); + TimeRange t = InputTimeAdjustment(input, -1, globals.time()); + + NodeGlobals new_globals = globals; + new_globals.set_time(t); NodeOutput out = GetConnectedOutput(input); - out.node()->Hash(out.output(), hash, t, video_params); + out.node()->Hash(out.output(), hash, new_globals, video_params); return true; } @@ -127,7 +130,7 @@ void Block::Retranslate() SetInputName(kEnabledInput, tr("Enabled")); } -void Block::Hash(const QString &, QCryptographicHash &, const rational &, const VideoParams &) const +void Block::Hash(const QString &, QCryptographicHash &, const NodeGlobals &, const VideoParams &) const { // A block does nothing by default, so we hash nothing } diff --git a/app/node/block/block.h b/app/node/block/block.h index 0d3b86f72..332b99c68 100644 --- a/app/node/block/block.h +++ b/app/node/block/block.h @@ -115,7 +115,7 @@ public: index_ = i; } - virtual void Hash(const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const override; + virtual void Hash(const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override; virtual void InvalidateCache(const TimeRange& range, const QString& from, int element = -1, InvalidateCacheOptions options = InvalidateCacheOptions()) override; @@ -134,7 +134,7 @@ signals: protected: virtual void InputValueChangedEvent(const QString& input, int element) override; - bool HashPassthrough(const QString &input, const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const; + bool HashPassthrough(const QString &input, const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const; Block* previous_; Block* next_; diff --git a/app/node/block/clip/clip.cpp b/app/node/block/clip/clip.cpp index edff8f436..1c37e11db 100644 --- a/app/node/block/clip/clip.cpp +++ b/app/node/block/clip/clip.cpp @@ -49,7 +49,8 @@ ClipBlock::ClipBlock() : AddInput(kReverseInput, NodeValue::kBoolean, false, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable)); IgnoreHashingFrom(kReverseInput); - AddInput(kBufferIn, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable)); + PrependInput(kBufferIn, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable)); + SetValueHintForInput(kBufferIn, {NodeValue::kBuffer, -1, QString()}); } Node *ClipBlock::copy() const @@ -231,18 +232,18 @@ TimeRange ClipBlock::OutputTimeAdjustment(const QString& input, int element, con return super::OutputTimeAdjustment(input, element, input_time); } -NodeValueTable ClipBlock::Value(const QString &output, NodeValueDatabase &value) const +void ClipBlock::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) + Q_UNUSED(globals) // We discard most values here except for the buffer we received - NodeValue data = value[kBufferIn].GetWithMeta(NodeValue::kBuffer); + NodeValue data = value[kBufferIn]; - NodeValueTable table; + table->Clear(); if (data.type() != NodeValue::kNone) { - table.Push(data); + table->Push(data); } - return table; } void ClipBlock::Retranslate() @@ -255,9 +256,9 @@ void ClipBlock::Retranslate() SetInputName(kReverseInput, tr("Reverse")); } -void ClipBlock::Hash(const QString &out, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const +void ClipBlock::Hash(const QString &out, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { - HashPassthrough(kBufferIn, out, hash, time, video_params); + HashPassthrough(kBufferIn, out, hash, globals, video_params); } } diff --git a/app/node/block/clip/clip.h b/app/node/block/clip/clip.h index 270df5d9d..904ada16e 100644 --- a/app/node/block/clip/clip.h +++ b/app/node/block/clip/clip.h @@ -55,11 +55,11 @@ public: virtual TimeRange OutputTimeAdjustment(const QString& input, int element, const TimeRange& input_time) const override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual void Retranslate() override; - virtual void Hash(const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const override; + virtual void Hash(const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override; double speed() const { diff --git a/app/node/block/transition/crossdissolve/crossdissolvetransition.cpp b/app/node/block/transition/crossdissolve/crossdissolvetransition.cpp index 07441e06d..8f9d33e62 100644 --- a/app/node/block/transition/crossdissolve/crossdissolvetransition.cpp +++ b/app/node/block/transition/crossdissolve/crossdissolvetransition.cpp @@ -59,7 +59,7 @@ ShaderCode CrossDissolveTransition::GetShaderCode(const QString &shader_id) cons return ShaderCode(FileFunctions::ReadFileAsString(":/shaders/crossdissolve.frag"), QString()); } -void CrossDissolveTransition::ShaderJobEvent(NodeValueDatabase &value, ShaderJob &job) const +void CrossDissolveTransition::ShaderJobEvent(const NodeValueRow &value, ShaderJob &job) const { Q_UNUSED(value) diff --git a/app/node/block/transition/crossdissolve/crossdissolvetransition.h b/app/node/block/transition/crossdissolve/crossdissolvetransition.h index 4d67d14a8..aca4fd039 100644 --- a/app/node/block/transition/crossdissolve/crossdissolvetransition.h +++ b/app/node/block/transition/crossdissolve/crossdissolvetransition.h @@ -45,7 +45,7 @@ public: virtual ShaderCode GetShaderCode(const QString& shader_id) const override; protected: - virtual void ShaderJobEvent(NodeValueDatabase& value, ShaderJob& job) const override; + virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob& job) const override; virtual void SampleJobEvent(SampleBufferPtr from_samples, SampleBufferPtr to_samples, SampleBufferPtr out_samples, double time_in) const override; diff --git a/app/node/block/transition/diptocolor/diptocolortransition.cpp b/app/node/block/transition/diptocolor/diptocolortransition.cpp index d28df020e..1c9691e13 100644 --- a/app/node/block/transition/diptocolor/diptocolortransition.cpp +++ b/app/node/block/transition/diptocolor/diptocolortransition.cpp @@ -61,9 +61,9 @@ ShaderCode DipToColorTransition::GetShaderCode(const QString &shader_id) const return ShaderCode(FileFunctions::ReadFileAsString(":/shaders/diptoblack.frag"), QString()); } -void DipToColorTransition::ShaderJobEvent(NodeValueDatabase &value, ShaderJob &job) const +void DipToColorTransition::ShaderJobEvent(const NodeValueRow &value, ShaderJob &job) const { - job.InsertValue(this, kColorInput, value); + job.InsertValue(kColorInput, value); } } diff --git a/app/node/block/transition/diptocolor/diptocolortransition.h b/app/node/block/transition/diptocolor/diptocolortransition.h index 14d148809..00ff56550 100644 --- a/app/node/block/transition/diptocolor/diptocolortransition.h +++ b/app/node/block/transition/diptocolor/diptocolortransition.h @@ -45,7 +45,7 @@ public: static const QString kColorInput; protected: - virtual void ShaderJobEvent(NodeValueDatabase &value, ShaderJob& job) const override; + virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob& job) const override; }; diff --git a/app/node/block/transition/transition.cpp b/app/node/block/transition/transition.cpp index dce6845ff..b5a0bd3ea 100644 --- a/app/node/block/transition/transition.cpp +++ b/app/node/block/transition/transition.cpp @@ -137,12 +137,12 @@ double TransitionBlock::GetInProgress(const double &time) const return clamp((GetInternalTransitionTime(time) - out_offset().toDouble()) / in_offset().toDouble(), 0.0, 1.0); } -void TransitionBlock::Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const +void TransitionBlock::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { - if (HashPassthrough(kInBlockInput, output, hash, time, video_params) || HashPassthrough(kOutBlockInput, output, hash, time, video_params)) { + if (HashPassthrough(kInBlockInput, output, hash, globals, video_params) || HashPassthrough(kOutBlockInput, output, hash, globals, video_params)) { HashAddNodeSignature(hash, output); - double time_dbl = time.toDouble(); + double time_dbl = globals.time().in().toDouble(); double all_prog = GetTotalProgress(time_dbl); double in_prog = GetInProgress(time_dbl); double out_prog = GetOutProgress(time_dbl); @@ -173,12 +173,12 @@ void TransitionBlock::InsertTransitionTimes(AcceleratedJob *job, const double &t NodeValue(NodeValue::kFloat, GetInProgress(time), this)); } -NodeValueTable TransitionBlock::Value(const QString &output, NodeValueDatabase &value) const +void TransitionBlock::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) - NodeValue out_buffer = value[kOutBlockInput].TakeWithMeta(NodeValue::kBuffer); - NodeValue in_buffer = value[kInBlockInput].TakeWithMeta(NodeValue::kBuffer); + NodeValue out_buffer = value[kOutBlockInput]; + NodeValue in_buffer = value[kInBlockInput]; NodeValue::Type data_type = (out_buffer.type() != NodeValue::kNone) ? out_buffer.type() : in_buffer.type(); NodeValue::Type job_type = NodeValue::kNone; @@ -196,9 +196,9 @@ NodeValueTable TransitionBlock::Value(const QString &output, NodeValueDatabase & job.InsertValue(kInBlockInput, in_buffer); } - job.InsertValue(this, kCurveInput, value); + job.InsertValue(kCurveInput, value); - double time = value[QStringLiteral("global")].Get(NodeValue::kFloat, QStringLiteral("time_in")).toDouble(); + double time = globals.time().in().toDouble(); InsertTransitionTimes(&job, time); ShaderJobEvent(value, job); @@ -211,8 +211,8 @@ NodeValueTable TransitionBlock::Value(const QString &output, NodeValueDatabase & SampleBufferPtr to_samples = in_buffer.data().value(); if (from_samples || to_samples) { - double time_in = value[QStringLiteral("global")].Get(NodeValue::kFloat, QStringLiteral("time_in")).toDouble(); - double time_out = value[QStringLiteral("global")].Get(NodeValue::kFloat, QStringLiteral("time_out")).toDouble(); + double time_in = globals.time().in().toDouble(); + double time_out = globals.time().out().toDouble(); const AudioParams& params = (from_samples) ? from_samples->audio_params() : to_samples->audio_params(); @@ -226,13 +226,9 @@ NodeValueTable TransitionBlock::Value(const QString &output, NodeValueDatabase & } } - NodeValueTable table = value.Merge(); - if (!push_job.isNull()) { - table.Push(job_type, push_job, this); + table->Push(job_type, push_job, this); } - - return table; } void TransitionBlock::InvalidateCache(const TimeRange &range, const QString &from, int element, InvalidateCacheOptions options) @@ -249,7 +245,7 @@ void TransitionBlock::InvalidateCache(const TimeRange &range, const QString &fro super::InvalidateCache(r, from, element, options); } -void TransitionBlock::ShaderJobEvent(NodeValueDatabase &value, ShaderJob &job) const +void TransitionBlock::ShaderJobEvent(const NodeValueRow &value, ShaderJob &job) const { Q_UNUSED(value) Q_UNUSED(job) diff --git a/app/node/block/transition/transition.h b/app/node/block/transition/transition.h index f14dd4ef3..55a510489 100644 --- a/app/node/block/transition/transition.h +++ b/app/node/block/transition/transition.h @@ -65,9 +65,9 @@ public: double GetOutProgress(const double &time) const; double GetInProgress(const double &time) const; - virtual void Hash(const QString& output, QCryptographicHash& hash, const rational &time, const VideoParams& video_params) const override; + virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual void InvalidateCache(const TimeRange& range, const QString& from, int element = -1, InvalidateCacheOptions options = InvalidateCacheOptions()) override; @@ -77,7 +77,7 @@ public: static const QString kCenterInput; protected: - virtual void ShaderJobEvent(NodeValueDatabase &value, ShaderJob& job) const; + virtual void ShaderJobEvent(const NodeValueRow &value, ShaderJob& job) const; virtual void SampleJobEvent(SampleBufferPtr from_samples, SampleBufferPtr to_samples, SampleBufferPtr out_samples, double time_in) const; diff --git a/app/node/distort/crop/cropdistortnode.cpp b/app/node/distort/crop/cropdistortnode.cpp index 7b1838206..80132f1bf 100644 --- a/app/node/distort/crop/cropdistortnode.cpp +++ b/app/node/distort/crop/cropdistortnode.cpp @@ -55,35 +55,25 @@ void CropDistortNode::Retranslate() SetInputName(kFeatherInput, tr("Feather")); } -NodeValueTable CropDistortNode::Value(const QString &output, NodeValueDatabase &value) const +void CropDistortNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) ShaderJob job; - job.InsertValue(this, kTextureInput, value); - job.InsertValue(this, kLeftInput, value); - job.InsertValue(this, kTopInput, value); - job.InsertValue(this, kRightInput, value); - job.InsertValue(this, kBottomInput, value); - job.InsertValue(this, kFeatherInput, value); - job.InsertValue(QStringLiteral("resolution_in"), - NodeValue(NodeValue::kVec2, value[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")), this)); + job.InsertValue(value); + job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this)); job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn); - NodeValueTable table = value.Merge(); - if (!job.GetValue(kTextureInput).data().isNull()) { if (!qIsNull(job.GetValue(kLeftInput).data().toDouble()) || !qIsNull(job.GetValue(kRightInput).data().toDouble()) || !qIsNull(job.GetValue(kTopInput).data().toDouble()) || !qIsNull(job.GetValue(kBottomInput).data().toDouble())) { - table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); + table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); } else { - table.Push(NodeValue::kTexture, job.GetValue(kTextureInput).data(), this); + table->Push(NodeValue::kTexture, job.GetValue(kTextureInput).data(), this); } } - - return table; } ShaderCode CropDistortNode::GetShaderCode(const QString &shader_id) const @@ -92,18 +82,18 @@ ShaderCode CropDistortNode::GetShaderCode(const QString &shader_id) const return ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/crop.frag"))); } -void CropDistortNode::DrawGizmos(NodeValueDatabase &db, QPainter *p) +void CropDistortNode::DrawGizmos(const NodeValueRow &row, const NodeGlobals &globals, QPainter *p) { - QVector2D resolution = db[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")).value(); + const QVector2D &resolution = globals.resolution(); const double handle_radius = GetGizmoHandleRadius(p->transform()); p->setPen(QPen(Qt::white, 0)); - double left_pt = resolution.x() * db[kLeftInput].Get(NodeValue::kFloat).toDouble(); - double top_pt = resolution.y() * db[kTopInput].Get(NodeValue::kFloat).toDouble(); - double right_pt = resolution.x() * (1.0 - db[kRightInput].Get(NodeValue::kFloat).toDouble()); - double bottom_pt = resolution.y() * (1.0 - db[kBottomInput].Get(NodeValue::kFloat).toDouble()); + double left_pt = resolution.x() * row[kLeftInput].data().toDouble(); + double top_pt = resolution.y() * row[kTopInput].data().toDouble(); + double right_pt = resolution.x() * (1.0 - row[kRightInput].data().toDouble()); + double bottom_pt = resolution.y() * (1.0 - row[kBottomInput].data().toDouble()); double center_x_pt = lerp(left_pt, right_pt, 0.5); double center_y_pt = lerp(top_pt, bottom_pt, 0.5); @@ -124,7 +114,7 @@ void CropDistortNode::DrawGizmos(NodeValueDatabase &db, QPainter *p) DrawAndExpandGizmoHandles(p, handle_radius, gizmo_resize_handle_, kGizmoScaleCount); } -bool CropDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p) +bool CropDistortNode::GizmoPress(const NodeValueRow &row, const NodeGlobals &globals, const QPointF &p) { bool found_handle = false; @@ -150,7 +140,7 @@ bool CropDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p) || in_rect) { gizmo_drag_ |= kGizmoLeft; - gizmo_start_.append(db[kLeftInput].Get(NodeValue::kFloat)); + gizmo_start_.append(row[kLeftInput].data()); } if (gizmo_active[kGizmoScaleTopLeft] @@ -159,7 +149,7 @@ bool CropDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p) || in_rect) { gizmo_drag_ |= kGizmoTop; - gizmo_start_.append(db[kTopInput].Get(NodeValue::kFloat)); + gizmo_start_.append(row[kTopInput].data()); } if (gizmo_active[kGizmoScaleTopRight] @@ -168,7 +158,7 @@ bool CropDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p) || in_rect) { gizmo_drag_ |= kGizmoRight; - gizmo_start_.append(db[kRightInput].Get(NodeValue::kFloat)); + gizmo_start_.append(row[kRightInput].data()); } if (gizmo_active[kGizmoScaleBottomLeft] @@ -177,11 +167,11 @@ bool CropDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p) || in_rect) { gizmo_drag_ |= kGizmoBottom; - gizmo_start_.append(db[kBottomInput].Get(NodeValue::kFloat)); + gizmo_start_.append(row[kBottomInput].data()); } if (gizmo_drag_ > kGizmoNone) { - gizmo_res_ = db[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")).value(); + gizmo_res_ = globals.resolution(); gizmo_drag_start_ = p; return true; diff --git a/app/node/distort/crop/cropdistortnode.h b/app/node/distort/crop/cropdistortnode.h index a43fcd882..602d5a830 100644 --- a/app/node/distort/crop/cropdistortnode.h +++ b/app/node/distort/crop/cropdistortnode.h @@ -63,7 +63,7 @@ public: virtual void Retranslate() override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual ShaderCode GetShaderCode(const QString &shader_id) const override; @@ -72,9 +72,9 @@ public: return true; } - virtual void DrawGizmos(NodeValueDatabase& db, QPainter *p) override; + virtual void DrawGizmos(const NodeValueRow& row, const NodeGlobals &globals, QPainter *p) override; - virtual bool GizmoPress(NodeValueDatabase& db, const QPointF &p) override; + virtual bool GizmoPress(const NodeValueRow& row, const NodeGlobals &globals, const QPointF &p) override; virtual void GizmoMove(const QPointF &p, const rational &time) override; virtual void GizmoRelease() override; diff --git a/app/node/distort/transform/transformdistortnode.cpp b/app/node/distort/transform/transformdistortnode.cpp index c61895514..45c85acf2 100644 --- a/app/node/distort/transform/transformdistortnode.cpp +++ b/app/node/distort/transform/transformdistortnode.cpp @@ -54,7 +54,7 @@ void TransformDistortNode::Retranslate() SetComboBoxStrings(kInterpolationInput, {tr("Nearest Neighbor"), tr("Bilinear"), tr("Mipmapped Bilinear")}); } -NodeValueTable TransformDistortNode::Value(const QString &output, NodeValueDatabase &value) const +void TransformDistortNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) @@ -62,36 +62,31 @@ NodeValueTable TransformDistortNode::Value(const QString &output, NodeValueDatab QMatrix4x4 generated_matrix = GenerateMatrix(value, true, false, false, false); // Pop texture - NodeValue texture_meta = value[kTextureInput].TakeWithMeta(NodeValue::kTexture); + NodeValue texture_meta = value[kTextureInput]; TexturePtr texture = texture_meta.data().value(); - // Merge table - NodeValueTable table = value[kTextureInput]; - // If we have a texture, generate a matrix and make it happen if (texture) { // Adjust our matrix by the resolutions involved - QMatrix4x4 real_matrix = GenerateAutoScaledMatrix(generated_matrix, value, texture->params()); + QMatrix4x4 real_matrix = GenerateAutoScaledMatrix(generated_matrix, value, globals, texture->params()); if (real_matrix.isIdentity()) { // We don't expect any changes, just push as normal - table.Push(texture_meta); + table->Push(texture_meta); } else { // The matrix will transform things ShaderJob job; job.InsertValue(QStringLiteral("ove_maintex"), NodeValue(NodeValue::kTexture, QVariant::fromValue(texture), this)); job.InsertValue(QStringLiteral("ove_mvpmat"), NodeValue(NodeValue::kMatrix, real_matrix, this)); - job.SetInterpolation(QStringLiteral("ove_maintex"), static_cast(value[kInterpolationInput].Get(NodeValue::kCombo).toInt())); + job.SetInterpolation(QStringLiteral("ove_maintex"), static_cast(value[kInterpolationInput].data().toInt())); // FIXME: This should be optimized, we can use matrix math to determine if this operation will // end up with gaps in the screen that will require an alpha channel. job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn); - table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); + table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); } } - - return table; } ShaderCode TransformDistortNode::GetShaderCode(const QString &shader_id) const @@ -102,9 +97,9 @@ ShaderCode TransformDistortNode::GetShaderCode(const QString &shader_id) const return ShaderCode(); } -bool TransformDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p) +bool TransformDistortNode::GizmoPress(const NodeValueRow &row, const NodeGlobals &globals, const QPointF &p) { - TexturePtr tex = db[kTextureInput].Get(NodeValue::kTexture).value(); + TexturePtr tex = row[kTextureInput].data().value(); if (!tex) { return false; } @@ -128,10 +123,10 @@ bool TransformDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p) if (scaling) { // Dragging scale handle - gizmo_start_ = {db[kScaleInput].Get(NodeValue::kVec2)}; + gizmo_start_ = {row[kScaleInput].data()}; gizmo_drag_ = kScaleInput; - gizmo_scale_uniform_ = db[kUniformScaleInput].Get(NodeValue::kBoolean).toBool(); + gizmo_scale_uniform_ = row[kUniformScaleInput].data().toBool(); if (gizmo_scale_active[kGizmoScaleTopLeft] || gizmo_scale_active[kGizmoScaleTopRight] || gizmo_scale_active[kGizmoScaleBottomLeft] || gizmo_scale_active[kGizmoScaleBottomRight]) { @@ -145,7 +140,7 @@ bool TransformDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p) // Store texture size VideoParams texture_params = tex->params(); QVector2D texture_sz(texture_params.square_pixel_width(), texture_params.height()); - gizmo_scale_anchor_ = db[kAnchorInput].Get(NodeValue::kVec2).value() + texture_sz/2; + gizmo_scale_anchor_ = row[kAnchorInput].data().value() + texture_sz/2; if (gizmo_scale_active[kGizmoScaleTopRight] || gizmo_scale_active[kGizmoScaleBottomRight] @@ -162,26 +157,26 @@ bool TransformDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p) } // Store current matrix - gizmo_matrix_ = GenerateMatrix(db, false, true, true, true); + gizmo_matrix_ = GenerateMatrix(row, false, true, true, true); return true; } else if (gizmo_anchor_pt_.contains(p)) { // Dragging the anchor point specifically - gizmo_start_ = {db[kAnchorInput].Get(NodeValue::kVec2), - db[kPositionInput].Get(NodeValue::kVec2)}; + gizmo_start_ = {row[kAnchorInput].data(), + row[kPositionInput].data()}; gizmo_drag_ = kAnchorInput; // Store current matrix - gizmo_matrix_ = GenerateMatrix(db, false, true, true, false); + gizmo_matrix_ = GenerateMatrix(row, false, true, true, false); return true; } else if (gizmo_rect_.containsPoint(p, Qt::OddEvenFill)) { // Dragging the main rectangle - gizmo_start_ = {db[kPositionInput].Get(NodeValue::kVec2)}; + gizmo_start_ = {row[kPositionInput].data()}; gizmo_drag_ = kPositionInput; return true; @@ -189,7 +184,7 @@ bool TransformDistortNode::GizmoPress(NodeValueDatabase &db, const QPointF &p) } else { // Dragging rotation - gizmo_start_ = {db[kRotationInput].Get(NodeValue::kFloat)}; + gizmo_start_ = {row[kRotationInput].data()}; gizmo_drag_ = kRotationInput; gizmo_start_angle_ = qAtan2(gizmo_drag_pos_.y() - gizmo_anchor_pt_.center().y(), gizmo_drag_pos_.x() - gizmo_anchor_pt_.center().x()); @@ -314,7 +309,7 @@ void TransformDistortNode::GizmoRelease() gizmo_drag_ = nullptr; } -void TransformDistortNode::Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const +void TransformDistortNode::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { // If not connected to output, this will produce nothing NodeOutput out = GetConnectedOutput(kTextureInput); @@ -326,12 +321,12 @@ void TransformDistortNode::Hash(const QString &output, QCryptographicHash &hash, NodeTraverser traverser; traverser.SetCacheVideoParams(video_params); - NodeValueDatabase db = traverser.GenerateDatabase(this, output, TimeRange(time, time + video_params.frame_rate_as_time_base())); - TexturePtr tex = db[kTextureInput].Get(NodeValue::kTexture).value(); + NodeValueRow db = traverser.GenerateRow(this, output, globals.time()); + TexturePtr tex = db[kTextureInput].data().value(); if (tex) { VideoParams tex_params = tex->params(); QMatrix4x4 matrix = GenerateMatrix(db, true, false, false, false); - matrix = GenerateAutoScaledMatrix(matrix, db, tex_params); + matrix = GenerateAutoScaledMatrix(matrix, db, globals, tex_params); if (!matrix.isIdentity()) { // Add fingerprint @@ -340,7 +335,7 @@ void TransformDistortNode::Hash(const QString &output, QCryptographicHash &hash, } } - out.node()->Hash(out.output(), hash, time, video_params); + out.node()->Hash(out.output(), hash, globals, video_params); } QMatrix4x4 TransformDistortNode::AdjustMatrixByResolutions(const QMatrix4x4 &mat, const QVector2D &sequence_res, const QVector2D &texture_res, AutoScaleType autoscale_type) @@ -393,11 +388,11 @@ QPointF TransformDistortNode::CreateScalePoint(double x, double y, const QPointF return mat.map(QPointF(x, y)) + half_res; } -QMatrix4x4 TransformDistortNode::GenerateAutoScaledMatrix(const QMatrix4x4& generated_matrix, NodeValueDatabase& value, const VideoParams& texture_params) const +QMatrix4x4 TransformDistortNode::GenerateAutoScaledMatrix(const QMatrix4x4& generated_matrix, const NodeValueRow& value, const NodeGlobals &globals, const VideoParams& texture_params) const { - QVector2D sequence_res = value[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")).value(); + const QVector2D &sequence_res = globals.resolution(); QVector2D texture_res(texture_params.square_pixel_width(), texture_params.height()); - AutoScaleType autoscale = static_cast(value[kAutoscaleInput].Get(NodeValue::kCombo).toInt()); + AutoScaleType autoscale = static_cast(value[kAutoscaleInput].data().toInt()); return AdjustMatrixByResolutions(generated_matrix, sequence_res, @@ -405,9 +400,9 @@ QMatrix4x4 TransformDistortNode::GenerateAutoScaledMatrix(const QMatrix4x4& gene autoscale); } -void TransformDistortNode::DrawGizmos(NodeValueDatabase &db, QPainter *p) +void TransformDistortNode::DrawGizmos(const NodeValueRow &row, const NodeGlobals &globals, QPainter *p) { - TexturePtr tex = db[kTextureInput].Get(NodeValue::kTexture).value(); + TexturePtr tex = row[kTextureInput].data().value(); if (!tex) { return; } @@ -416,7 +411,7 @@ void TransformDistortNode::DrawGizmos(NodeValueDatabase &db, QPainter *p) p->setPen(QPen(Qt::white, 0)); // Get the sequence resolution - QVector2D sequence_res = db[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")).value(); + const QVector2D &sequence_res = globals.resolution(); QVector2D sequence_half_res = sequence_res/2; QPointF sequence_half_res_pt = sequence_half_res.toPointF(); @@ -425,12 +420,12 @@ void TransformDistortNode::DrawGizmos(NodeValueDatabase &db, QPainter *p) QVector2D tex_sz(tex_params.square_pixel_width(), tex_params.height()); // Retrieve autoscale value - AutoScaleType autoscale = static_cast(db[kAutoscaleInput].Get(NodeValue::kCombo).toInt()); + AutoScaleType autoscale = static_cast(row[kAutoscaleInput].data().toInt()); // Fold values into a matrix for the rectangle QMatrix4x4 rectangle_matrix; rectangle_matrix.scale(sequence_half_res); - rectangle_matrix *= AdjustMatrixByResolutions(GenerateMatrix(db, false, false, false, false), + rectangle_matrix *= AdjustMatrixByResolutions(GenerateMatrix(row, false, false, false, false), sequence_res, tex_sz, autoscale); @@ -454,7 +449,7 @@ void TransformDistortNode::DrawGizmos(NodeValueDatabase &db, QPainter *p) // Draw anchor point QMatrix4x4 anchor_matrix; anchor_matrix.scale(sequence_half_res); - anchor_matrix *= AdjustMatrixByResolutions(GenerateMatrix(db, false, true, false, false), + anchor_matrix *= AdjustMatrixByResolutions(GenerateMatrix(row, false, true, false, false), sequence_res, tex_sz, autoscale); diff --git a/app/node/distort/transform/transformdistortnode.h b/app/node/distort/transform/transformdistortnode.h index e9c2016dd..ed10b8427 100644 --- a/app/node/distort/transform/transformdistortnode.h +++ b/app/node/distort/transform/transformdistortnode.h @@ -65,7 +65,7 @@ public: virtual void Retranslate() override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual ShaderCode GetShaderCode(const QString& shader_id) const override; @@ -74,13 +74,13 @@ public: return true; } - virtual void DrawGizmos(NodeValueDatabase& db, QPainter *p) override; + virtual void DrawGizmos(const NodeValueRow &row, const NodeGlobals &globals, QPainter *p) override; - virtual bool GizmoPress(NodeValueDatabase& db, const QPointF &p) override; + virtual bool GizmoPress(const NodeValueRow &row, const NodeGlobals &globals, const QPointF &p) override; virtual void GizmoMove(const QPointF &p, const rational &time) override; virtual void GizmoRelease() override; - virtual void Hash(const QString& output, QCryptographicHash& hash, const rational &time, const VideoParams& video_params) const override; + virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override; enum AutoScaleType { kAutoScaleNone, @@ -101,7 +101,7 @@ public: private: static QPointF CreateScalePoint(double x, double y, const QPointF& half_res, const QMatrix4x4& mat); - QMatrix4x4 GenerateAutoScaledMatrix(const QMatrix4x4 &generated_matrix, NodeValueDatabase &db, const VideoParams &texture_params) const; + QMatrix4x4 GenerateAutoScaledMatrix(const QMatrix4x4 &generated_matrix, const NodeValueRow &db, const NodeGlobals &globals, const VideoParams &texture_params) const; // Gizmo variables QString gizmo_drag_; diff --git a/app/node/filter/blur/blur.cpp b/app/node/filter/blur/blur.cpp index 463e27fec..dcfe21e45 100644 --- a/app/node/filter/blur/blur.cpp +++ b/app/node/filter/blur/blur.cpp @@ -87,22 +87,14 @@ ShaderCode BlurFilterNode::GetShaderCode(const QString &shader_id) const return ShaderCode(FileFunctions::ReadFileAsString(":/shaders/blur.frag")); } -NodeValueTable BlurFilterNode::Value(const QString &output, NodeValueDatabase &value) const +void BlurFilterNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) ShaderJob job; - job.InsertValue(this, kTextureInput, value); - job.InsertValue(this, kMethodInput, value); - job.InsertValue(this, kRadiusInput, value); - job.InsertValue(this, kHorizInput, value); - job.InsertValue(this, kVertInput, value); - job.InsertValue(this, kRepeatEdgePixelsInput, value); - job.InsertValue(QStringLiteral("resolution_in"), - NodeValue(NodeValue::kVec2, value[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")), this)); - - NodeValueTable table = value.Merge(); + job.InsertValue(value); + job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this)); // If there's no texture, no need to run an operation if (!job.GetValue(kTextureInput).data().isNull()) { @@ -121,16 +113,14 @@ NodeValueTable BlurFilterNode::Value(const QString &output, NodeValueDatabase &v job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn); } - table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); + table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); } else { // If we're not performing the blur job, just push the texture - table.Push(job.GetValue(kTextureInput)); + table->Push(job.GetValue(kTextureInput)); } } - - return table; } } diff --git a/app/node/filter/blur/blur.h b/app/node/filter/blur/blur.h index fb4d9e851..1e3aeece8 100644 --- a/app/node/filter/blur/blur.h +++ b/app/node/filter/blur/blur.h @@ -43,7 +43,7 @@ public: virtual void Retranslate() override; virtual ShaderCode GetShaderCode(const QString &shader_id) const override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; static const QString kTextureInput; static const QString kMethodInput; diff --git a/app/node/filter/mosaic/mosaicfilternode.cpp b/app/node/filter/mosaic/mosaicfilternode.cpp index ebe91462d..2ea42e469 100644 --- a/app/node/filter/mosaic/mosaicfilternode.cpp +++ b/app/node/filter/mosaic/mosaicfilternode.cpp @@ -44,34 +44,28 @@ void MosaicFilterNode::Retranslate() SetInputName(kVertInput, tr("Vertical")); } -NodeValueTable MosaicFilterNode::Value(const QString &output, NodeValueDatabase &value) const +void MosaicFilterNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) ShaderJob job; - job.InsertValue(this, kTextureInput, value); - job.InsertValue(this, kHorizInput, value); - job.InsertValue(this, kVertInput, value); + job.InsertValue(value); // Mipmapping makes this look weird, so we just use bilinear for finding the color of each block job.SetInterpolation(kTextureInput, Texture::kLinear); - NodeValueTable table = value.Merge(); - if (!job.GetValue(kTextureInput).data().isNull()) { TexturePtr texture = job.GetValue(kTextureInput).data().value(); if (texture && job.GetValue(kHorizInput).data().toInt() != texture->width() && job.GetValue(kVertInput).data().toInt() != texture->height()) { - table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); + table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); } else { - table.Push(job.GetValue(kTextureInput)); + table->Push(job.GetValue(kTextureInput)); } } - - return table; } ShaderCode MosaicFilterNode::GetShaderCode(const QString &shader_id) const diff --git a/app/node/filter/mosaic/mosaicfilternode.h b/app/node/filter/mosaic/mosaicfilternode.h index 5578858a7..fcd906dd6 100644 --- a/app/node/filter/mosaic/mosaicfilternode.h +++ b/app/node/filter/mosaic/mosaicfilternode.h @@ -60,7 +60,7 @@ public: virtual void Retranslate() override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual ShaderCode GetShaderCode(const QString &shader_id) const override; static const QString kTextureInput; diff --git a/app/node/filter/stroke/stroke.cpp b/app/node/filter/stroke/stroke.cpp index e35dbb682..aa56f01fd 100644 --- a/app/node/filter/stroke/stroke.cpp +++ b/app/node/filter/stroke/stroke.cpp @@ -82,32 +82,23 @@ void StrokeFilterNode::Retranslate() SetInputName(kInnerInput, tr("Inner")); } -NodeValueTable StrokeFilterNode::Value(const QString &output, NodeValueDatabase &value) const +void StrokeFilterNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) ShaderJob job; - job.InsertValue(this, kTextureInput, value); - job.InsertValue(this, kColorInput, value); - job.InsertValue(this, kRadiusInput, value); - job.InsertValue(this, kOpacityInput, value); - job.InsertValue(this, kInnerInput, value); - job.InsertValue(QStringLiteral("resolution_in"), - NodeValue(NodeValue::kVec2, value[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")), this)); - - NodeValueTable table = value.Merge(); + job.InsertValue(value); + job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this)); if (!job.GetValue(kTextureInput).data().isNull()) { if (job.GetValue(kRadiusInput).data().toDouble() > 0.0 && job.GetValue(kOpacityInput).data().toDouble() > 0.0) { - table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); + table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); } else { - table.Push(job.GetValue(kTextureInput)); + table->Push(job.GetValue(kTextureInput)); } } - - return table; } ShaderCode StrokeFilterNode::GetShaderCode(const QString &shader_id) const diff --git a/app/node/filter/stroke/stroke.h b/app/node/filter/stroke/stroke.h index 7b2117bf5..dc95d1490 100644 --- a/app/node/filter/stroke/stroke.h +++ b/app/node/filter/stroke/stroke.h @@ -42,7 +42,7 @@ public: virtual void Retranslate() override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual ShaderCode GetShaderCode(const QString &shader_id) const override; static const QString kTextureInput; diff --git a/app/node/generator/matrix/matrix.cpp b/app/node/generator/matrix/matrix.cpp index 22744c8d8..0dfd3d801 100644 --- a/app/node/generator/matrix/matrix.cpp +++ b/app/node/generator/matrix/matrix.cpp @@ -88,18 +88,16 @@ void MatrixGenerator::Retranslate() SetInputName(kAnchorInput, tr("Anchor Point")); } -NodeValueTable MatrixGenerator::Value(const QString &output, NodeValueDatabase &value) const +void MatrixGenerator::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) // Push matrix output QMatrix4x4 mat = GenerateMatrix(value, true, false, false, false); - NodeValueTable out = value.Merge(); - out.Push(NodeValue::kMatrix, mat, this); - return out; + table->Push(NodeValue::kMatrix, mat, this); } -QMatrix4x4 MatrixGenerator::GenerateMatrix(NodeValueDatabase &value, bool take, bool ignore_anchor, bool ignore_position, bool ignore_scale) const +QMatrix4x4 MatrixGenerator::GenerateMatrix(const NodeValueRow &value, bool take, bool ignore_anchor, bool ignore_position, bool ignore_scale) const { QVector2D anchor; QVector2D position; @@ -108,47 +106,47 @@ QMatrix4x4 MatrixGenerator::GenerateMatrix(NodeValueDatabase &value, bool take, if (!ignore_anchor) { if (take) { // Take and store - anchor = value[kAnchorInput].Take(NodeValue::kVec2).value(); + anchor = value[kAnchorInput].data().value(); } else { // Get and store - anchor = value[kAnchorInput].Get(NodeValue::kVec2).value(); + anchor = value[kAnchorInput].data().value(); } } else if (take) { // Just take - value[kAnchorInput].Take(NodeValue::kVec2).value(); + value[kAnchorInput].data().value(); } if (!ignore_scale) { if (take) { - scale = value[kScaleInput].Take(NodeValue::kVec2).value(); + scale = value[kScaleInput].data().value(); } else { - scale = value[kScaleInput].Get(NodeValue::kVec2).value(); + scale = value[kScaleInput].data().value(); } } else if (take) { - value[kScaleInput].Take(NodeValue::kVec2).value(); + value[kScaleInput].data().value(); } if (!ignore_position) { if (take) { - position = value[kPositionInput].Take(NodeValue::kVec2).value(); + position = value[kPositionInput].data().value(); } else { - position = value[kPositionInput].Get(NodeValue::kVec2).value(); + position = value[kPositionInput].data().value(); } } else if (take) { - value[kPositionInput].Take(NodeValue::kVec2).value(); + value[kPositionInput].data().value(); } if (take) { return GenerateMatrix(position, - value[kRotationInput].Take(NodeValue::kFloat).toFloat(), + value[kRotationInput].data().toFloat(), scale, - value[kUniformScaleInput].Take(NodeValue::kBoolean).toBool(), + value[kUniformScaleInput].data().toBool(), anchor); } else { return GenerateMatrix(position, - value[kRotationInput].Get(NodeValue::kFloat).toFloat(), + value[kRotationInput].data().toFloat(), scale, - value[kUniformScaleInput].Get(NodeValue::kBoolean).toBool(), + value[kUniformScaleInput].data().toBool(), anchor); } diff --git a/app/node/generator/matrix/matrix.h b/app/node/generator/matrix/matrix.h index 37091b91e..f356d1987 100644 --- a/app/node/generator/matrix/matrix.h +++ b/app/node/generator/matrix/matrix.h @@ -46,7 +46,7 @@ public: virtual void Retranslate() override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; static const QString kPositionInput; static const QString kRotationInput; @@ -55,7 +55,7 @@ public: static const QString kAnchorInput; protected: - QMatrix4x4 GenerateMatrix(NodeValueDatabase &value, bool take, bool ignore_anchor, bool ignore_position, bool ignore_scale) const; + QMatrix4x4 GenerateMatrix(const NodeValueRow &value, bool take, bool ignore_anchor, bool ignore_position, bool ignore_scale) const; static QMatrix4x4 GenerateMatrix(const QVector2D &pos, const float &rot, const QVector2D &scale, diff --git a/app/node/generator/polygon/polygon.cpp b/app/node/generator/polygon/polygon.cpp index f74bd5a97..f0704aec8 100644 --- a/app/node/generator/polygon/polygon.cpp +++ b/app/node/generator/polygon/polygon.cpp @@ -86,20 +86,17 @@ ShaderCode PolygonGenerator::GetShaderCode(const QString &shader_id) const return ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/polygon.frag"))); } -NodeValueTable PolygonGenerator::Value(const QString &output, NodeValueDatabase &value) const +void PolygonGenerator::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) ShaderJob job; - job.InsertValue(this, kPointsInput, value); - job.InsertValue(this, kColorInput, value); - job.InsertValue(QStringLiteral("resolution_in"), value[QStringLiteral("global")].GetWithMeta(NodeValue::kVec2, QStringLiteral("resolution"))); + job.InsertValue(value); + job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this)); job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn); - NodeValueTable table = value.Merge(); - table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); - return table; + table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); } bool PolygonGenerator::HasGizmos() const diff --git a/app/node/generator/polygon/polygon.h b/app/node/generator/polygon/polygon.h index 7daa5f015..6b6e82fb6 100644 --- a/app/node/generator/polygon/polygon.h +++ b/app/node/generator/polygon/polygon.h @@ -44,7 +44,7 @@ public: virtual void Retranslate() override; virtual ShaderCode GetShaderCode(const QString& shader_id) const override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual bool HasGizmos() const override; //virtual void DrawGizmos(NodeValueDatabase& db, QPainter *p) const override; diff --git a/app/node/generator/shape/shapenode.cpp b/app/node/generator/shape/shapenode.cpp index 0c8f258a4..d5d3734da 100644 --- a/app/node/generator/shape/shapenode.cpp +++ b/app/node/generator/shape/shapenode.cpp @@ -68,22 +68,17 @@ ShaderCode ShapeNode::GetShaderCode(const QString &shader_id) const return ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/shape.frag"))); } -NodeValueTable ShapeNode::Value(const QString &output, NodeValueDatabase &value) const +void ShapeNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) ShaderJob job; - job.InsertValue(this, kTypeInput, value); - job.InsertValue(this, kPositionInput, value); - job.InsertValue(this, kSizeInput, value); - job.InsertValue(this, kColorInput, value); - job.InsertValue(QStringLiteral("resolution_in"), value[QStringLiteral("global")].GetWithMeta(NodeValue::kVec2, QStringLiteral("resolution"))); + job.InsertValue(value); + job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this)); job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn); - NodeValueTable table = value.Merge(); - table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); - return table; + table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); } } diff --git a/app/node/generator/shape/shapenode.h b/app/node/generator/shape/shapenode.h index 0381be00d..eb20a18ad 100644 --- a/app/node/generator/shape/shapenode.h +++ b/app/node/generator/shape/shapenode.h @@ -47,7 +47,7 @@ public: virtual void Retranslate() override; virtual ShaderCode GetShaderCode(const QString& shader_id) const override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; static QString kTypeInput; diff --git a/app/node/generator/solid/solid.cpp b/app/node/generator/solid/solid.cpp index 8b9f294f7..c093e48cb 100644 --- a/app/node/generator/solid/solid.cpp +++ b/app/node/generator/solid/solid.cpp @@ -62,16 +62,13 @@ void SolidGenerator::Retranslate() SetInputName(kColorInput, tr("Color")); } -NodeValueTable SolidGenerator::Value(const QString &output, NodeValueDatabase &value) const +void SolidGenerator::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) ShaderJob job; - job.InsertValue(this, kColorInput, value); - - NodeValueTable table = value.Merge(); - table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); - return table; + job.InsertValue(value); + table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); } ShaderCode SolidGenerator::GetShaderCode(const QString &shader_id) const diff --git a/app/node/generator/solid/solid.h b/app/node/generator/solid/solid.h index 38c9981b9..aace92bbf 100644 --- a/app/node/generator/solid/solid.h +++ b/app/node/generator/solid/solid.h @@ -42,7 +42,7 @@ public: virtual void Retranslate() override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual ShaderCode GetShaderCode(const QString &shader_id) const override; static const QString kColorInput; diff --git a/app/node/generator/text/text.cpp b/app/node/generator/text/text.cpp index 6a9ff27bb..338a5d464 100644 --- a/app/node/generator/text/text.cpp +++ b/app/node/generator/text/text.cpp @@ -89,26 +89,17 @@ void TextGenerator::Retranslate() SetComboBoxStrings(kVAlignInput, {tr("Top"), tr("Center"), tr("Bottom")}); } -NodeValueTable TextGenerator::Value(const QString &output, NodeValueDatabase &value) const +void TextGenerator::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) GenerateJob job; - job.InsertValue(this, kTextInput, value); - job.InsertValue(this, kHtmlInput, value); - job.InsertValue(this, kColorInput, value); - job.InsertValue(this, kVAlignInput, value); - job.InsertValue(this, kFontInput, value); - job.InsertValue(this, kFontSizeInput, value); + job.InsertValue(value); job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn); - NodeValueTable table = value.Merge(); - if (!job.GetValue(kTextInput).data().toString().isEmpty()) { - table.Push(NodeValue::kGenerateJob, QVariant::fromValue(job), this); + table->Push(NodeValue::kGenerateJob, QVariant::fromValue(job), this); } - - return table; } void TextGenerator::GenerateFrame(FramePtr frame, const GenerateJob& job) const diff --git a/app/node/generator/text/text.h b/app/node/generator/text/text.h index e58525d0c..60534fd3d 100644 --- a/app/node/generator/text/text.h +++ b/app/node/generator/text/text.h @@ -42,7 +42,7 @@ public: virtual void Retranslate() override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual void GenerateFrame(FramePtr frame, const GenerateJob &job) const override; diff --git a/app/node/globals.cpp b/app/node/globals.cpp new file mode 100644 index 000000000..171c2de35 --- /dev/null +++ b/app/node/globals.cpp @@ -0,0 +1,25 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2021 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#include "globals.h" + +namespace olive { + +} diff --git a/app/node/globals.h b/app/node/globals.h new file mode 100644 index 000000000..d80da2a5c --- /dev/null +++ b/app/node/globals.h @@ -0,0 +1,62 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2021 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#ifndef NODEGLOBALS_H +#define NODEGLOBALS_H + +#include + +#include "common/timerange.h" + +namespace olive { + +class NodeGlobals +{ +public: + NodeGlobals(const QVector2D &resolution, const TimeRange &time) : + resolution_(resolution), + time_(time) + {} + + const QVector2D &resolution() const + { + return resolution_; + } + + const TimeRange &time() const + { + return time_; + } + + void set_time(const TimeRange &time) + { + time_ = time; + } + +private: + QVector2D resolution_; + + TimeRange time_; + +}; + +} + +#endif // NODEGLOBALS_H diff --git a/app/node/input/time/timeinput.cpp b/app/node/input/time/timeinput.cpp index 3b974f1bb..d9d704851 100644 --- a/app/node/input/time/timeinput.cpp +++ b/app/node/input/time/timeinput.cpp @@ -51,27 +51,23 @@ QString TimeInput::Description() const return tr("Generates the time (in seconds) at this frame."); } -NodeValueTable TimeInput::Value(const QString &output, NodeValueDatabase &value) const +void TimeInput::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) - NodeValueTable table = value.Merge(); - - table.Push(NodeValue::kFloat, - value[QStringLiteral("global")].Get(NodeValue::kFloat, QStringLiteral("time_in")), - this, - false, - QStringLiteral("time")); - - return table; + table->Push(NodeValue::kFloat, + globals.time().in().toDouble(), + this, + false, + QStringLiteral("time")); } -void TimeInput::Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const +void TimeInput::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { - Node::Hash(output, hash, time, video_params); + Node::Hash(output, hash, globals, video_params); // Make sure time is hashed - hash.addData(NodeValue::ValueToBytes(NodeValue::kRational, QVariant::fromValue(time))); + hash.addData(NodeValue::ValueToBytes(NodeValue::kFloat, globals.time().in().toDouble())); } } diff --git a/app/node/input/time/timeinput.h b/app/node/input/time/timeinput.h index 570acb9e2..4df699a7e 100644 --- a/app/node/input/time/timeinput.h +++ b/app/node/input/time/timeinput.h @@ -40,9 +40,9 @@ public: virtual QVector Category() const override; virtual QString Description() const override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase& value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; - virtual void Hash(const QString& output, QCryptographicHash& hash, const rational& time, const VideoParams& video_params) const override; + virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override; }; diff --git a/app/node/input/value/valuenode.cpp b/app/node/input/value/valuenode.cpp index 9349c850d..39a3d247a 100644 --- a/app/node/input/value/valuenode.cpp +++ b/app/node/input/value/valuenode.cpp @@ -59,14 +59,13 @@ void ValueNode::Retranslate() SetComboBoxStrings(kTypeInput, type_names); } -NodeValueTable ValueNode::Value(const QString &output, NodeValueDatabase &value) const +void ValueNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { + Q_UNUSED(globals) Q_UNUSED(output) - // Pop combobox value off table because no other node will need it - value[kTypeInput].Take(NodeValue::kCombo); - - return value.Merge(); + // Ensure value is pushed onto the table + table->Push(value[kValueInput]); } void ValueNode::InputValueChangedEvent(const QString &input, int element) diff --git a/app/node/input/value/valuenode.h b/app/node/input/value/valuenode.h index fc5d8bf98..389dc56ad 100644 --- a/app/node/input/value/valuenode.h +++ b/app/node/input/value/valuenode.h @@ -63,7 +63,7 @@ public: virtual void Retranslate() override; - virtual NodeValueTable Value(const QString &output, NodeValueDatabase &value) const override; + virtual void Value(const QString &output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; protected: virtual void InputValueChangedEvent(const QString &input, int element) override; diff --git a/app/node/math/math/math.cpp b/app/node/math/math/math.cpp index be35c56f2..e788d0477 100644 --- a/app/node/math/math/math.cpp +++ b/app/node/math/math/math.cpp @@ -88,35 +88,33 @@ ShaderCode MathNode::GetShaderCode(const QString &shader_id) const return GetShaderCodeInternal(shader_id, kParamAIn, kParamBIn); } -NodeValueTable MathNode::Value(const QString &output, NodeValueDatabase &value) const +void MathNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) // Auto-detect what values to operate with - // FIXME: Add manual override for this - PairingCalculator calc(value[kParamAIn], value[kParamBIn]); + // FIXME: Very inefficient + NodeValueTable at, bt; + at.Push(value[kParamAIn]); + bt.Push(value[kParamBIn]); + PairingCalculator calc(at, bt); // Do nothing if no pairing was found if (!calc.FoundMostLikelyPairing()) { - return value.Merge(); + return; } - NodeValue val_a = calc.GetMostLikelyValueA(); - value[kParamAIn].Remove(val_a); - - NodeValue val_b = calc.GetMostLikelyValueB(); - value[kParamBIn].Remove(val_b); - - return ValueInternal(value, - GetOperation(), + return ValueInternal(GetOperation(), calc.GetMostLikelyPairing(), kParamAIn, - val_a, + calc.GetMostLikelyValueA(), kParamBIn, - val_b); + calc.GetMostLikelyValueB(), + globals, + table); } -void MathNode::ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const +void MathNode::ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const { return ProcessSamplesInternal(values, GetOperation(), kParamAIn, kParamBIn, input, output, index); } diff --git a/app/node/math/math/math.h b/app/node/math/math/math.h index 24571aab9..8d5bd3a4c 100644 --- a/app/node/math/math/math.h +++ b/app/node/math/math/math.h @@ -54,9 +54,9 @@ public: SetStandardValue(kMethodIn, o); } - virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; - virtual void ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override; + virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override; static const QString kMethodIn; static const QString kParamAIn; diff --git a/app/node/math/math/mathbase.cpp b/app/node/math/math/mathbase.cpp index faceab1ab..d76f878aa 100644 --- a/app/node/math/math/mathbase.cpp +++ b/app/node/math/math/mathbase.cpp @@ -163,21 +163,19 @@ void MathNodeBase::PushVector(NodeValueTable *output, olive::NodeValue::Type typ } } -NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation operation, Pairing pairing, const QString& param_a_in, const NodeValue& val_a, const QString& param_b_in, const NodeValue& val_b) const +void MathNodeBase::ValueInternal(Operation operation, Pairing pairing, const QString& param_a_in, const NodeValue& val_a, const QString& param_b_in, const NodeValue& val_b, const NodeGlobals &globals, NodeValueTable *output) const { - NodeValueTable output = value.Merge(); - switch (pairing) { case kPairNumberNumber: { if (val_a.type() == NodeValue::kRational && val_b.type() == NodeValue::kRational && operation != kOpPower) { // Preserve rationals - output.Push(NodeValue::kRational, + output->Push(NodeValue::kRational, QVariant::fromValue(PerformAddSubMultDiv(operation, val_a.data().value(), val_b.data().value())), this); } else { - output.Push(NodeValue::kFloat, + output->Push(NodeValue::kFloat, PerformAll(operation, RetrieveNumber(val_a), RetrieveNumber(val_b)), this); } @@ -188,7 +186,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o { // We convert all vectors to QVector4D just for simplicity and exploit the fact that kVec4 is higher than kVec2 in // the enum to find the largest data type - PushVector(&output, + PushVector(output, qMax(val_a.type(), val_b.type()), PerformAddSubMultDiv(operation, RetrieveVector(val_a), RetrieveVector(val_b))); break; @@ -200,7 +198,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o QVector4D vec = (val_a.type() == NodeValue::kMatrix) ? RetrieveVector(val_b) : RetrieveVector(val_a); // Only valid operation is multiply - PushVector(&output, + PushVector(output, qMax(val_a.type(), val_b.type()), PerformMult(operation, vec, matrix)); break; @@ -212,7 +210,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o float number = RetrieveNumber((val_a.type() & NodeValue::kMatrix) ? val_b : val_a); // Only multiply and divide are valid operations - PushVector(&output, val_a.type(), PerformMultDiv(operation, vec, number)); + PushVector(output, val_a.type(), PerformMultDiv(operation, vec, number)); break; } @@ -220,7 +218,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o { QMatrix4x4 mat_a = val_a.data().value(); QMatrix4x4 mat_b = val_b.data().value(); - output.Push(NodeValue::kMatrix, PerformAddSubMult(operation, mat_a, mat_b), this); + output->Push(NodeValue::kMatrix, PerformAddSubMult(operation, mat_a, mat_b), this); break; } @@ -230,7 +228,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o Color col_b = val_b.data().value(); // Only add and subtract are valid operations - output.Push(NodeValue::kColor, QVariant::fromValue(PerformAddSub(operation, col_a, col_b)), this); + output->Push(NodeValue::kColor, QVariant::fromValue(PerformAddSub(operation, col_a, col_b)), this); break; } @@ -241,7 +239,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o float num = (val_a.type() == NodeValue::kColor) ? val_b.data().toFloat() : val_a.data().toFloat(); // Only multiply and divide are valid operations - output.Push(NodeValue::kColor, QVariant::fromValue(PerformMult(operation, col, num)), this); + output->Push(NodeValue::kColor, QVariant::fromValue(PerformMult(operation, col, num)), this); break; } @@ -275,7 +273,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o } } - output.Push(NodeValue::kSamples, QVariant::fromValue(mixed_samples), this); + output->Push(NodeValue::kSamples, QVariant::fromValue(mixed_samples), this); break; } @@ -307,7 +305,7 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o } } else if (pairing == kPairTextureMatrix) { // Only allow matrix multiplication - QVector2D sequence_res = value[QStringLiteral("global")].Get(NodeValue::kVec2, QStringLiteral("resolution")).value(); + const QVector2D &sequence_res = globals.resolution(); QVector2D texture_res(texture->params().width() * texture->pixel_aspect_ratio().toDouble(), texture->params().height()); QMatrix4x4 adjusted_matrix = TransformDistortNode::AdjustMatrixByResolutions(number_val.data().value(), @@ -328,10 +326,10 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o if (operation_is_noop) { // Just push texture as-is - output.Push(texture_val); + output->Push(texture_val); } else { // Push shader job - output.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); + output->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); } break; } @@ -357,9 +355,9 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o } } - output.Push(NodeValue::kSamples, QVariant::fromValue(job.samples()), this); + output->Push(NodeValue::kSamples, QVariant::fromValue(job.samples()), this); } else { - output.Push(NodeValue::kSampleJob, QVariant::fromValue(job), this); + output->Push(NodeValue::kSampleJob, QVariant::fromValue(job), this); } } break; @@ -369,17 +367,15 @@ NodeValueTable MathNodeBase::ValueInternal(NodeValueDatabase &value, Operation o case kPairCount: break; } - - return output; } -void MathNodeBase::ProcessSamplesInternal(NodeValueDatabase &values, MathNodeBase::Operation operation, const QString ¶m_a_in, const QString ¶m_b_in, const SampleBufferPtr input, SampleBufferPtr output, int index) const +void MathNodeBase::ProcessSamplesInternal(const NodeValueRow &values, MathNodeBase::Operation operation, const QString ¶m_a_in, const QString ¶m_b_in, const SampleBufferPtr input, SampleBufferPtr output, int index) const { // This function is only used for sample+number pairing - NodeValue number_val = values[param_a_in].GetWithMeta(NodeValue::kNumber); + NodeValue number_val = values[param_a_in]; if (number_val.type() == NodeValue::kNone) { - number_val = values[param_b_in].GetWithMeta(NodeValue::kNumber); + number_val = values[param_b_in]; if (number_val.type() == NodeValue::kNone) { return; @@ -460,8 +456,6 @@ MathNodeBase::PairingCalculator::PairingCalculator(const NodeValueTable &table_a QVector MathNodeBase::PairingCalculator::GetPairLikelihood(const NodeValueTable &table) { - // FIXME: When we introduce a manual override, placing it here would be the least problematic - QVector likelihood(kPairCount, -1); for (int i=0;i(); TexturePtr blend_tex = job.GetValue(kBlendIn).data().value(); @@ -89,10 +86,10 @@ NodeValueTable MergeNode::Value(const QString &output, NodeValueDatabase &value) if (base_tex || blend_tex) { if (!base_tex || (blend_tex && blend_tex->channel_count() < VideoParams::kRGBAChannelCount)) { // We only have a blend texture or the blend texture is RGB only, no need to alpha over - table.Push(job.GetValue(kBlendIn)); + table->Push(job.GetValue(kBlendIn)); } else if (!blend_tex) { // We only have a base texture, no need to alpha over - table.Push(job.GetValue(kBaseIn)); + table->Push(job.GetValue(kBaseIn)); } else { // We have both textures, push the job if (base_tex->channel_count() < VideoParams::kRGBAChannelCount) { @@ -100,19 +97,17 @@ NodeValueTable MergeNode::Value(const QString &output, NodeValueDatabase &value) job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOff); } - table.Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); + table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); } } - - return table; } -void MergeNode::Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const +void MergeNode::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { NodeTraverser traverser; traverser.SetCacheVideoParams(video_params); - NodeValueDatabase db = traverser.GenerateDatabase(this, output, TimeRange(time, time+video_params.frame_rate_as_time_base())); + NodeValueDatabase db = traverser.GenerateDatabase(this, output, globals.time()); TexturePtr base_tex = db[kBaseIn].Get(NodeValue::kTexture).value(); TexturePtr blend_tex = db[kBlendIn].Get(NodeValue::kTexture).value(); @@ -128,12 +123,12 @@ void MergeNode::Hash(const QString &output, QCryptographicHash &hash, const rati if (!passthrough_base) { NodeOutput blend_output = GetConnectedOutput(kBlendIn); - blend_output.node()->Hash(blend_output.output(), hash, time, video_params); + blend_output.node()->Hash(blend_output.output(), hash, globals, video_params); } if (!passthrough_blend) { NodeOutput base_output = GetConnectedOutput(kBaseIn); - base_output.node()->Hash(base_output.output(), hash, time, video_params); + base_output.node()->Hash(base_output.output(), hash, globals, video_params); } Q_ASSERT(!passthrough_base || !passthrough_blend); diff --git a/app/node/math/merge/merge.h b/app/node/math/merge/merge.h index 0c9f9bd3a..66c465da1 100644 --- a/app/node/math/merge/merge.h +++ b/app/node/math/merge/merge.h @@ -43,12 +43,12 @@ public: virtual void Retranslate() override; virtual ShaderCode GetShaderCode(const QString &shader_id) const override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; static const QString kBaseIn; static const QString kBlendIn; - virtual void Hash(const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const override; + virtual void Hash(const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override; private: NodeInput* base_in_; diff --git a/app/node/math/trigonometry/trigonometry.cpp b/app/node/math/trigonometry/trigonometry.cpp index 7bdf96799..909c83074 100644 --- a/app/node/math/trigonometry/trigonometry.cpp +++ b/app/node/math/trigonometry/trigonometry.cpp @@ -76,13 +76,11 @@ void TrigonometryNode::Retranslate() SetInputName(kMethodIn, tr("Method")); } -NodeValueTable TrigonometryNode::Value(const QString &output, NodeValueDatabase &value) const +void TrigonometryNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(output) - float x = value[kXIn].Take(NodeValue::kFloat).toFloat(); - - NodeValueTable table = value.Merge(); + double x = value[kXIn].data().toFloat(); switch (static_cast(GetStandardValue(kMethodIn).toInt())) { case kOpSine: @@ -114,9 +112,7 @@ NodeValueTable TrigonometryNode::Value(const QString &output, NodeValueDatabase break; } - table.Push(NodeValue::kFloat, x, this); - - return table; + table->Push(NodeValue::kFloat, x, this); } } diff --git a/app/node/math/trigonometry/trigonometry.h b/app/node/math/trigonometry/trigonometry.h index d68505d62..04d7bf329 100644 --- a/app/node/math/trigonometry/trigonometry.h +++ b/app/node/math/trigonometry/trigonometry.h @@ -42,7 +42,7 @@ public: virtual void Retranslate() override; - virtual NodeValueTable Value(const QString& output, NodeValueDatabase &value) const override; + virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; static const QString kMethodIn; static const QString kXIn; diff --git a/app/node/node.cpp b/app/node/node.cpp index e83b1f71f..6142d002a 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -43,16 +43,14 @@ namespace olive { const QString Node::kDefaultOutput = QStringLiteral("output"); -Node::Node(bool create_default_output) : +Node::Node() : can_be_deleted_(true), override_color_(-1), folder_(nullptr), operation_stack_(0), cache_result_(false) { - if (create_default_output) { - AddOutput(); - } + AddOutput(); } Node::~Node() @@ -1015,11 +1013,13 @@ Node::InputFlags Node::GetInputFlags(const QString &input) const } } -NodeValueTable Node::Value(const QString& output, NodeValueDatabase &value) const +void Node::Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const { + // Do nothing Q_UNUSED(output) - - return value.Merge(); + Q_UNUSED(value) + Q_UNUSED(globals) + Q_UNUSED(table) } void Node::InvalidateCache(const TimeRange &range, const QString &from, int element, InvalidateCacheOptions options) @@ -1422,11 +1422,11 @@ bool Node::HasGizmos() const return false; } -void Node::DrawGizmos(NodeValueDatabase &, QPainter *) +void Node::DrawGizmos(const NodeValueRow &, const NodeGlobals &, QPainter *) { } -bool Node::GizmoPress(NodeValueDatabase &, const QPointF &) +bool Node::GizmoPress(const NodeValueRow &, const NodeGlobals &, const QPointF &) { return false; } @@ -1453,7 +1453,7 @@ void Node::SetLabel(const QString &s) } } -void Node::Hash(const QString &output, QCryptographicHash &hash, const rational& time, const VideoParams &video_params) const +void Node::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { // Add this Node's ID and output being used HashAddNodeSignature(hash, output); @@ -1467,7 +1467,7 @@ void Node::Hash(const QString &output, QCryptographicHash &hash, const rational& int arr_sz = InputArraySize(input); for (int i=-1; i Node::GetDependenciesInternal(bool traverse, bool exclusive_only return list; } -void Node::HashInputElement(QCryptographicHash &hash, const QString& input, int element, const rational &time, const VideoParams& video_params) const +void Node::HashInputElement(QCryptographicHash &hash, const QString& input, int element, const NodeGlobals &globals, const VideoParams& video_params) const { // Get time adjustment // For a single frame, we only care about one of the times - rational input_time = InputTimeAdjustment(input, element, TimeRange(time, time)).in(); + TimeRange input_time = InputTimeAdjustment(input, element, globals.time()); if (IsInputConnected(input, element)) { // Traverse down this edge NodeOutput output = GetConnectedOutput(input, element); - output.node()->Hash(output.output(), hash, input_time, video_params); + NodeGlobals new_globals = globals; + new_globals.set_time(input_time); + output.node()->Hash(output.output(), hash, new_globals, video_params); } else { // Grab the value at this time - QVariant value = GetValueAtTime(input, input_time, element); + QVariant value = GetValueAtTime(input, input_time.in(), element); hash.addData(NodeValue::ValueToBytes(GetInputDataType(input), value)); } } @@ -1629,7 +1631,7 @@ ShaderCode Node::GetShaderCode(const QString &shader_id) const return ShaderCode(QString(), QString()); } -void Node::ProcessSamples(NodeValueDatabase &, const SampleBufferPtr, SampleBufferPtr, int) const +void Node::ProcessSamples(const NodeValueRow &, const SampleBufferPtr, SampleBufferPtr, int) const { } diff --git a/app/node/node.h b/app/node/node.h index dde2e706f..6f67d59b9 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -34,6 +34,7 @@ #include "common/rational.h" #include "common/timerange.h" #include "common/xmlutils.h" +#include "node/globals.h" #include "node/keyframe.h" #include "node/inputimmediate.h" #include "node/param.h" @@ -92,7 +93,7 @@ public: kCategoryCount }; - Node(bool create_default_output = true); + Node(); virtual ~Node() override; @@ -487,6 +488,22 @@ public: int InputArraySize(const QString& id) const; + struct ValueHint { + QVector type; + int index = -1; + QString tag; + }; + + ValueHint GetValueHintForInput(const QString &input) const + { + return value_hints_.value(input); + } + + void SetValueHintForInput(const QString &input, const ValueHint &hint) + { + value_hints_.insert(input, hint); + } + const NodeKeyframeTrack& GetTrackFromKeyframe(NodeKeyframe* key) const; using InputConnections = std::map; @@ -542,7 +559,7 @@ public: /** * @brief If Value() pushes a ShaderJob, this is the function that will process them. */ - virtual void ProcessSamples(NodeValueDatabase &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const; + virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const; /** * @brief If Value() pushes a GenerateJob, override this function for the image to create @@ -722,20 +739,20 @@ 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 NodeValueTable Value(const QString &output, NodeValueDatabase& value) const; + virtual void Value(const QString &output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const; virtual bool HasGizmos() const; - virtual void DrawGizmos(NodeValueDatabase& db, QPainter* p); + virtual void DrawGizmos(const NodeValueRow& row, const NodeGlobals &globals, QPainter* p); - virtual bool GizmoPress(NodeValueDatabase& db, const QPointF& p); + virtual bool GizmoPress(const NodeValueRow& row, const NodeGlobals &globals, const QPointF& p); virtual void GizmoMove(const QPointF& p, const rational &time); virtual void GizmoRelease(); const QString& GetLabel() const; void SetLabel(const QString& s); - virtual void Hash(const QString& output, QCryptographicHash& hash, const rational &time, const VideoParams& video_params) const; + virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const; void InvalidateAll(const QString& input, int element = -1); @@ -1151,7 +1168,7 @@ private: QVector GetDependenciesInternal(bool traverse, bool exclusive_only) const; - void HashInputElement(QCryptographicHash& hash, const QString &input, int element, const rational& time, const VideoParams &video_params) const; + void HashInputElement(QCryptographicHash& hash, const QString &input, int element, const NodeGlobals &globals, const VideoParams &video_params) const; void ParameterValueChanged(const QString &input, int element, const olive::TimeRange &range); void ParameterValueChanged(const NodeInput& input, const olive::TimeRange &range) @@ -1220,6 +1237,8 @@ private: bool cache_result_; + QMap value_hints_; + private slots: /** * @brief Slot when a keyframe's time changes to keep the keyframes correctly sorted by time diff --git a/app/node/output/track/track.cpp b/app/node/output/track/track.cpp index 55dbaf5e9..4f4c4a8dc 100644 --- a/app/node/output/track/track.cpp +++ b/app/node/output/track/track.cpp @@ -580,15 +580,17 @@ bool Track::IsLocked() const return locked_; } -void Track::Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const +void Track::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { Q_UNUSED(output) - Block* b = BlockAtTime(time); + Block* b = BlockAtTime(globals.time().in()); // Defer to block at this time, don't add any of our own information to the hash if (b) { - b->Hash(kDefaultOutput, hash, TransformTimeForBlock(b, time), video_params); + NodeGlobals new_globals = globals; + new_globals.set_time(TransformRangeForBlock(b, globals.time())); + b->Hash(kDefaultOutput, hash, new_globals, video_params); } } diff --git a/app/node/output/track/track.h b/app/node/output/track/track.h index 3b3abc10b..f56934f2e 100644 --- a/app/node/output/track/track.h +++ b/app/node/output/track/track.h @@ -361,7 +361,7 @@ public: bool IsLocked() const; - virtual void Hash(const QString& output, QCryptographicHash& hash, const rational &time, const VideoParams& video_params) const override; + virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override; static const double kTrackHeightDefault; static const double kTrackHeightMinimum; diff --git a/app/node/output/viewer/viewer.cpp b/app/node/output/viewer/viewer.cpp index f64ea8109..233de4372 100644 --- a/app/node/output/viewer/viewer.cpp +++ b/app/node/output/viewer/viewer.cpp @@ -546,23 +546,6 @@ int ViewerOutput::AddStream(Track::Type type, const QVariant& value) return index; } -void ViewerOutput::InputResized(const QString &input, int old_size, int new_size) -{ - if (input == kVideoParamsInput || input == kAudioParamsInput) { - Track::Type type = (input == kVideoParamsInput) ? Track::kVideo : Track::kAudio; - - if (new_size > old_size) { - for (int i=old_size; i ViewerOutput::GetEnabledVideoStreams() const { QVector streams; diff --git a/app/node/output/viewer/viewer.h b/app/node/output/viewer/viewer.h index 13798cd98..cb4309a67 100644 --- a/app/node/output/viewer/viewer.h +++ b/app/node/output/viewer/viewer.h @@ -245,9 +245,6 @@ private: bool video_cache_enabled_; bool audio_cache_enabled_; -private slots: - void InputResized(const QString& input, int old_size, int new_size); - }; } diff --git a/app/node/project/footage/footage.cpp b/app/node/project/footage/footage.cpp index 3448bbdee..b9663a8ba 100644 --- a/app/node/project/footage/footage.cpp +++ b/app/node/project/footage/footage.cpp @@ -323,9 +323,9 @@ QString Footage::DescribeAudioStream(const AudioParams ¶ms) QString::number(params.sample_rate())); } -void Footage::Hash(const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const +void Footage::Hash(const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { - super::Hash(output, hash, time, video_params); + super::Hash(output, hash, globals, video_params); // Footage last modified date hash.addData(QString::number(timestamp()).toUtf8()); @@ -356,7 +356,7 @@ void Footage::Hash(const QString& output, QCryptographicHash &hash, const ration // Footage timestamp if (params.video_type() != VideoParams::kVideoTypeStill) { - rational adjusted_time = AdjustTimeByLoopMode(time, loop_mode(), GetLength(), params.video_type(), params.frame_rate_as_time_base()); + rational adjusted_time = AdjustTimeByLoopMode(globals.time().in(), loop_mode(), GetLength(), params.video_type(), params.frame_rate_as_time_base()); if (!adjusted_time.isNaN()) { int64_t video_ts = Timecode::time_to_timestamp(adjusted_time, params.time_base()); @@ -374,17 +374,16 @@ void Footage::Hash(const QString& output, QCryptographicHash &hash, const ration } } -NodeValueTable Footage::Value(const QString &output, NodeValueDatabase &value) const +void Footage::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { + Q_UNUSED(globals) + Track::Reference ref = Track::Reference::FromString(output); // Pop filename from table - QString file = value[kFilenameInput].Take(NodeValue::kFile).toString(); + QString file = value[kFilenameInput].data().toString(); - LoopMode loop_mode = static_cast(value[kLoopModeInput].Take(NodeValue::kCombo).toInt()); - - // Merge table - NodeValueTable table = value.Merge(); + LoopMode loop_mode = static_cast(value[kLoopModeInput].data().toInt()); // If the file exists and the reference is valid, push a footage job to the renderer if (QFileInfo(file).exists()) { @@ -403,11 +402,9 @@ NodeValueTable Footage::Value(const QString &output, NodeValueDatabase &value) c job.set_cache_path(project()->cache_path()); } - table.Push(NodeValue::kRational, QVariant::fromValue(GetLength()), this, false, QStringLiteral("length")); - table.Push(NodeValue::kFootageJob, QVariant::fromValue(job), this); + table->Push(NodeValue::kRational, QVariant::fromValue(GetLength()), this, false, QStringLiteral("length")); + table->Push(NodeValue::kFootageJob, QVariant::fromValue(job), this); } - - return table; } QString Footage::GetStreamTypeName(Track::Type type) diff --git a/app/node/project/footage/footage.h b/app/node/project/footage/footage.h index abfc7f873..4f31650b6 100644 --- a/app/node/project/footage/footage.h +++ b/app/node/project/footage/footage.h @@ -181,9 +181,9 @@ public: static QString DescribeVideoStream(const VideoParams& params); static QString DescribeAudioStream(const AudioParams& params); - virtual void Hash(const QString& output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const override; + virtual void Hash(const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override; - virtual NodeValueTable Value(const QString &output, NodeValueDatabase& value) const override; + virtual void Value(const QString &output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; static QString GetStreamTypeName(Track::Type type); diff --git a/app/node/time/timeremap/timeremap.cpp b/app/node/time/timeremap/timeremap.cpp index c7fefd45e..e3205712f 100644 --- a/app/node/time/timeremap/timeremap.cpp +++ b/app/node/time/timeremap/timeremap.cpp @@ -98,13 +98,16 @@ QVector TimeRemapNode::inputs_for_output(const QString &output) const return {kInputInput}; } -void TimeRemapNode::Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams &video_params) const +void TimeRemapNode::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { // Don't hash anything of our own, just pass-through to the connected node at the remapped tmie Q_UNUSED(output) if (IsInputConnected(kInputInput)) { NodeOutput out = GetConnectedOutput(kInputInput); - out.node()->Hash(out.output(), hash, GetRemappedTime(time), video_params); + + NodeGlobals new_globals = globals; + new_globals.set_time(TimeRange(GetRemappedTime(globals.time().in()), GetRemappedTime(globals.time().out()))); + out.node()->Hash(out.output(), hash, new_globals, video_params); } } diff --git a/app/node/time/timeremap/timeremap.h b/app/node/time/timeremap/timeremap.h index 31243be02..b36fa052d 100644 --- a/app/node/time/timeremap/timeremap.h +++ b/app/node/time/timeremap/timeremap.h @@ -47,7 +47,7 @@ public: virtual QVector inputs_for_output(const QString &output) const override; - virtual void Hash(const QString &output, QCryptographicHash &hash, const rational &time, const VideoParams& video_params) const override; + virtual void Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override; static const QString kTimeInput; static const QString kInputInput; diff --git a/app/node/traverser.cpp b/app/node/traverser.cpp index e16683755..c139f7d83 100644 --- a/app/node/traverser.cpp +++ b/app/node/traverser.cpp @@ -40,11 +40,65 @@ NodeValueDatabase NodeTraverser::GenerateDatabase(const Node* node, const QStrin database.Insert(input, ProcessInput(node, input, range)); } - AddGlobalsToDatabase(database, range); - return database; } +NodeValueRow NodeTraverser::GenerateRow(NodeValueDatabase *database, const Node *node, const QString &output, const TimeRange &range) +{ + // Generate row + NodeValueRow row; + for (auto it=database->begin(); it!=database->end(); it++) { + // Get hint for which value should be pulled + row.insert(it.key(), GenerateRowValue(node, it.key(), &it.value())); + } + + return row; +} + +NodeValueRow NodeTraverser::GenerateRow(const Node *node, const QString &output, const TimeRange &range) +{ + // Generate database of input values of node + NodeValueDatabase database = GenerateDatabase(node, output, range); + + return GenerateRow(&database, node, output, range); +} + +NodeValue NodeTraverser::GenerateRowValue(const Node *node, const QString &input, NodeValueTable *table) +{ + Node::ValueHint hint = node->GetValueHintForInput(input); + QVector types = hint.type; + + if (types.isEmpty()) { + types.append(node->GetInputDataType(input)); + } + + if (hint.index == -1) { + // Get most recent value with this type and tag + return table->TakeWithMeta(types, hint.tag); + } else { + // Try to find value at this index + int index = table->Count() - hint.index; + int diff = 0; + + while (index + diff < table->Count() && index - diff >= 0) { + if (index + diff < table->Count() && types.contains(table->at(index + diff).type())) { + return table->TakeAt(index + diff); + } + if (index - diff >= 0 && types.contains(table->at(index - diff).type())) { + return table->TakeAt(index - diff); + } + diff++; + } + + return NodeValue(); + } +} + +NodeGlobals NodeTraverser::GenerateGlobals(const VideoParams ¶ms, const TimeRange &time) +{ + return NodeGlobals(QVector2D(params.width(), params.height()), time); +} + int NodeTraverser::GetChannelCountFromJob(const GenerateJob &job) { switch (job.GetAlphaChannelRequired()) { @@ -132,12 +186,20 @@ NodeValueTable NodeTraverser::GenerateTable(const Node *n, const QString& output // FIXME: Cache certain values here if we've already processed them before - // Generate database of input values of node + // Generate row for node NodeValueDatabase database = GenerateDatabase(n, output, range); + NodeValueRow row = GenerateRow(&database, n, output, range); + + // Pre-process row + qDebug() << "FIXME: Implement pre-process of row"; + + // Generate output table + NodeValueTable table = database.Merge(); // By this point, the node should have all the inputs it needs to render correctly - NodeValueTable table = n->Value(output, database); + n->Value(output, row, GenerateGlobals(video_params_, range), &table); + // Post-process table PostProcessTable(n, output, range, table); return table; @@ -218,17 +280,6 @@ QVariant NodeTraverser::GetCachedTexture(const QByteArray& hash) return QVariant(); } -void NodeTraverser::AddGlobalsToDatabase(NodeValueDatabase &db, const TimeRange& range) const -{ - // Insert global variables - NodeValueTable global; - global.Push(NodeValue::kFloat, range.in().toDouble(), nullptr, false, QStringLiteral("time_in")); - global.Push(NodeValue::kFloat, range.out().toDouble(), nullptr, false, QStringLiteral("time_out")); - global.Push(NodeValue::kVec2, GenerateResolution(), nullptr, false, QStringLiteral("resolution")); - - db.Insert(QStringLiteral("global"), global); -} - QVector2D NodeTraverser::GenerateResolution() const { return QVector2D(video_params_.square_pixel_width(), video_params_.height()); diff --git a/app/node/traverser.h b/app/node/traverser.h index b2b3698d7..31f87f1c5 100644 --- a/app/node/traverser.h +++ b/app/node/traverser.h @@ -44,6 +44,17 @@ public: NodeValueDatabase GenerateDatabase(const Node *node, const QString &output, const TimeRange &range); + NodeValueRow GenerateRow(NodeValueDatabase *database, const Node *node, const QString &output, const TimeRange &range); + NodeValueRow GenerateRow(const Node *node, const QString &output, const TimeRange &range); + + NodeValue GenerateRowValue(const Node *node, const QString &input, NodeValueTable *table); + + static NodeGlobals GenerateGlobals(const VideoParams ¶ms, const TimeRange &time); + static NodeGlobals GenerateGlobals(const VideoParams ¶ms, const rational &time) + { + return GenerateGlobals(params, TimeRange(time, time + params.frame_rate_as_time_base())); + } + const VideoParams& GetCacheVideoParams() const { return video_params_; @@ -80,8 +91,6 @@ protected: return false; } - void AddGlobalsToDatabase(NodeValueDatabase& db, const TimeRange &range) const; - QVector2D GenerateResolution() const; private: diff --git a/app/node/value.h b/app/node/value.h index b11a192f0..d4ea43f8f 100644 --- a/app/node/value.h +++ b/app/node/value.h @@ -381,6 +381,11 @@ public: bool Has(NodeValue::Type type) const; void Remove(const NodeValue& v); + void Clear() + { + values_.clear(); + } + bool isEmpty() const { return values_.isEmpty(); @@ -395,6 +400,8 @@ private: }; +using NodeValueRow = QHash; + } Q_DECLARE_METATYPE(olive::NodeValue) diff --git a/app/node/valuedatabase.h b/app/node/valuedatabase.h index c6cd8399b..725ed1e62 100644 --- a/app/node/valuedatabase.h +++ b/app/node/valuedatabase.h @@ -43,30 +43,40 @@ public: NodeValueTable Merge() const; - using const_iterator = QHash::const_iterator; + using Tables = QHash; + using const_iterator = Tables::const_iterator; + using iterator = Tables::iterator; - inline QHash::const_iterator begin() const + inline const_iterator cbegin() const { return tables_.cbegin(); } - inline QHash::const_iterator end() const + inline const_iterator cend() const { return tables_.cend(); } + inline iterator begin() + { + return tables_.begin(); + } + + inline iterator end() + { + return tables_.end(); + } + inline bool contains(const QString& s) const { return tables_.contains(s); } private: - QHash tables_; + Tables tables_; }; -using NodeValueMap = QHash; - } Q_DECLARE_METATYPE(olive::NodeValueDatabase) diff --git a/app/render/job/acceleratedjob.cpp b/app/render/job/acceleratedjob.cpp index 2925f388a..c53fc4f1e 100644 --- a/app/render/job/acceleratedjob.cpp +++ b/app/render/job/acceleratedjob.cpp @@ -20,13 +20,6 @@ #include "acceleratedjob.h" -#include "node/node.h" - namespace olive { -void AcceleratedJob::InsertValue(const Node* node, const QString& input, NodeValueDatabase& value) -{ - InsertValue(input, value[input].TakeWithMeta(node->GetInputDataType(input))); -} - } diff --git a/app/render/job/acceleratedjob.h b/app/render/job/acceleratedjob.h index 9e7d687e2..caafc2fbe 100644 --- a/app/render/job/acceleratedjob.h +++ b/app/render/job/acceleratedjob.h @@ -35,20 +35,28 @@ public: return value_map_.value(input); } - void InsertValue(const Node* node, const QString& input, NodeValueDatabase& value); + void InsertValue(const QString &input, const NodeValueRow &row) + { + value_map_.insert(input, row.value(input)); + } void InsertValue(const QString& input, const NodeValue& value) { value_map_.insert(input, value); } - const NodeValueMap &GetValues() const + void InsertValue(const NodeValueRow &row) + { + value_map_.insert(row); + } + + const NodeValueRow &GetValues() const { return value_map_; } private: - NodeValueMap value_map_; + NodeValueRow value_map_; }; diff --git a/app/render/job/samplejob.h b/app/render/job/samplejob.h index 57d8ff616..ad78bb6d2 100644 --- a/app/render/job/samplejob.h +++ b/app/render/job/samplejob.h @@ -38,9 +38,9 @@ public: samples_ = value.data().value(); } - SampleJob(const QString& from, NodeValueDatabase& db) + SampleJob(const QString& from, const NodeValueRow& row) { - samples_ = db[from].Take(NodeValue::kSamples).value(); + samples_ = row[from].data().value(); } SampleBufferPtr samples() const diff --git a/app/render/opengl/openglrenderer.cpp b/app/render/opengl/openglrenderer.cpp index dc8da16cd..2b9a498b8 100644 --- a/app/render/opengl/openglrenderer.cpp +++ b/app/render/opengl/openglrenderer.cpp @@ -429,8 +429,7 @@ void OpenGLRenderer::Blit(QVariant s, ShaderJob job, Texture *destination, Video functions_->glUseProgram(shader); - NodeValueMap::const_iterator it; - for (it=job.GetValues().constBegin(); it!=job.GetValues().constEnd(); it++) { + for (auto it=job.GetValues().constBegin(); it!=job.GetValues().constEnd(); it++) { // See if the shader has takes this parameter as an input GLint variable_location = functions_->glGetUniformLocation(shader, it.key().toUtf8().constData()); diff --git a/app/render/rendermanager.cpp b/app/render/rendermanager.cpp index 8f3df3815..ed32f20df 100644 --- a/app/render/rendermanager.cpp +++ b/app/render/rendermanager.cpp @@ -118,7 +118,7 @@ QByteArray RenderManager::Hash(const Node *n, const QString& output, const Video hasher.addData(reinterpret_cast(&interlacing), sizeof(interlacing)); if (n) { - n->Hash(output, hasher, time, params); + n->Hash(output, hasher, NodeTraverser::GenerateGlobals(params, time), params); } return hasher.result(); diff --git a/app/render/renderprocessor.cpp b/app/render/renderprocessor.cpp index 7901a8232..3698483aa 100644 --- a/app/render/renderprocessor.cpp +++ b/app/render/renderprocessor.cpp @@ -542,7 +542,7 @@ QVariant RenderProcessor::ProcessSamples(const Node *node, const TimeRange &rang } SampleBufferPtr output_buffer = SampleBuffer::CreateAllocated(job.samples()->audio_params(), job.samples()->sample_count()); - NodeValueDatabase value_db; + NodeValueRow value_db; const AudioParams& audio_params = ticket_->property("aparam").value(); @@ -556,11 +556,9 @@ QVariant RenderProcessor::ProcessSamples(const Node *node, const TimeRange &rang for (auto j=job.GetValues().constBegin(); j!=job.GetValues().constEnd(); j++) { NodeValueTable value = ProcessInput(node, j.key(), TimeRange(this_sample_time, this_sample_time)); - value_db.Insert(j.key(), value); + value_db.insert(j.key(), GenerateRowValue(node, j.key(), &value)); } - AddGlobalsToDatabase(value_db, TimeRange(this_sample_time, this_sample_time)); - node->ProcessSamples(value_db, job.samples(), output_buffer, diff --git a/app/widget/viewer/viewerdisplay.cpp b/app/widget/viewer/viewerdisplay.cpp index 3bae651b8..dce6bb886 100644 --- a/app/widget/viewer/viewerdisplay.cpp +++ b/app/widget/viewer/viewerdisplay.cpp @@ -204,7 +204,7 @@ void ViewerDisplayWidget::IncrementSkippedFrames() void ViewerDisplayWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton && gizmos_ - && gizmos_->GizmoPress(gizmo_db_, TransformViewerSpaceToBufferSpace(event->pos()))) { + && gizmos_->GizmoPress(gizmo_db_, NodeTraverser::GenerateGlobals(gizmo_params_, GenerateGizmoTime()), TransformViewerSpaceToBufferSpace(event->pos()))) { // Handle gizmo click gizmo_click_ = true; @@ -400,14 +400,12 @@ void ViewerDisplayWidget::OnPaint() NodeTraverser gt; gt.SetCacheVideoParams(gizmo_params_); - rational node_time = GetGizmoTime(); - - gizmo_db_ = gt.GenerateDatabase(gizmos_, QString(), - TimeRange(node_time, node_time + gizmo_params_.frame_rate_as_time_base())); + TimeRange range = GenerateGizmoTime(); + gizmo_db_ = gt.GenerateRow(gizmos_, Node::kDefaultOutput, range); QPainter p(inner_widget()); p.setWorldTransform(GenerateGizmoTransform()); - gizmos_->DrawGizmos(gizmo_db_, &p); + gizmos_->DrawGizmos(gizmo_db_, NodeTraverser::GenerateGlobals(gizmo_params_, range), &p); } // Draw action/title safe areas diff --git a/app/widget/viewer/viewerdisplay.h b/app/widget/viewer/viewerdisplay.h index b87d16dbe..c9d05ef23 100644 --- a/app/widget/viewer/viewerdisplay.h +++ b/app/widget/viewer/viewerdisplay.h @@ -237,6 +237,12 @@ private: QTransform GenerateGizmoTransform(); + TimeRange GenerateGizmoTime() + { + rational node_time = GetGizmoTime(); + return TimeRange(node_time, node_time + gizmo_params_.frame_rate_as_time_base()); + } + /** * @brief Internal reference to the OpenGL texture to draw. Set in SetTexture() and used in paintGL(). */ @@ -283,7 +289,7 @@ private: ViewerSafeMarginInfo safe_margin_; Node* gizmos_; - NodeValueDatabase gizmo_db_; + NodeValueRow gizmo_db_; rational gizmo_drag_time_; VideoParams gizmo_params_; QPoint gizmo_start_drag_;