From b07bccb7dc96ed0fb9ddb29a26a26df5e261124a Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Tue, 7 Sep 2021 22:01:36 -0700 Subject: [PATCH] nodes: revert to single output --- app/common/xmlutils.cpp | 4 +- app/common/xmlutils.h | 1 - app/core.cpp | 2 +- app/node/audio/pan/pan.cpp | 3 +- app/node/audio/pan/pan.h | 2 +- app/node/audio/volume/volume.cpp | 4 +- app/node/audio/volume/volume.h | 2 +- app/node/block/block.cpp | 8 +- app/node/block/block.h | 4 +- app/node/block/clip/clip.cpp | 18 ++- app/node/block/clip/clip.h | 4 +- app/node/block/transition/transition.cpp | 22 ++- app/node/block/transition/transition.h | 8 +- app/node/distort/crop/cropdistortnode.cpp | 4 +- app/node/distort/crop/cropdistortnode.h | 2 +- .../transform/transformdistortnode.cpp | 18 +-- .../distort/transform/transformdistortnode.h | 4 +- app/node/factory.cpp | 4 - app/node/filter/blur/blur.cpp | 4 +- app/node/filter/blur/blur.h | 2 +- app/node/filter/mosaic/mosaicfilternode.cpp | 4 +- app/node/filter/mosaic/mosaicfilternode.h | 2 +- app/node/filter/stroke/stroke.cpp | 4 +- app/node/filter/stroke/stroke.h | 2 +- app/node/generator/matrix/matrix.cpp | 4 +- app/node/generator/matrix/matrix.h | 2 +- app/node/generator/polygon/polygon.cpp | 4 +- app/node/generator/polygon/polygon.h | 2 +- app/node/generator/shape/shapenode.cpp | 4 +- app/node/generator/shape/shapenode.h | 2 +- app/node/generator/solid/solid.cpp | 4 +- app/node/generator/solid/solid.h | 2 +- app/node/generator/text/text.cpp | 4 +- app/node/generator/text/text.h | 2 +- app/node/graph.h | 4 +- app/node/input/time/timeinput.cpp | 6 +- app/node/input/time/timeinput.h | 4 +- app/node/input/value/valuenode.cpp | 3 +- app/node/input/value/valuenode.h | 2 +- app/node/math/math/math.cpp | 4 +- app/node/math/math/math.h | 2 +- app/node/math/merge/merge.cpp | 18 +-- app/node/math/merge/merge.h | 4 +- app/node/math/trigonometry/trigonometry.cpp | 4 +- app/node/math/trigonometry/trigonometry.h | 2 +- app/node/node.cpp | 149 ++++++++---------- app/node/node.h | 89 ++++------- app/node/output/track/track.cpp | 39 ++--- app/node/output/track/track.h | 12 +- app/node/output/viewer/viewer.cpp | 26 +-- app/node/output/viewer/viewer.h | 10 +- app/node/param.cpp | 10 +- app/node/param.h | 71 +++------ app/node/project/folder/folder.cpp | 8 +- app/node/project/folder/folder.h | 4 +- app/node/project/footage/footage.cpp | 139 ++++++++-------- app/node/project/footage/footage.h | 10 +- app/node/project/sequence/sequence.cpp | 8 +- app/node/project/sequence/sequence.h | 4 +- app/node/time/timeremap/timeremap.cpp | 13 +- app/node/time/timeremap/timeremap.h | 4 +- app/node/traverser.cpp | 56 ++++--- app/node/traverser.h | 15 +- app/render/previewautocacher.cpp | 24 +-- app/render/previewautocacher.h | 10 +- app/render/rendermanager.cpp | 2 +- app/render/rendermanager.h | 6 +- app/render/renderprocessor.cpp | 15 +- app/task/precache/precachetask.cpp | 4 +- app/task/render/render.cpp | 2 +- .../nodeparamview/nodeparamviewitem.cpp | 2 +- app/widget/nodeparamview/nodeparamviewitem.h | 2 +- .../nodeparamview/nodeparamviewundo.cpp | 11 ++ app/widget/nodeparamview/nodeparamviewundo.h | 32 ++++ app/widget/nodetableview/nodetableview.cpp | 10 +- app/widget/nodeview/nodeview.cpp | 39 ++--- app/widget/nodeview/nodeview.h | 5 +- app/widget/nodeview/nodeviewedge.cpp | 4 +- app/widget/nodeview/nodeviewedge.h | 6 +- app/widget/nodeview/nodeviewitem.cpp | 10 +- app/widget/nodeview/nodeviewitem.h | 2 +- app/widget/nodeview/nodeviewscene.cpp | 10 +- app/widget/nodeview/nodeviewscene.h | 8 +- app/widget/nodeview/nodeviewundo.cpp | 8 +- app/widget/nodeview/nodeviewundo.h | 8 +- app/widget/timelinewidget/tool/import.cpp | 11 +- .../trackview/trackviewitem.cpp | 6 +- app/widget/viewer/viewer.cpp | 6 +- app/widget/viewer/viewerdisplay.cpp | 2 +- 89 files changed, 511 insertions(+), 616 deletions(-) diff --git a/app/common/xmlutils.cpp b/app/common/xmlutils.cpp index af2ed0fca..e8a967cbf 100644 --- a/app/common/xmlutils.cpp +++ b/app/common/xmlutils.cpp @@ -29,9 +29,9 @@ namespace olive { void XMLConnectNodes(const XMLNodeData &xml_node_data, MultiUndoCommand *command) { foreach (const XMLNodeData::SerializedConnection& con, xml_node_data.desired_connections) { - NodeOutput out(xml_node_data.node_ptrs.value(con.output_node), con.output); + Node *out = xml_node_data.node_ptrs.value(con.output_node); - if (out.IsValid()) { + if (out) { if (command) { command->add_child(new NodeEdgeAddCommand(out, con.input)); } else { diff --git a/app/common/xmlutils.h b/app/common/xmlutils.h index f4f62eb14..98e595c42 100644 --- a/app/common/xmlutils.h +++ b/app/common/xmlutils.h @@ -39,7 +39,6 @@ struct XMLNodeData { struct SerializedConnection { NodeInput input; quintptr output_node; - QString output; }; struct BlockLink { diff --git a/app/core.cpp b/app/core.cpp index 0c85b0d78..d729a8fbe 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -75,7 +75,7 @@ namespace olive { Core* Core::instance_ = nullptr; -const uint Core::kProjectVersion = 210528; +const uint Core::kProjectVersion = 210907; Core::Core(const CoreParams& params) : main_window_(nullptr), diff --git a/app/node/audio/pan/pan.cpp b/app/node/audio/pan/pan.cpp index 2d8e7c5a4..457c4cdd1 100644 --- a/app/node/audio/pan/pan.cpp +++ b/app/node/audio/pan/pan.cpp @@ -62,9 +62,8 @@ QString PanNode::Description() const return tr("Adjust the stereo panning of an audio source."); } -void PanNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void PanNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) Q_UNUSED(globals) // Create a sample job diff --git a/app/node/audio/pan/pan.h b/app/node/audio/pan/pan.h index deb896a11..6f8fd9a89 100644 --- a/app/node/audio/pan/pan.h +++ b/app/node/audio/pan/pan.h @@ -40,7 +40,7 @@ public: virtual QVector Category() const override; virtual QString Description() const override; - virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override; diff --git a/app/node/audio/volume/volume.cpp b/app/node/audio/volume/volume.cpp index 8e6d8056d..e6c26b50e 100644 --- a/app/node/audio/volume/volume.cpp +++ b/app/node/audio/volume/volume.cpp @@ -61,10 +61,8 @@ QString VolumeNode::Description() const return tr("Adjusts the volume of an audio source."); } -void VolumeNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void VolumeNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - return ValueInternal(kOpMultiply, kPairSampleNumber, kSamplesInput, diff --git a/app/node/audio/volume/volume.h b/app/node/audio/volume/volume.h index 24cf9ae9b..a9fcc10d9 100644 --- a/app/node/audio/volume/volume.h +++ b/app/node/audio/volume/volume.h @@ -40,7 +40,7 @@ public: virtual QVector Category() const override; virtual QString Description() const override; - virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override; diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp index d4b2e9a42..a14fc8cc8 100644 --- a/app/node/block/block.cpp +++ b/app/node/block/block.cpp @@ -100,7 +100,7 @@ void Block::InputValueChangedEvent(const QString &input, int element) } } -bool Block::HashPassthrough(const QString &input, const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const +bool Block::HashPassthrough(const QString &input, const Node::ValueHint &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { if (IsInputConnected(input)) { TimeRange t = InputTimeAdjustment(input, -1, globals.time()); @@ -108,8 +108,8 @@ bool Block::HashPassthrough(const QString &input, const QString &output, QCrypto NodeGlobals new_globals = globals; new_globals.set_time(t); - NodeOutput out = GetConnectedOutput(input); - out.node()->Hash(out.output(), hash, new_globals, video_params); + Node *out = GetConnectedOutput(input); + out->Hash(GetValueHintForInput(input, -1), hash, new_globals, video_params); return true; } @@ -130,7 +130,7 @@ void Block::Retranslate() SetInputName(kEnabledInput, tr("Enabled")); } -void Block::Hash(const QString &, QCryptographicHash &, const NodeGlobals &, const VideoParams &) const +void Block::Hash(const ValueHint &hint, 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 332b99c68..e187d3524 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 NodeGlobals &globals, const VideoParams& video_params) const override; + virtual void Hash(const Node::ValueHint &hint, 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 NodeGlobals &globals, const VideoParams& video_params) const; + bool HashPassthrough(const QString &input, const ValueHint &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 1c37e11db..0d30667a8 100644 --- a/app/node/block/clip/clip.cpp +++ b/app/node/block/clip/clip.cpp @@ -20,6 +20,7 @@ #include "clip.h" +#include "node/output/track/track.h" #include "widget/slider/floatslider.h" #include "widget/slider/rationalslider.h" @@ -50,7 +51,7 @@ ClipBlock::ClipBlock() : IgnoreHashingFrom(kReverseInput); PrependInput(kBufferIn, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable)); - SetValueHintForInput(kBufferIn, {NodeValue::kBuffer, -1, QString()}); + SetValueHintForInput(kBufferIn, -1, {NodeValue::kBuffer, -1, QString()}); } Node *ClipBlock::copy() const @@ -60,6 +61,14 @@ Node *ClipBlock::copy() const QString ClipBlock::Name() const { + if (track()) { + if (track()->type() == Track::kVideo) { + return tr("Video Clip"); + } else if (track()->type() == Track::kAudio) { + return tr("Audio Clip"); + } + } + return tr("Clip"); } @@ -232,9 +241,8 @@ TimeRange ClipBlock::OutputTimeAdjustment(const QString& input, int element, con return super::OutputTimeAdjustment(input, element, input_time); } -void ClipBlock::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void ClipBlock::Value(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 @@ -256,9 +264,9 @@ void ClipBlock::Retranslate() SetInputName(kReverseInput, tr("Reverse")); } -void ClipBlock::Hash(const QString &out, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const +void ClipBlock::Hash(const ValueHint &out, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { - HashPassthrough(kBufferIn, out, hash, globals, video_params); + HashPassthrough(kBufferIn, GetValueHintForInput(kBufferIn, -1), hash, globals, video_params); } } diff --git a/app/node/block/clip/clip.h b/app/node/block/clip/clip.h index 904ada16e..3e914734d 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual void Retranslate() override; - virtual void Hash(const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override; + virtual void Hash(const Node::ValueHint& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override; double speed() const { diff --git a/app/node/block/transition/transition.cpp b/app/node/block/transition/transition.cpp index b5a0bd3ea..7b89294fd 100644 --- a/app/node/block/transition/transition.cpp +++ b/app/node/block/transition/transition.cpp @@ -137,10 +137,10 @@ 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 NodeGlobals &globals, const VideoParams &video_params) const +void TransitionBlock::Hash(const ValueHint &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { if (HashPassthrough(kInBlockInput, output, hash, globals, video_params) || HashPassthrough(kOutBlockInput, output, hash, globals, video_params)) { - HashAddNodeSignature(hash, output); + HashAddNodeSignature(hash); double time_dbl = globals.time().in().toDouble(); double all_prog = GetTotalProgress(time_dbl); @@ -173,10 +173,8 @@ void TransitionBlock::InsertTransitionTimes(AcceleratedJob *job, const double &t NodeValue(NodeValue::kFloat, GetInProgress(time), this)); } -void TransitionBlock::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void TransitionBlock::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - 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(); @@ -236,7 +234,7 @@ void TransitionBlock::InvalidateCache(const TimeRange &range, const QString &fro TimeRange r = range; if (from == kOutBlockInput || from == kInBlockInput) { - Block *n = dynamic_cast(GetConnectedNode(from)); + Block *n = dynamic_cast(GetConnectedOutput(from)); if (n) { r = Track::TransformRangeFromBlock(n, r); } @@ -275,24 +273,24 @@ double TransitionBlock::TransformCurve(double linear) const return linear; } -void TransitionBlock::InputConnectedEvent(const QString &input, int element, const NodeOutput &output) +void TransitionBlock::InputConnectedEvent(const QString &input, int element, Node *output) { Q_UNUSED(element) if (input == kOutBlockInput) { // If node is not a block, this will just be null - if ((connected_out_block_ = dynamic_cast(output.node()))) { + if ((connected_out_block_ = dynamic_cast(output))) { connected_out_block_->set_out_transition(this); } } else if (input == kInBlockInput) { // If node is not a block, this will just be null - if ((connected_in_block_ = dynamic_cast(output.node()))) { + if ((connected_in_block_ = dynamic_cast(output))) { connected_in_block_->set_in_transition(this); } } } -void TransitionBlock::InputDisconnectedEvent(const QString &input, int element, const NodeOutput &output) +void TransitionBlock::InputDisconnectedEvent(const QString &input, int element, Node *output) { Q_UNUSED(element) Q_UNUSED(output) @@ -313,7 +311,7 @@ void TransitionBlock::InputDisconnectedEvent(const QString &input, int element, TimeRange TransitionBlock::InputTimeAdjustment(const QString &input, int element, const TimeRange &input_time) const { if (input == kInBlockInput || input == kOutBlockInput) { - Block* block = dynamic_cast(GetConnectedNode(input)); + Block* block = dynamic_cast(GetConnectedOutput(input)); if (block) { return input_time + in() - block->in(); } @@ -325,7 +323,7 @@ TimeRange TransitionBlock::InputTimeAdjustment(const QString &input, int element TimeRange TransitionBlock::OutputTimeAdjustment(const QString &input, int element, const TimeRange &input_time) const { if (input == kInBlockInput || input == kOutBlockInput) { - Block* block = dynamic_cast(GetConnectedNode(input)); + Block* block = dynamic_cast(GetConnectedOutput(input)); if (block) { return input_time + block->in() - in(); } diff --git a/app/node/block/transition/transition.h b/app/node/block/transition/transition.h index 55a510489..0ff8ad922 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 NodeGlobals &globals, const VideoParams& video_params) const override; + virtual void Hash(const ValueHint& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override; - virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(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; @@ -83,9 +83,9 @@ protected: double TransformCurve(double linear) const; - virtual void InputConnectedEvent(const QString& input, int element, const NodeOutput& output) override; + virtual void InputConnectedEvent(const QString& input, int element, Node *output) override; - virtual void InputDisconnectedEvent(const QString& input, int element, const NodeOutput& output) override; + virtual void InputDisconnectedEvent(const QString& input, int element, Node *output) override; virtual TimeRange InputTimeAdjustment(const QString& input, int element, const TimeRange& input_time) const override; diff --git a/app/node/distort/crop/cropdistortnode.cpp b/app/node/distort/crop/cropdistortnode.cpp index 80132f1bf..d3441d6ea 100644 --- a/app/node/distort/crop/cropdistortnode.cpp +++ b/app/node/distort/crop/cropdistortnode.cpp @@ -55,10 +55,8 @@ void CropDistortNode::Retranslate() SetInputName(kFeatherInput, tr("Feather")); } -void CropDistortNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void CropDistortNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - ShaderJob job; job.InsertValue(value); job.InsertValue(QStringLiteral("resolution_in"), NodeValue(NodeValue::kVec2, globals.resolution(), this)); diff --git a/app/node/distort/crop/cropdistortnode.h b/app/node/distort/crop/cropdistortnode.h index 602d5a830..b8e997fa0 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual ShaderCode GetShaderCode(const QString &shader_id) const override; diff --git a/app/node/distort/transform/transformdistortnode.cpp b/app/node/distort/transform/transformdistortnode.cpp index 45c85acf2..2e901d68a 100644 --- a/app/node/distort/transform/transformdistortnode.cpp +++ b/app/node/distort/transform/transformdistortnode.cpp @@ -39,7 +39,7 @@ TransformDistortNode::TransformDistortNode() AddInput(kInterpolationInput, NodeValue::kCombo, 2); - AddInput(kTextureInput, NodeValue::kTexture, InputFlags(kInputFlagNotKeyframable)); + PrependInput(kTextureInput, NodeValue::kTexture, InputFlags(kInputFlagNotKeyframable)); } void TransformDistortNode::Retranslate() @@ -54,10 +54,8 @@ void TransformDistortNode::Retranslate() SetComboBoxStrings(kInterpolationInput, {tr("Nearest Neighbor"), tr("Bilinear"), tr("Mipmapped Bilinear")}); } -void TransformDistortNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void TransformDistortNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - // Generate matrix QMatrix4x4 generated_matrix = GenerateMatrix(value, true, false, false, false); @@ -309,11 +307,11 @@ void TransformDistortNode::GizmoRelease() gizmo_drag_ = nullptr; } -void TransformDistortNode::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const +void TransformDistortNode::Hash(const ValueHint &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { // If not connected to output, this will produce nothing - NodeOutput out = GetConnectedOutput(kTextureInput); - if (!out.IsValid()) { + Node *out = GetConnectedOutput(kTextureInput); + if (!out) { return; } @@ -321,7 +319,7 @@ void TransformDistortNode::Hash(const QString &output, QCryptographicHash &hash, NodeTraverser traverser; traverser.SetCacheVideoParams(video_params); - NodeValueRow db = traverser.GenerateRow(this, output, globals.time()); + NodeValueRow db = traverser.GenerateRow(this, globals.time()); TexturePtr tex = db[kTextureInput].data().value(); if (tex) { VideoParams tex_params = tex->params(); @@ -330,12 +328,12 @@ void TransformDistortNode::Hash(const QString &output, QCryptographicHash &hash, if (!matrix.isIdentity()) { // Add fingerprint - HashAddNodeSignature(hash, output); + HashAddNodeSignature(hash); hash.addData(reinterpret_cast(&matrix), sizeof(matrix)); } } - out.node()->Hash(out.output(), hash, globals, video_params); + out->Hash(GetValueHintForInput(kTextureInput, -1), hash, globals, video_params); } QMatrix4x4 TransformDistortNode::AdjustMatrixByResolutions(const QMatrix4x4 &mat, const QVector2D &sequence_res, const QVector2D &texture_res, AutoScaleType autoscale_type) diff --git a/app/node/distort/transform/transformdistortnode.h b/app/node/distort/transform/transformdistortnode.h index ed10b8427..e2f0c4a81 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual ShaderCode GetShaderCode(const QString& shader_id) const override; @@ -80,7 +80,7 @@ public: virtual void GizmoMove(const QPointF &p, const rational &time) override; virtual void GizmoRelease() override; - virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override; + virtual void Hash(const ValueHint& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override; enum AutoScaleType { kAutoScaleNone, diff --git a/app/node/factory.cpp b/app/node/factory.cpp index 9f6c7f335..9fa88710a 100644 --- a/app/node/factory.cpp +++ b/app/node/factory.cpp @@ -63,10 +63,6 @@ void NodeFactory::Initialize() Node* created_node = CreateFromFactoryIndex(static_cast(i)); library_.append(created_node); - - if (created_node->outputs().isEmpty()) { - qWarning() << "Node" << created_node->id() << "has no outputs"; - } } } diff --git a/app/node/filter/blur/blur.cpp b/app/node/filter/blur/blur.cpp index dcfe21e45..a7eb1741d 100644 --- a/app/node/filter/blur/blur.cpp +++ b/app/node/filter/blur/blur.cpp @@ -87,10 +87,8 @@ ShaderCode BlurFilterNode::GetShaderCode(const QString &shader_id) const return ShaderCode(FileFunctions::ReadFileAsString(":/shaders/blur.frag")); } -void BlurFilterNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void BlurFilterNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - ShaderJob job; job.InsertValue(value); diff --git a/app/node/filter/blur/blur.h b/app/node/filter/blur/blur.h index 1e3aeece8..4b061040d 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(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 2ea42e469..242d5682f 100644 --- a/app/node/filter/mosaic/mosaicfilternode.cpp +++ b/app/node/filter/mosaic/mosaicfilternode.cpp @@ -44,10 +44,8 @@ void MosaicFilterNode::Retranslate() SetInputName(kVertInput, tr("Vertical")); } -void MosaicFilterNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void MosaicFilterNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - ShaderJob job; job.InsertValue(value); diff --git a/app/node/filter/mosaic/mosaicfilternode.h b/app/node/filter/mosaic/mosaicfilternode.h index fcd906dd6..726da5744 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(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 aa56f01fd..7818d7e46 100644 --- a/app/node/filter/stroke/stroke.cpp +++ b/app/node/filter/stroke/stroke.cpp @@ -82,10 +82,8 @@ void StrokeFilterNode::Retranslate() SetInputName(kInnerInput, tr("Inner")); } -void StrokeFilterNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void StrokeFilterNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - ShaderJob job; job.InsertValue(value); diff --git a/app/node/filter/stroke/stroke.h b/app/node/filter/stroke/stroke.h index dc95d1490..d70e7e7bc 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(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 0dfd3d801..461d2ca3f 100644 --- a/app/node/generator/matrix/matrix.cpp +++ b/app/node/generator/matrix/matrix.cpp @@ -88,10 +88,8 @@ void MatrixGenerator::Retranslate() SetInputName(kAnchorInput, tr("Anchor Point")); } -void MatrixGenerator::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void MatrixGenerator::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - // Push matrix output QMatrix4x4 mat = GenerateMatrix(value, true, false, false, false); table->Push(NodeValue::kMatrix, mat, this); diff --git a/app/node/generator/matrix/matrix.h b/app/node/generator/matrix/matrix.h index f356d1987..6ccb318a0 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; static const QString kPositionInput; static const QString kRotationInput; diff --git a/app/node/generator/polygon/polygon.cpp b/app/node/generator/polygon/polygon.cpp index f0704aec8..c246b6f94 100644 --- a/app/node/generator/polygon/polygon.cpp +++ b/app/node/generator/polygon/polygon.cpp @@ -86,10 +86,8 @@ ShaderCode PolygonGenerator::GetShaderCode(const QString &shader_id) const return ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/polygon.frag"))); } -void PolygonGenerator::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void PolygonGenerator::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - ShaderJob job; job.InsertValue(value); diff --git a/app/node/generator/polygon/polygon.h b/app/node/generator/polygon/polygon.h index 6b6e82fb6..31876eda9 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(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 d5d3734da..2d9848c1a 100644 --- a/app/node/generator/shape/shapenode.cpp +++ b/app/node/generator/shape/shapenode.cpp @@ -68,10 +68,8 @@ ShaderCode ShapeNode::GetShaderCode(const QString &shader_id) const return ShaderCode(FileFunctions::ReadFileAsString(QStringLiteral(":/shaders/shape.frag"))); } -void ShapeNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void ShapeNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - ShaderJob job; job.InsertValue(value); diff --git a/app/node/generator/shape/shapenode.h b/app/node/generator/shape/shapenode.h index eb20a18ad..3f9ff5d39 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(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 c093e48cb..76b2340df 100644 --- a/app/node/generator/solid/solid.cpp +++ b/app/node/generator/solid/solid.cpp @@ -62,10 +62,8 @@ void SolidGenerator::Retranslate() SetInputName(kColorInput, tr("Color")); } -void SolidGenerator::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void SolidGenerator::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - ShaderJob job; job.InsertValue(value); table->Push(NodeValue::kShaderJob, QVariant::fromValue(job), this); diff --git a/app/node/generator/solid/solid.h b/app/node/generator/solid/solid.h index aace92bbf..9e60090bc 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(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 338a5d464..a3035a2e9 100644 --- a/app/node/generator/text/text.cpp +++ b/app/node/generator/text/text.cpp @@ -89,10 +89,8 @@ void TextGenerator::Retranslate() SetComboBoxStrings(kVAlignInput, {tr("Top"), tr("Center"), tr("Bottom")}); } -void TextGenerator::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void TextGenerator::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - GenerateJob job; job.InsertValue(value); job.SetAlphaChannelRequired(GenerateJob::kAlphaForceOn); diff --git a/app/node/generator/text/text.h b/app/node/generator/text/text.h index 60534fd3d..d673eb558 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(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/graph.h b/app/node/graph.h index 8935db662..59bcde0f5 100644 --- a/app/node/graph.h +++ b/app/node/graph.h @@ -123,9 +123,9 @@ signals: */ void NodeRemoved(Node* node); - void InputConnected(const NodeOutput& output, const NodeInput& input); + void InputConnected(Node *output, const NodeInput& input); - void InputDisconnected(const NodeOutput& output, const NodeInput& input); + void InputDisconnected(Node *output, const NodeInput& input); void ValueChanged(const NodeInput& input); diff --git a/app/node/input/time/timeinput.cpp b/app/node/input/time/timeinput.cpp index d9d704851..0d15f8ce3 100644 --- a/app/node/input/time/timeinput.cpp +++ b/app/node/input/time/timeinput.cpp @@ -51,10 +51,8 @@ QString TimeInput::Description() const return tr("Generates the time (in seconds) at this frame."); } -void TimeInput::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void TimeInput::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - table->Push(NodeValue::kFloat, globals.time().in().toDouble(), this, @@ -62,7 +60,7 @@ void TimeInput::Value(const QString &output, const NodeValueRow &value, const No QStringLiteral("time")); } -void TimeInput::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const +void TimeInput::Hash(const ValueHint &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { Node::Hash(output, hash, globals, video_params); diff --git a/app/node/input/time/timeinput.h b/app/node/input/time/timeinput.h index 4df699a7e..f5ad3e37a 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; - virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override; + virtual void Hash(const ValueHint& 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 39a3d247a..215e7a08c 100644 --- a/app/node/input/value/valuenode.cpp +++ b/app/node/input/value/valuenode.cpp @@ -59,10 +59,9 @@ void ValueNode::Retranslate() SetComboBoxStrings(kTypeInput, type_names); } -void ValueNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void ValueNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { Q_UNUSED(globals) - Q_UNUSED(output) // Ensure value is pushed onto the table table->Push(value[kValueInput]); diff --git a/app/node/input/value/valuenode.h b/app/node/input/value/valuenode.h index 389dc56ad..f6205fbd8 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 void Value(const QString &output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(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 e788d0477..d601c2a8d 100644 --- a/app/node/math/math/math.cpp +++ b/app/node/math/math/math.cpp @@ -88,10 +88,8 @@ ShaderCode MathNode::GetShaderCode(const QString &shader_id) const return GetShaderCodeInternal(shader_id, kParamAIn, kParamBIn); } -void MathNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void MathNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - // Auto-detect what values to operate with // FIXME: Very inefficient NodeValueTable at, bt; diff --git a/app/node/math/math/math.h b/app/node/math/math/math.h index 8d5bd3a4c..b87b09a19 100644 --- a/app/node/math/math/math.h +++ b/app/node/math/math/math.h @@ -54,7 +54,7 @@ public: SetStandardValue(kMethodIn, o); } - virtual void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; virtual void ProcessSamples(const NodeValueRow &values, const SampleBufferPtr input, SampleBufferPtr output, int index) const override; diff --git a/app/node/math/merge/merge.cpp b/app/node/math/merge/merge.cpp index 5be3bae26..b2732e88d 100644 --- a/app/node/math/merge/merge.cpp +++ b/app/node/math/merge/merge.cpp @@ -73,10 +73,8 @@ ShaderCode MergeNode::GetShaderCode(const QString &shader_id) const return ShaderCode(FileFunctions::ReadFileAsString(":/shaders/alphaover.frag")); } -void MergeNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void MergeNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - ShaderJob job; job.InsertValue(value); @@ -102,12 +100,12 @@ void MergeNode::Value(const QString &output, const NodeValueRow &value, const No } } -void MergeNode::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const +void MergeNode::Hash(const ValueHint &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { NodeTraverser traverser; traverser.SetCacheVideoParams(video_params); - NodeValueDatabase db = traverser.GenerateDatabase(this, output, globals.time()); + NodeValueDatabase db = traverser.GenerateDatabase(this, globals.time()); TexturePtr base_tex = db[kBaseIn].Get(NodeValue::kTexture).value(); TexturePtr blend_tex = db[kBlendIn].Get(NodeValue::kTexture).value(); @@ -118,17 +116,17 @@ void MergeNode::Hash(const QString &output, QCryptographicHash &hash, const Node if (!passthrough_base && !passthrough_blend) { // This merge will actually do something so we add a fingerprint - HashAddNodeSignature(hash, output); + HashAddNodeSignature(hash); } if (!passthrough_base) { - NodeOutput blend_output = GetConnectedOutput(kBlendIn); - blend_output.node()->Hash(blend_output.output(), hash, globals, video_params); + Node *blend_output = GetConnectedOutput(kBlendIn); + blend_output->Hash(GetValueHintForInput(kBlendIn, -1), hash, globals, video_params); } if (!passthrough_blend) { - NodeOutput base_output = GetConnectedOutput(kBaseIn); - base_output.node()->Hash(base_output.output(), hash, globals, video_params); + Node *base_output = GetConnectedOutput(kBaseIn); + base_output->Hash(GetValueHintForInput(kBaseIn, -1), 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 66c465da1..dc127c33d 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(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 NodeGlobals &globals, const VideoParams& video_params) const override; + virtual void Hash(const ValueHint& 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 909c83074..d60087621 100644 --- a/app/node/math/trigonometry/trigonometry.cpp +++ b/app/node/math/trigonometry/trigonometry.cpp @@ -76,10 +76,8 @@ void TrigonometryNode::Retranslate() SetInputName(kMethodIn, tr("Method")); } -void TrigonometryNode::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void TrigonometryNode::Value(const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const { - Q_UNUSED(output) - double x = value[kXIn].data().toFloat(); switch (static_cast(GetStandardValue(kMethodIn).toInt())) { diff --git a/app/node/math/trigonometry/trigonometry.h b/app/node/math/trigonometry/trigonometry.h index 04d7bf329..1f1058f6b 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 void Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(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 6142d002a..bf4f80453 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -35,6 +35,7 @@ #include "project/project.h" #include "ui/colorcoding.h" #include "ui/icons/icons.h" +#include "widget/nodeparamview/nodeparamviewundo.h" #include "widget/nodeview/nodeviewundo.h" namespace olive { @@ -50,7 +51,6 @@ Node::Node() : operation_stack_(0), cache_result_(false) { - AddOutput(); } Node::~Node() @@ -122,19 +122,18 @@ void Node::Load(QXmlStreamReader *reader, XMLNodeData& xml_node_data, uint versi } QString output_node_id; - QString output_param_id; while (XMLReadNextStartElement(reader)) { - if (reader->name() == QStringLiteral("node")) { + if ((version >= 210907 && reader->name() == QStringLiteral("output")) || reader->name() == QStringLiteral("node")) { output_node_id = reader->readElementText(); - } else if (reader->name() == QStringLiteral("output")) { - output_param_id = reader->readElementText(); + } else if (version < 210907 && reader->name() == QStringLiteral("output")) { + qDebug() << "FIXME: Convert output string to ValueHint"; } else { reader->skipCurrentElement(); } } - xml_node_data.desired_connections.append({NodeInput(this, param_id, ele), output_node_id.toULongLong(), output_param_id}); + xml_node_data.desired_connections.append({NodeInput(this, param_id, ele), output_node_id.toULongLong()}); } else { reader->skipCurrentElement(); } @@ -173,8 +172,7 @@ void Node::Save(QXmlStreamWriter *writer) const writer->writeAttribute(QStringLiteral("input"), it->first.input()); writer->writeAttribute(QStringLiteral("element"), QString::number(it->first.element())); - writer->writeTextElement(QStringLiteral("node"), QString::number(reinterpret_cast(it->second.node()))); - writer->writeTextElement(QStringLiteral("output"), it->second.output()); + writer->writeTextElement(QStringLiteral("output"), QString::number(reinterpret_cast(it->second))); writer->writeEndElement(); // connection } @@ -248,25 +246,25 @@ QBrush Node::brush(qreal top, qreal bottom) const } } -void Node::ConnectEdge(const NodeOutput &output, const NodeInput &input) +void Node::ConnectEdge(Node *output, const NodeInput &input) { // Ensure graph is the same - Q_ASSERT(input.node()->parent() == output.node()->parent()); + Q_ASSERT(input.node()->parent() == output->parent()); // Ensure a connection isn't getting overwritten Q_ASSERT(input.node()->input_connections().find(input) == input.node()->input_connections().end()); // Insert connection on both sides input.node()->input_connections_[input] = output; - output.node()->output_connections_.push_back(std::pair({output, input})); + output->output_connections_.push_back(std::pair({output, input})); // Call internal events input.node()->InputConnectedEvent(input.input(), input.element(), output); - output.node()->OutputConnectedEvent(output.output(), input); + output->OutputConnectedEvent(input); // Emit signals emit input.node()->InputConnected(output, input); - emit output.node()->OutputConnected(output, input); + emit output->OutputConnected(output, input); // Invalidate all if this node isn't ignoring this input if (!input.node()->ignore_connections_.contains(input.input())) { @@ -274,10 +272,10 @@ void Node::ConnectEdge(const NodeOutput &output, const NodeInput &input) } } -void Node::DisconnectEdge(const NodeOutput &output, const NodeInput &input) +void Node::DisconnectEdge(Node *output, const NodeInput &input) { // Ensure graph is the same - Q_ASSERT(input.node()->parent() == output.node()->parent()); + Q_ASSERT(input.node()->parent() == output->parent()); // Ensure connection exists Q_ASSERT(input.node()->input_connections().at(input) == output); @@ -286,15 +284,15 @@ void Node::DisconnectEdge(const NodeOutput &output, const NodeInput &input) InputConnections& inputs = input.node()->input_connections_; inputs.erase(inputs.find(input)); - OutputConnections& outputs = output.node()->output_connections_; - outputs.erase(std::find(outputs.begin(), outputs.end(), std::pair({output, input}))); + OutputConnections& outputs = output->output_connections_; + outputs.erase(std::find(outputs.begin(), outputs.end(), std::pair({output, input}))); // Call internal events input.node()->InputDisconnectedEvent(input.input(), input.element(), output); - output.node()->OutputDisconnectedEvent(output.output(), input); + output->OutputDisconnectedEvent(input); emit input.node()->InputDisconnected(output, input); - emit output.node()->OutputDisconnected(output, input); + emit output->OutputDisconnected(output, input); if (!input.node()->ignore_connections_.contains(input.input())) { input.node()->InvalidateAll(input.input(), input.element()); @@ -437,10 +435,10 @@ void Node::SetInputIsKeyframing(const QString &input, bool e, int element) bool Node::IsInputConnected(const QString &input, int element) const { - return GetConnectedOutput(input, element).IsValid(); + return GetConnectedOutput(input, element); } -NodeOutput Node::GetConnectedOutput(const QString &input, int element) const +Node *Node::GetConnectedOutput(const QString &input, int element) const { for (auto it=input_connections_.cbegin(); it!=input_connections_.cend(); it++) { if (it->first.input() == input && it->first.element() == element) { @@ -448,7 +446,7 @@ NodeOutput Node::GetConnectedOutput(const QString &input, int element) const } } - return NodeOutput(); + return nullptr; } bool Node::IsUsingStandardValue(const QString &input, int track, int element) const @@ -1013,10 +1011,9 @@ Node::InputFlags Node::GetInputFlags(const QString &input) const } } -void Node::Value(const QString& output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const +void Node::Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const { // Do nothing - Q_UNUSED(output) Q_UNUSED(value) Q_UNUSED(globals) Q_UNUSED(table) @@ -1092,19 +1089,19 @@ void Node::CopyDependencyGraph(const QVector &src, const QVector for (auto it=src_node->input_connections_.cbegin(); it!=src_node->input_connections_.cend(); it++) { // Determine if the connected node is in our src list - int connection_index = src.indexOf(it->second.node()); + int connection_index = src.indexOf(it->second); if (connection_index > -1) { // Find the equivalent node in the dst list - Node* dst_connection = dst.at(connection_index); - - NodeOutput copied_output = NodeOutput(dst_connection, it->second.output()); + Node *copied_output = dst.at(connection_index); NodeInput copied_input = NodeInput(dst_node, it->first.input(), it->first.element()); if (command) { command->add_child(new NodeEdgeAddCommand(copied_output, copied_input)); + command->add_child(new NodeSetValueHintCommand(copied_input, src_node->GetValueHintForInput(copied_input.input(), copied_input.element()))); } else { ConnectEdge(copied_output, copied_input); + copied_input.node()->SetValueHintForInput(copied_input.input(), copied_input.element(), src_node->GetValueHintForInput(copied_input.input(), copied_input.element())); } } } @@ -1128,8 +1125,7 @@ Node *Node::CopyNodeAndDependencyGraphMinusItemsInternal(QMap& cre // Go through input connections and copy if non-item and connect if item for (auto it=node->input_connections_.cbegin(); it!=node->input_connections_.cend(); it++) { NodeInput input = it->first; - NodeOutput output = it->second; - Node* connected = output.node(); + Node* connected = it->second; Node* connected_copy; if (connected->IsItem()) { @@ -1144,8 +1140,9 @@ Node *Node::CopyNodeAndDependencyGraphMinusItemsInternal(QMap& cre } } - command->add_child(new NodeEdgeAddCommand(NodeOutput(connected_copy, output.output()), - NodeInput(copy, input.input(), input.element()))); + NodeInput copied_input(copy, input.input(), input.element()); + command->add_child(new NodeEdgeAddCommand(connected_copy, copied_input)); + command->add_child(new NodeSetValueHintCommand(copied_input, node->GetValueHintForInput(input.input(), input.element()))); } if (node->parent()->GetPositionMap().contains(node)) { @@ -1256,10 +1253,9 @@ bool Node::AreLinked(Node *a, Node *b) return a->links_.contains(b); } -void Node::HashAddNodeSignature(QCryptographicHash &hash, const QString &output) const +void Node::HashAddNodeSignature(QCryptographicHash &hash) const { hash.addData(id().toUtf8()); - hash.addData(output.toUtf8()); } void Node::InsertInput(const QString &id, NodeValue::Type type, const QVariant &default_value, Node::InputFlags flags, int index) @@ -1306,32 +1302,6 @@ void Node::RemoveInput(const QString &id) emit InputRemoved(id); } -void Node::AddOutput(const QString &id) -{ - if (id.isEmpty()) { - qWarning() << "Rejected adding output with an empty ID on node" << this->id(); - return; - } - - if (HasParamWithID(id)) { - qWarning() << "Failed to add output to node" << this->id() << "- param with ID" << id << "already exists"; - return; - } - - outputs_.append(id); - - emit OutputAdded(id); -} - -void Node::RemoveOutput(const QString &id) -{ - if (outputs_.removeOne(id)) { - emit OutputRemoved(id); - } else { - ReportInvalidInput("remove", id); - } -} - void Node::ReportInvalidInput(const char *attempted_action, const QString& id) const { qWarning() << "Failed to" << attempted_action << "parameter" << id @@ -1453,13 +1423,29 @@ void Node::SetLabel(const QString &s) } } -void Node::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const +QString Node::GetLabelAndName() const +{ + if (GetLabel().isEmpty()) { + return Name(); + } else { + return tr("%1 (%2)").arg(GetLabel(), Name()); + } +} + +QString Node::GetLabelOrName() const +{ + if (GetLabel().isEmpty()) { + return Name(); + } + return GetLabel(); +} + +void Node::Hash(const ValueHint &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { // Add this Node's ID and output being used - HashAddNodeSignature(hash, output); + HashAddNodeSignature(hash); - auto inputs = inputs_for_output(output); - foreach (const QString& input, inputs) { + foreach (const QString& input, inputs()) { // For each input, try to hash its value if (ignore_when_hashing_.contains(input)) { continue; @@ -1557,10 +1543,9 @@ void Node::SetCanBeDeleted(bool s) void GetDependenciesRecursively(QVector& list, const Node* node, bool traverse, bool exclusive_only) { for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) { - Node* connected_node = it->second.node(); + Node* connected_node = it->second; - if (!exclusive_only - || (connected_node->outputs().size() == 1 && !connected_node->IsItem())) { + if (!exclusive_only || !connected_node->IsItem()) { if (!list.contains(connected_node)) { list.append(connected_node); @@ -1597,11 +1582,11 @@ void Node::HashInputElement(QCryptographicHash &hash, const QString& input, int if (IsInputConnected(input, element)) { // Traverse down this edge - NodeOutput output = GetConnectedOutput(input, element); + Node *output = GetConnectedOutput(input, element); NodeGlobals new_globals = globals; new_globals.set_time(input_time); - output.node()->Hash(output.output(), hash, new_globals, video_params); + output->Hash(GetValueHintForInput(input, element), hash, new_globals, video_params); } else { // Grab the value at this time QVariant value = GetValueAtTime(input, input_time.in(), element); @@ -1655,7 +1640,7 @@ bool Node::OutputsTo(Node *n, bool recursively, const OutputConnections &ignore_ return true; } else if (recursively && connected->OutputsTo(n, recursively, ignore_edges, added_edge)) { return true; - } else if (added_edge.first.node() == this) { + } else if (added_edge.first == this) { Node *proposed_connected = added_edge.second.node(); if (proposed_connected == n) { @@ -1702,11 +1687,11 @@ bool Node::OutputsTo(const NodeInput &input, bool recursively) const bool Node::InputsFrom(Node *n, bool recursively) const { for (auto it=input_connections_.cbegin(); it!=input_connections_.cend(); it++) { - const NodeOutput& connected = it->second; + Node *connected = it->second; - if (connected.node() == n) { + if (connected == n) { return true; - } else if (recursively && connected.node()->InputsFrom(n, recursively)) { + } else if (recursively && connected->InputsFrom(n, recursively)) { return true; } } @@ -1717,11 +1702,11 @@ bool Node::InputsFrom(Node *n, bool recursively) const bool Node::InputsFrom(const QString &id, bool recursively) const { for (auto it=input_connections_.cbegin(); it!=input_connections_.cend(); it++) { - const NodeOutput& connected = it->second; + Node *connected = it->second; - if (connected.node()->id() == id) { + if (connected->id() == id) { return true; - } else if (recursively && connected.node()->InputsFrom(id, recursively)) { + } else if (recursively && connected->InputsFrom(id, recursively)) { return true; } } @@ -1808,7 +1793,7 @@ QVector Node::TransformTimeTo(const TimeRange &time, Node *target, bo // If this input is connected, traverse it to see if we stumble across the specified `node` for (auto it=input_connections_.cbegin(); it!=input_connections_.cend(); it++) { TimeRange input_adjustment = InputTimeAdjustment(it->first.input(), it->first.element(), time); - Node* connected = it->second.node(); + Node* connected = it->second; if (connected == target) { // We found the target, no need to keep traversing @@ -2121,29 +2106,27 @@ void Node::InputValueChangedEvent(const QString &input, int element) Q_UNUSED(element) } -void Node::InputConnectedEvent(const QString &input, int element, const NodeOutput &output) +void Node::InputConnectedEvent(const QString &input, int element, Node *output) { Q_UNUSED(input) Q_UNUSED(element) Q_UNUSED(output) } -void Node::InputDisconnectedEvent(const QString &input, int element, const NodeOutput &output) +void Node::InputDisconnectedEvent(const QString &input, int element, Node *output) { Q_UNUSED(input) Q_UNUSED(element) Q_UNUSED(output) } -void Node::OutputConnectedEvent(const QString &output, const NodeInput &input) +void Node::OutputConnectedEvent(const NodeInput &input) { - Q_UNUSED(output) Q_UNUSED(input) } -void Node::OutputDisconnectedEvent(const QString &output, const NodeInput &input) +void Node::OutputDisconnectedEvent(const NodeInput &input) { - Q_UNUSED(output) Q_UNUSED(input) } diff --git a/app/node/node.h b/app/node/node.h index 6f67d59b9..57e7b7045 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -198,30 +198,14 @@ public: return input_ids_; } - virtual QVector inputs_for_output(const QString& output) const - { - Q_UNUSED(output) - return inputs(); - } - - const QVector& outputs() const - { - return outputs_; - } - bool HasInputWithID(const QString& id) const { return input_ids_.contains(id); } - bool HasOutputWithID(const QString& id) const - { - return outputs_.contains(id); - } - bool HasParamWithID(const QString& id) const { - return HasInputWithID(id) || HasOutputWithID(id); + return HasInputWithID(id); } /** @@ -255,9 +239,9 @@ public: } } - static void ConnectEdge(const NodeOutput& output, const NodeInput& input); + static void ConnectEdge(Node *output, const NodeInput& input); - static void DisconnectEdge(const NodeOutput& output, const NodeInput& input); + static void DisconnectEdge(Node *output, const NodeInput& input); QString GetInputName(const QString& id) const; @@ -295,23 +279,13 @@ public: return IsInputStatic(input.input(), input.element()); } - NodeOutput GetConnectedOutput(const QString& input, int element = -1) const; + Node *GetConnectedOutput(const QString& input, int element = -1) const; - NodeOutput GetConnectedOutput(const NodeInput& input) const + Node *GetConnectedOutput(const NodeInput& input) const { return GetConnectedOutput(input.input(), input.element()); } - Node* GetConnectedNode(const QString& input, int element = -1) const - { - return GetConnectedOutput(input, element).node(); - } - - Node* GetConnectedNode(const NodeInput& input) const - { - return GetConnectedNode(input.input(), input.element()); - } - bool IsUsingStandardValue(const QString& input, int track, int element = -1) const; NodeValue::Type GetInputDataType(const QString& id) const; @@ -494,19 +468,19 @@ public: QString tag; }; - ValueHint GetValueHintForInput(const QString &input) const + ValueHint GetValueHintForInput(const QString &input, int element) const { - return value_hints_.value(input); + return value_hints_.value({input, element}); } - void SetValueHintForInput(const QString &input, const ValueHint &hint) + void SetValueHintForInput(const QString &input, int element, const ValueHint &hint) { - value_hints_.insert(input, hint); + value_hints_.insert({input, element}, hint); } const NodeKeyframeTrack& GetTrackFromKeyframe(NodeKeyframe* key) const; - using InputConnections = std::map; + using InputConnections = std::map; /** * @brief Return map of input connections @@ -519,7 +493,7 @@ public: return input_connections_; } - using OutputConnection = std::pair; + using OutputConnection = std::pair; using OutputConnections = std::vector; /** @@ -739,7 +713,7 @@ 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 void Value(const QString &output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const; + virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const; virtual bool HasGizmos() const; @@ -752,7 +726,10 @@ public: const QString& GetLabel() const; void SetLabel(const QString& s); - virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const; + QString GetLabelAndName() const; + QString GetLabelOrName() const; + + virtual void Hash(const ValueHint &output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const; void InvalidateAll(const QString& input, int element = -1); @@ -873,7 +850,7 @@ protected: }; - void HashAddNodeSignature(QCryptographicHash &hash, const QString &output) const; + void HashAddNodeSignature(QCryptographicHash &hash) const; void InsertInput(const QString& id, NodeValue::Type type, const QVariant& default_value, InputFlags flags, int index); @@ -899,10 +876,6 @@ protected: void RemoveInput(const QString& id); - void AddOutput(const QString& id = kDefaultOutput); - - void RemoveOutput(const QString& id); - void SetInputName(const QString& id, const QString& name); void SetComboBoxStrings(const QString& id, const QStringList& strings) @@ -954,13 +927,13 @@ protected: virtual void InputValueChangedEvent(const QString& input, int element); - virtual void InputConnectedEvent(const QString& input, int element, const NodeOutput& output); + virtual void InputConnectedEvent(const QString& input, int element, Node *output); - virtual void InputDisconnectedEvent(const QString& input, int element, const NodeOutput& output); + virtual void InputDisconnectedEvent(const QString& input, int element, Node *output); - virtual void OutputConnectedEvent(const QString& output, const NodeInput& input); + virtual void OutputConnectedEvent(const NodeInput& input); - virtual void OutputDisconnectedEvent(const QString& output, const NodeInput& input); + virtual void OutputDisconnectedEvent(const NodeInput& input); virtual void childEvent(QChildEvent *event) override; @@ -984,13 +957,13 @@ signals: void ValueChanged(const NodeInput& input, const TimeRange& range); - void InputConnected(const NodeOutput& output, const NodeInput& input); + void InputConnected(Node *output, const NodeInput& input); - void InputDisconnected(const NodeOutput& output, const NodeInput& input); + void InputDisconnected(Node *output, const NodeInput& input); - void OutputConnected(const NodeOutput& output, const NodeInput& input); + void OutputConnected(Node *output, const NodeInput& input); - void OutputDisconnected(const NodeOutput& output, const NodeInput& input); + void OutputDisconnected(Node *output, const NodeInput& input); void InputPropertyChanged(const QString& input, const QString& key, const QVariant& value); @@ -1010,10 +983,6 @@ signals: void InputRemoved(const QString& id); - void OutputAdded(const QString& id); - - void OutputRemoved(const QString& id); - void InputNameChanged(const QString& id, const QString& name); void InputDataTypeChanged(const QString& id, NodeValue::Type type); @@ -1075,7 +1044,7 @@ private: try { NodeInput input(node_, input_, i); - NodeOutput output = node_->input_connections().at(input); + Node *output = node_->input_connections().at(input); removed_connections_[input] = output; @@ -1219,8 +1188,6 @@ private: QVector input_ids_; QVector input_data_; - QVector outputs_; - QMap standard_immediates_; QMap > array_immediates_; @@ -1237,7 +1204,7 @@ private: bool cache_result_; - QMap value_hints_; + QMap value_hints_; private slots: /** @@ -1271,7 +1238,7 @@ template void Node::FindInputNodeInternal(const Node* n, QVector &list) { for (auto it=n->input_connections_.cbegin(); it!=n->input_connections_.cend(); it++) { - Node* edge = it->second.node(); + Node* edge = it->second; T* cast_test = dynamic_cast(edge); if (cast_test) { diff --git a/app/node/output/track/track.cpp b/app/node/output/track/track.cpp index 4f4c4a8dc..de2141cf3 100644 --- a/app/node/output/track/track.cpp +++ b/app/node/output/track/track.cpp @@ -72,6 +72,14 @@ Node *Track::copy() const QString Track::Name() const { + if (track_type_ == Track::kVideo) { + return tr("Video Track %1").arg(index_); + } else if (track_type_ == Track::kAudio) { + return tr("Audio Track %1").arg(index_); + } else if (track_type_ == Track::kSubtitle) { + return tr("Subtitle Track %1").arg(index_); + } + return tr("Track"); } @@ -145,7 +153,7 @@ void Track::SaveCustom(QXmlStreamWriter *writer) const writer->writeTextElement(QStringLiteral("height"), QString::number(GetTrackHeight())); } -void Track::InputConnectedEvent(const QString &input, int element, const NodeOutput &output) +void Track::InputConnectedEvent(const QString &input, int element, Node *output) { if (input == kBlockInput) { if (element == -1) { @@ -155,7 +163,7 @@ void Track::InputConnectedEvent(const QString &input, int element, const NodeOut } // Check if a block was connected, if not, ignore - Block* block = dynamic_cast(output.node()); + Block* block = dynamic_cast(output); if (!block) { return; @@ -220,7 +228,7 @@ void Track::InputConnectedEvent(const QString &input, int element, const NodeOut } } -void Track::InputDisconnectedEvent(const QString &input, int element, const NodeOutput &output) +void Track::InputDisconnectedEvent(const QString &input, int element, Node *output) { if (input == kBlockInput) { if (element == -1) { @@ -229,7 +237,7 @@ void Track::InputDisconnectedEvent(const QString &input, int element, const Node return; } - Block* b = dynamic_cast(output.node()); + Block* b = dynamic_cast(output); if (!b) { return; @@ -425,7 +433,7 @@ void Track::InvalidateCache(const TimeRange& range, const QString& from, int ele if (from == kBlockInput && element >= 0 - && (b = dynamic_cast(GetConnectedOutput(from, element).node())) + && (b = dynamic_cast(GetConnectedOutput(from, element))) && !options.value(QStringLiteral("lengthevent")).toBool()) { // Limit the range signal to the corresponding block TimeRange transformed = TransformRangeFromBlock(b, range); @@ -553,23 +561,6 @@ rational Track::track_length() const } } -QString Track::GetDefaultTrackName(Track::Type type, int index) -{ - // Starts tracks at 1 rather than 0 - int user_friendly_index = index+1; - - switch (type) { - case Track::kVideo: return tr("Video %1").arg(user_friendly_index); - case Track::kAudio: return tr("Audio %1").arg(user_friendly_index); - case Track::kSubtitle: return tr("Subtitle %1").arg(user_friendly_index); - case Track::kNone: - case Track::kCount: - break; - } - - return tr("Track %1").arg(user_friendly_index); -} - bool Track::IsMuted() const { return GetStandardValue(kMutedInput).toBool(); @@ -580,7 +571,7 @@ bool Track::IsLocked() const return locked_; } -void Track::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const +void Track::Hash(const Node::ValueHint &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const { Q_UNUSED(output) @@ -590,7 +581,7 @@ void Track::Hash(const QString &output, QCryptographicHash &hash, const NodeGlob if (b) { NodeGlobals new_globals = globals; new_globals.set_time(TransformRangeForBlock(b, globals.time())); - b->Hash(kDefaultOutput, hash, new_globals, video_params); + b->Hash(GetValueHintForInput(kBlockInput, GetArrayIndexFromBlock(b)), hash, new_globals, video_params); } } diff --git a/app/node/output/track/track.h b/app/node/output/track/track.h index f56934f2e..e0a167aea 100644 --- a/app/node/output/track/track.h +++ b/app/node/output/track/track.h @@ -355,13 +355,13 @@ public: rational track_length() const; - static QString GetDefaultTrackName(Track::Type type, int index); - bool IsMuted() const; bool IsLocked() const; - virtual void Hash(const QString& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override; + virtual void Hash(const Node::ValueHint& output, QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const override; + + int GetArrayIndexFromBlock(Block* block) const; static const double kTrackHeightDefault; static const double kTrackHeightMinimum; @@ -416,17 +416,15 @@ protected: virtual void SaveCustom(QXmlStreamWriter* writer) const override; - virtual void InputConnectedEvent(const QString& input, int element, const NodeOutput& output) override; + virtual void InputConnectedEvent(const QString& input, int element, Node *output) override; - virtual void InputDisconnectedEvent(const QString& input, int element, const NodeOutput& output) override; + virtual void InputDisconnectedEvent(const QString& input, int element, Node *output) override; virtual void InputValueChangedEvent(const QString& input, int element) override; private: void UpdateInOutFrom(int index); - int GetArrayIndexFromBlock(Block* block) const; - int GetArrayIndexFromCacheIndex(int index) const; int GetCacheIndexFromArrayIndex(int index) const; diff --git a/app/node/output/viewer/viewer.cpp b/app/node/output/viewer/viewer.cpp index c4f779208..75f77d7de 100644 --- a/app/node/output/viewer/viewer.cpp +++ b/app/node/output/viewer/viewer.cpp @@ -252,20 +252,6 @@ void ViewerOutput::InvalidateCache(const TimeRange& range, const QString& from, super::InvalidateCache(range, from, element, options); } -QVector ViewerOutput::inputs_for_output(const QString &output) const -{ - QVector inputs; - Track::Type type = Track::Reference::TypeFromString(output); - - if (type == Track::kVideo) { - inputs.append(kTextureInput); - } else if (type == Track::kAudio) { - inputs.append(kSamplesInput); - } - - return inputs; -} - QVector ViewerOutput::GetEnabledStreamsAsReferences() const { QVector refs; @@ -329,7 +315,7 @@ void ViewerOutput::VerifyLength() } } -void ViewerOutput::InputConnectedEvent(const QString &input, int element, const NodeOutput &output) +void ViewerOutput::InputConnectedEvent(const QString &input, int element, Node *output) { if (input == kTextureInput) { emit TextureInputChanged(); @@ -338,7 +324,7 @@ void ViewerOutput::InputConnectedEvent(const QString &input, int element, const super::InputConnectedEvent(input, element, output); } -void ViewerOutput::InputDisconnectedEvent(const QString &input, int element, const NodeOutput &output) +void ViewerOutput::InputDisconnectedEvent(const QString &input, int element, Node *output) { if (input == kTextureInput) { emit TextureInputChanged(); @@ -354,7 +340,7 @@ rational ViewerOutput::VerifyLengthInternal(Track::Type type) const switch (type) { case Track::kVideo: if (IsInputConnected(kTextureInput)) { - NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kTextureInput), TimeRange(0, 0)); + NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kTextureInput), GetValueHintForInput(kTextureInput, -1), TimeRange(0, 0)); rational r = t.Get(NodeValue::kRational, QStringLiteral("length")).value(); if (!r.isNaN()) { return r; @@ -363,7 +349,7 @@ rational ViewerOutput::VerifyLengthInternal(Track::Type type) const break; case Track::kAudio: if (IsInputConnected(kSamplesInput)) { - NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kSamplesInput), TimeRange(0, 0)); + NodeValueTable t = traverser.GenerateTable(GetConnectedOutput(kSamplesInput), GetValueHintForInput(kSamplesInput, -1), TimeRange(0, 0)); rational r = t.Get(NodeValue::kRational, QStringLiteral("length")).value();; if (!r.isNaN()) { return r; @@ -379,12 +365,12 @@ rational ViewerOutput::VerifyLengthInternal(Track::Type type) const return 0; } -NodeOutput ViewerOutput::GetConnectedTextureOutput() +Node *ViewerOutput::GetConnectedTextureOutput() { return GetConnectedOutput(kTextureInput); } -NodeOutput ViewerOutput::GetConnectedSampleOutput() +Node *ViewerOutput::GetConnectedSampleOutput() { return GetConnectedOutput(kSamplesInput); } diff --git a/app/node/output/viewer/viewer.h b/app/node/output/viewer/viewer.h index cb4309a67..6ba9bdd2d 100644 --- a/app/node/output/viewer/viewer.h +++ b/app/node/output/viewer/viewer.h @@ -68,8 +68,6 @@ public: virtual void InvalidateCache(const TimeRange& range, const QString& from, int element, InvalidateCacheOptions options) override; - virtual QVector inputs_for_output(const QString& output) const override; - VideoParams GetVideoParams(int index = 0) const { // This check isn't strictly necessary (GetStandardValue will return a null VideoParams anyway), @@ -150,9 +148,9 @@ public: virtual void Retranslate() override; - virtual NodeOutput GetConnectedTextureOutput(); + virtual Node *GetConnectedTextureOutput(); - virtual NodeOutput GetConnectedSampleOutput(); + virtual Node *GetConnectedSampleOutput(); void SetViewerVideoCacheEnabled(bool e) { video_cache_enabled_ = e; } void SetViewerAudioCacheEnabled(bool e) { audio_cache_enabled_ = e; } @@ -207,9 +205,9 @@ public slots: void VerifyLength(); protected: - virtual void InputConnectedEvent(const QString &input, int element, const NodeOutput &output) override; + virtual void InputConnectedEvent(const QString &input, int element, Node *output) override; - virtual void InputDisconnectedEvent(const QString &input, int element, const NodeOutput &output) override; + virtual void InputDisconnectedEvent(const QString &input, int element, Node *output) override; virtual rational VerifyLengthInternal(Track::Type type) const; diff --git a/app/node/param.cpp b/app/node/param.cpp index c972822d3..9f6bd8c4d 100644 --- a/app/node/param.cpp +++ b/app/node/param.cpp @@ -60,12 +60,12 @@ bool NodeInput::IsArray() const } } -NodeOutput NodeInput::GetConnectedOutput() const +Node *NodeInput::GetConnectedOutput() const { if (IsValid()) { return node_->GetConnectedOutput(*this); } else { - return NodeOutput(); + return nullptr; } } @@ -128,12 +128,6 @@ uint qHash(const NodeInput &i) return qHash(i.node()) ^ qHash(i.input()) ^ qHash(i.element()); } -NodeOutput::NodeOutput(Node *n) -{ - node_ = n; - output_ = Node::kDefaultOutput; -} - uint qHash(const NodeKeyframeTrackReference &i) { return qHash(i.input()) & qHash(i.track()); diff --git a/app/node/param.h b/app/node/param.h index b13e8a342..575ef6f8b 100644 --- a/app/node/param.h +++ b/app/node/param.h @@ -41,51 +41,6 @@ struct NodeInputPair { QString input; }; -/** - * @brief Defines a node output - */ -class NodeOutput -{ -public: - NodeOutput(Node* n, const QString& o) - { - node_ = n; - output_ = o; - } - - NodeOutput(Node* n); - - NodeOutput() - { - node_ = nullptr; - } - - bool operator==(const NodeOutput& rhs) const - { - return node_ == rhs.node_ && output_ == rhs.output_; - } - - Node* node() const - { - return node_; - } - - const QString& output() const - { - return output_; - } - - bool IsValid() const - { - return node_; - } - -private: - Node* node_; - QString output_; - -}; - /** * @brief Defines a Node input */ @@ -166,7 +121,7 @@ public: bool IsArray() const; - NodeOutput GetConnectedOutput() const; + Node *GetConnectedOutput() const; NodeValue::Type GetDataType() const; @@ -192,6 +147,30 @@ private: }; +struct InputElementPair { + QString input; + int element; + + bool operator<(const InputElementPair &rhs) const + { + if (input != rhs.input) { + return input < rhs.input; + } + + return element < rhs.element; + } + + bool operator==(const InputElementPair &rhs) const + { + return input == rhs.input && element == rhs.element; + } + + bool operator!=(const InputElementPair &rhs) const + { + return !(*this == rhs); + } +}; + class NodeKeyframeTrackReference { public: NodeKeyframeTrackReference() diff --git a/app/node/project/folder/folder.cpp b/app/node/project/folder/folder.cpp index 0dde22fff..feae6d612 100644 --- a/app/node/project/folder/folder.cpp +++ b/app/node/project/folder/folder.cpp @@ -84,10 +84,10 @@ int Folder::index_of_child_in_array(Node *item) const return item_element_index_.at(index_of_item); } -void Folder::InputConnectedEvent(const QString &input, int element, const NodeOutput &output) +void Folder::InputConnectedEvent(const QString &input, int element, Node *output) { if (input == kChildInput && element != -1) { - Node* item = output.node(); + Node* item = output; // The insert index is always our "count" because we only support appending in our internal // model. For sorting/organizing, a QSortFilterProxyModel is used instead. @@ -99,10 +99,10 @@ void Folder::InputConnectedEvent(const QString &input, int element, const NodeOu } } -void Folder::InputDisconnectedEvent(const QString &input, int element, const NodeOutput &output) +void Folder::InputDisconnectedEvent(const QString &input, int element, Node *output) { if (input == kChildInput && element != -1) { - Node* item = output.node(); + Node* item = output; int child_index = item_children_.indexOf(item); emit BeginRemoveItem(item, child_index); diff --git a/app/node/project/folder/folder.h b/app/node/project/folder/folder.h index c1436f1c7..1303ce7d7 100644 --- a/app/node/project/folder/folder.h +++ b/app/node/project/folder/folder.h @@ -170,9 +170,9 @@ signals: void EndRemoveItem(); protected: - virtual void InputConnectedEvent(const QString& input, int element, const NodeOutput& output) override; + virtual void InputConnectedEvent(const QString& input, int element, Node *output) override; - virtual void InputDisconnectedEvent(const QString& input, int element, const NodeOutput& output) override; + virtual void InputDisconnectedEvent(const QString& input, int element, Node *output) override; private: template diff --git a/app/node/project/footage/footage.cpp b/app/node/project/footage/footage.cpp index b9663a8ba..8e4bd32b0 100644 --- a/app/node/project/footage/footage.cpp +++ b/app/node/project/footage/footage.cpp @@ -73,12 +73,6 @@ void Footage::Retranslate() SetComboBoxStrings(kLoopModeInput, {tr("None"), tr("Loop"), tr("Clamp")}); } -QVector Footage::inputs_for_output(const QString &output) const -{ - Q_UNUSED(output) - return {kFilenameInput, kLoopModeInput}; -} - bool Footage::LoadCustom(QXmlStreamReader *reader, XMLNodeData &xml_node_data, uint version, const QAtomicInt* cancelled) { if (reader->name() == QStringLiteral("timestamp")) { @@ -280,6 +274,24 @@ int Footage::GetStreamIndex(Track::Type type, int index) const } } +Track::Reference Footage::GetReferenceFromRealIndex(int real_index) const +{ + // Check video streams + for (int i=0; icolor_manager()->GetConfigFilename().toUtf8()); + hash.addData(GetColorspaceToUse(params).toUtf8()); - if (params.is_valid()) { - // Add footage details to hash - QString fn = filename(); + // Alpha associated setting + hash.addData(QString::number(params.premultiplied_alpha()).toUtf8()); - // Footage stream - hash.addData(QString::number(ref.index()).toUtf8()); + // Pixel aspect ratio + hash.addData(reinterpret_cast(¶ms.pixel_aspect_ratio()), sizeof(params.pixel_aspect_ratio())); - if (!fn.isEmpty()) { - // Current color config and space - hash.addData(project()->color_manager()->GetConfigFilename().toUtf8()); - hash.addData(GetColorspaceToUse(params).toUtf8()); + // Footage timestamp + if (params.video_type() != VideoParams::kVideoTypeStill) { + rational adjusted_time = AdjustTimeByLoopMode(globals.time().in(), loop_mode(), GetLength(), params.video_type(), params.frame_rate_as_time_base()); - // Alpha associated setting - hash.addData(QString::number(params.premultiplied_alpha()).toUtf8()); + if (!adjusted_time.isNaN()) { + int64_t video_ts = Timecode::time_to_timestamp(adjusted_time, params.time_base()); - // Pixel aspect ratio - hash.addData(reinterpret_cast(¶ms.pixel_aspect_ratio()), sizeof(params.pixel_aspect_ratio())); - - // Footage timestamp - if (params.video_type() != VideoParams::kVideoTypeStill) { - 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()); - - // Add timestamp in units of the video stream's timebase - hash.addData(reinterpret_cast(&video_ts), sizeof(video_ts)); - } - - // Add start time - used for both image sequences and video streams - auto start_time = params.start_time(); - hash.addData(reinterpret_cast(&start_time), sizeof(start_time)); - } + // Add timestamp in units of the video stream's timebase + hash.addData(reinterpret_cast(&video_ts), sizeof(video_ts)); } + + // Add start time - used for both image sequences and video streams + auto start_time = params.start_time(); + hash.addData(reinterpret_cast(&start_time), sizeof(start_time)); } } } -void Footage::Value(const QString &output, const NodeValueRow &value, const NodeGlobals &globals, NodeValueTable *table) const +void Footage::Value(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].data().toString(); @@ -387,23 +384,29 @@ void Footage::Value(const QString &output, const NodeValueRow &value, const Node // If the file exists and the reference is valid, push a footage job to the renderer if (QFileInfo(file).exists()) { - FootageJob job(decoder_, filename(), ref.type(), GetLength(), loop_mode); - - if (ref.type() == Track::kVideo) { - VideoParams vp = GetVideoParams(ref.index()); - - // Ensure the colorspace is valid and not empty - vp.set_colorspace(GetColorspaceToUse(vp)); - - job.set_video_params(vp); - } else { - AudioParams ap = GetAudioParams(ref.index()); - job.set_audio_params(ap); - job.set_cache_path(project()->cache_path()); - } - + // Push length table->Push(NodeValue::kRational, QVariant::fromValue(GetLength()), this, false, QStringLiteral("length")); - table->Push(NodeValue::kFootageJob, QVariant::fromValue(job), this); + + // Push each stream as a footage job + for (int i=0; icache_path()); + } + + table->Push(NodeValue::kFootageJob, QVariant::fromValue(job), this, false, ref.ToString()); + } } } @@ -424,23 +427,21 @@ QString Footage::GetStreamTypeName(Track::Type type) return tr("Unknown"); } -NodeOutput Footage::GetConnectedTextureOutput() +Node *Footage::GetConnectedTextureOutput() { - QString output = Track::Reference(Track::kVideo, 0).ToString(); - if (HasOutputWithID(output)) { - return NodeOutput(this, output); + if (GetVideoStreamCount() > 0) { + return this; } else { - return NodeOutput(); + return nullptr; } } -NodeOutput Footage::GetConnectedSampleOutput() +Node *Footage::GetConnectedSampleOutput() { - QString output = Track::Reference(Track::kAudio, 0).ToString(); - if (HasOutputWithID(output)) { - return NodeOutput(this, output); + if (GetAudioStreamCount() > 0) { + return this; } else { - return NodeOutput(); + return nullptr; } } diff --git a/app/node/project/footage/footage.h b/app/node/project/footage/footage.h index 4f31650b6..4b3cba828 100644 --- a/app/node/project/footage/footage.h +++ b/app/node/project/footage/footage.h @@ -84,8 +84,6 @@ public: virtual void Retranslate() override; - virtual QVector inputs_for_output(const QString &output) const override; - /** * @brief Reset Footage state ready for running through Probe() again * @@ -181,15 +179,15 @@ public: static QString DescribeVideoStream(const VideoParams& params); static QString DescribeAudioStream(const AudioParams& params); - virtual void Hash(const QString& output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override; + virtual void Hash(const ValueHint &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override; - virtual void Value(const QString &output, const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; static QString GetStreamTypeName(Track::Type type); - virtual NodeOutput GetConnectedTextureOutput() override; + virtual Node *GetConnectedTextureOutput() override; - virtual NodeOutput GetConnectedSampleOutput() override; + virtual Node *GetConnectedSampleOutput() override; static rational AdjustTimeByLoopMode(rational time, LoopMode loop_mode, const rational& length, VideoParams::Type type, const rational &timebase); diff --git a/app/node/project/sequence/sequence.cpp b/app/node/project/sequence/sequence.cpp index 4c05bb501..27b17708f 100644 --- a/app/node/project/sequence/sequence.cpp +++ b/app/node/project/sequence/sequence.cpp @@ -137,12 +137,12 @@ rational Sequence::VerifyLengthInternal(Track::Type type) const return 0; } -void Sequence::InputConnectedEvent(const QString &input, int element, const NodeOutput &output) +void Sequence::InputConnectedEvent(const QString &input, int element, Node *output) { foreach (TrackList* list, track_lists_) { if (list->track_input() == input) { // Return because we found our input - list->TrackConnected(output.node(), element); + list->TrackConnected(output, element); return; } } @@ -150,12 +150,12 @@ void Sequence::InputConnectedEvent(const QString &input, int element, const Node super::InputConnectedEvent(input, element, output); } -void Sequence::InputDisconnectedEvent(const QString &input, int element, const NodeOutput &output) +void Sequence::InputDisconnectedEvent(const QString &input, int element, Node *output) { foreach (TrackList* list, track_lists_) { if (list->track_input() == input) { // Return because we found our input - list->TrackDisconnected(output.node(), element); + list->TrackDisconnected(output, element); return; } } diff --git a/app/node/project/sequence/sequence.h b/app/node/project/sequence/sequence.h index fd50b9e92..62900b031 100644 --- a/app/node/project/sequence/sequence.h +++ b/app/node/project/sequence/sequence.h @@ -97,9 +97,9 @@ public: } protected: - virtual void InputConnectedEvent(const QString &input, int element, const NodeOutput &output) override; + virtual void InputConnectedEvent(const QString &input, int element, Node *output) override; - virtual void InputDisconnectedEvent(const QString &input, int element, const NodeOutput &output) override; + virtual void InputDisconnectedEvent(const QString &input, int element, Node *output) override; virtual rational VerifyLengthInternal(Track::Type type) const override; diff --git a/app/node/time/timeremap/timeremap.cpp b/app/node/time/timeremap/timeremap.cpp index e3205712f..e8310937c 100644 --- a/app/node/time/timeremap/timeremap.cpp +++ b/app/node/time/timeremap/timeremap.cpp @@ -34,6 +34,7 @@ TimeRemapNode::TimeRemapNode() AddInput(kTimeInput, NodeValue::kRational, QVariant::fromValue(rational(0)), InputFlags(kInputFlagNotConnectable)); SetInputProperty(kTimeInput, QStringLiteral("view"), RationalSlider::kTime); SetInputProperty(kTimeInput, QStringLiteral("viewlock"), true); + IgnoreHashingFrom(kTimeInput); AddInput(kInputInput, NodeValue::kNone, InputFlags(kInputFlagNotKeyframable)); } @@ -92,22 +93,16 @@ void TimeRemapNode::Retranslate() SetInputName(kInputInput, QStringLiteral("Input")); } -QVector TimeRemapNode::inputs_for_output(const QString &output) const -{ - Q_UNUSED(output) - return {kInputInput}; -} - -void TimeRemapNode::Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams &video_params) const +void TimeRemapNode::Hash(const ValueHint &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); + Node *out = GetConnectedOutput(kInputInput); 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); + out->Hash(GetValueHintForInput(kInputInput, -1), hash, new_globals, video_params); } } diff --git a/app/node/time/timeremap/timeremap.h b/app/node/time/timeremap/timeremap.h index b36fa052d..52250a140 100644 --- a/app/node/time/timeremap/timeremap.h +++ b/app/node/time/timeremap/timeremap.h @@ -45,9 +45,7 @@ public: virtual void Retranslate() override; - virtual QVector inputs_for_output(const QString &output) const override; - - virtual void Hash(const QString &output, QCryptographicHash &hash, const NodeGlobals &globals, const VideoParams& video_params) const override; + virtual void Hash(const ValueHint &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 8b8cf47eb..55a786ea7 100644 --- a/app/node/traverser.cpp +++ b/app/node/traverser.cpp @@ -26,13 +26,12 @@ namespace olive { -NodeValueDatabase NodeTraverser::GenerateDatabase(const Node* node, const QString& output, const TimeRange &range) +NodeValueDatabase NodeTraverser::GenerateDatabase(const Node* node, const TimeRange &range) { NodeValueDatabase database; // We need to insert tables into the database for each input - auto inputs = node->inputs_for_output(output); - foreach (const QString& input, inputs) { + foreach (const QString& input, node->inputs()) { if (IsCancelled()) { return NodeValueDatabase(); } @@ -43,7 +42,7 @@ NodeValueDatabase NodeTraverser::GenerateDatabase(const Node* node, const QStrin return database; } -NodeValueRow NodeTraverser::GenerateRow(NodeValueDatabase *database, const Node *node, const QString &output, const TimeRange &range) +NodeValueRow NodeTraverser::GenerateRow(NodeValueDatabase *database, const Node *node, const TimeRange &range) { // Generate row NodeValueRow row; @@ -55,17 +54,36 @@ NodeValueRow NodeTraverser::GenerateRow(NodeValueDatabase *database, const Node return row; } -NodeValueRow NodeTraverser::GenerateRow(const Node *node, const QString &output, const TimeRange &range) +NodeValueRow NodeTraverser::GenerateRow(const Node *node, const TimeRange &range) { // Generate database of input values of node - NodeValueDatabase database = GenerateDatabase(node, output, range); + NodeValueDatabase database = GenerateDatabase(node, range); - return GenerateRow(&database, node, output, range); + return GenerateRow(&database, node, range); } NodeValue NodeTraverser::GenerateRowValue(const Node *node, const QString &input, NodeValueTable *table) { - Node::ValueHint hint = node->GetValueHintForInput(input); + NodeValue value = GenerateRowValueElement(node, input, -1, table); + + if (value.array()) { + // Resolve each element of array + QVector tables = value.data().value >(); + QVector output(tables.size()); + + for (int i=0; iGetValueHintForInput(input, element); QVector types = hint.type; if (types.isEmpty()) { @@ -133,7 +151,7 @@ NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& inpu TimeRange adjusted_range = node->InputTimeAdjustment(input, -1, range); // Value will equal something from the connected node, follow it - return GenerateTable(node->GetConnectedOutput(input), adjusted_range); + return GenerateTable(node->GetConnectedOutput(input), node->GetValueHintForInput(input, -1), adjusted_range); } else { @@ -151,7 +169,7 @@ NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& inpu TimeRange adjusted_range = node->InputTimeAdjustment(input, i, range); if (node->IsInputConnected(input, i)) { - sub_tbl = GenerateTable(node->GetConnectedOutput(input, i), adjusted_range); + sub_tbl = GenerateTable(node->GetConnectedOutput(input, i), node->GetValueHintForInput(input, i), adjusted_range); } else { QVariant input_value = node->GetValueAtTime(input, adjusted_range.in(), i); sub_tbl.Push(node->GetInputDataType(input), input_value, node); @@ -176,7 +194,7 @@ NodeValueTable NodeTraverser::ProcessInput(const Node* node, const QString& inpu } } -NodeValueTable NodeTraverser::GenerateTable(const Node *n, const QString& output, const TimeRange& range) +NodeValueTable NodeTraverser::GenerateTable(const Node *n, const Node::ValueHint &hint, const TimeRange& range) { const Track* track = dynamic_cast(n); if (track) { @@ -187,8 +205,8 @@ NodeValueTable NodeTraverser::GenerateTable(const Node *n, const QString& output // FIXME: Cache certain values here if we've already processed them before // Generate row for node - NodeValueDatabase database = GenerateDatabase(n, output, range); - NodeValueRow row = GenerateRow(&database, n, output, range); + NodeValueDatabase database = GenerateDatabase(n, range); + NodeValueRow row = GenerateRow(&database, n, range); //qDebug() << "FIXME: Implement pre-process of row"; @@ -196,10 +214,10 @@ NodeValueTable NodeTraverser::GenerateTable(const Node *n, const QString& output NodeValueTable table = database.Merge(); // By this point, the node should have all the inputs it needs to render correctly - n->Value(output, row, GenerateGlobals(video_params_, range), &table); + n->Value(row, GenerateGlobals(video_params_, range), &table); // Post-process table - PostProcessTable(n, output, range, table); + PostProcessTable(n, hint, range, table); return table; } @@ -212,7 +230,7 @@ NodeValueTable NodeTraverser::GenerateBlockTable(const Track *track, const TimeR NodeValueTable table; if (active_block) { - table = GenerateTable(active_block, Track::TransformRangeForBlock(active_block, range)); + table = GenerateTable(active_block, track->GetValueHintForInput(Track::kBlockInput, track->GetArrayIndexFromBlock(active_block)), Track::TransformRangeForBlock(active_block, range)); } return table; @@ -231,7 +249,7 @@ QVariant NodeTraverser::ProcessAudioFootage(const FootageJob& stream, const Time Q_UNUSED(stream) Q_UNUSED(input_time) - return QVariant(); + return QVariant::fromValue(SampleBuffer::Create()); } QVariant NodeTraverser::ProcessShader(const Node *node, const TimeRange &range, const ShaderJob &job) @@ -284,7 +302,7 @@ QVector2D NodeTraverser::GenerateResolution() const return QVector2D(video_params_.square_pixel_width(), video_params_.height()); } -void NodeTraverser::PostProcessTable(const Node *node, const QString& output, const TimeRange &range, NodeValueTable &output_params) +void NodeTraverser::PostProcessTable(const Node *node, const Node::ValueHint &hint, const TimeRange &range, NodeValueTable &output_params) { bool got_cached_frame = false; QByteArray cached_node_hash; @@ -292,7 +310,7 @@ void NodeTraverser::PostProcessTable(const Node *node, const QString& output, co // Convert footage to image/sample buffers if (CanCacheFrames() && node->GetCacheTextures()) { // This node is set to cache the result, see if we can retrieved a previously cached version - cached_node_hash = RenderManager::Hash(node, output, GetCacheVideoParams(), range.in()); + cached_node_hash = RenderManager::Hash(node, hint, GetCacheVideoParams(), range.in()); QVariant cached_frame = GetCachedTexture(cached_node_hash); if (!cached_frame.isNull()) { diff --git a/app/node/traverser.h b/app/node/traverser.h index 31f87f1c5..8ad6d822c 100644 --- a/app/node/traverser.h +++ b/app/node/traverser.h @@ -36,18 +36,15 @@ class NodeTraverser : public CancelableObject public: NodeTraverser() = default; - NodeValueTable GenerateTable(const Node *n, const QString &output, const TimeRange &range); - NodeValueTable GenerateTable(const NodeOutput& output, const TimeRange &range) - { - return GenerateTable(output.node(), output.output(), range); - } + NodeValueTable GenerateTable(const Node *n, const Node::ValueHint &hint, const TimeRange &range); - NodeValueDatabase GenerateDatabase(const Node *node, const QString &output, const TimeRange &range); + NodeValueDatabase GenerateDatabase(const Node *node, 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); + NodeValueRow GenerateRow(NodeValueDatabase *database, const Node *node, const TimeRange &range); + NodeValueRow GenerateRow(const Node *node, const TimeRange &range); NodeValue GenerateRowValue(const Node *node, const QString &input, NodeValueTable *table); + NodeValue GenerateRowValueElement(const Node *node, const QString &input, int element, NodeValueTable *table); static NodeGlobals GenerateGlobals(const VideoParams ¶ms, const TimeRange &time); static NodeGlobals GenerateGlobals(const VideoParams ¶ms, const rational &time) @@ -94,7 +91,7 @@ protected: QVector2D GenerateResolution() const; private: - void PostProcessTable(const Node *node, const QString &output, const TimeRange &range, NodeValueTable &output_params); + void PostProcessTable(const Node *node, const Node::ValueHint &hint, const TimeRange &range, NodeValueTable &output_params); VideoParams video_params_; diff --git a/app/render/previewautocacher.cpp b/app/render/previewautocacher.cpp index c4896f21c..a2a9a50d0 100644 --- a/app/render/previewautocacher.cpp +++ b/app/render/previewautocacher.cpp @@ -70,7 +70,7 @@ QVector PreviewAutoCacher::GenerateHashes(ViewerOut const rational &time = times.at(i); // See if hash already exists in disk cache - QByteArray hash = RenderManager::Hash(viewer->GetConnectedTextureOutput(), viewer->GetVideoParams(), time); + QByteArray hash = RenderManager::Hash(viewer->GetConnectedTextureOutput(), viewer->GetValueHintForInput(ViewerOutput::kTextureInput, -1), viewer->GetVideoParams(), time); // Check memory list since disk checking is slow bool hash_exists = existing_hashes.contains(hash); @@ -357,20 +357,20 @@ void PreviewAutoCacher::RemoveNode(Node *node) delete copy; } -void PreviewAutoCacher::AddEdge(const NodeOutput &output, const NodeInput &input) +void PreviewAutoCacher::AddEdge(Node *output, const NodeInput &input) { - Node* our_output = copy_map_.value(output.node()); + Node* our_output = copy_map_.value(output); Node* our_input = copy_map_.value(input.node()); - Node::ConnectEdge(NodeOutput(our_output, output.output()), NodeInput(our_input, input.input(), input.element())); + Node::ConnectEdge(our_output, NodeInput(our_input, input.input(), input.element())); } -void PreviewAutoCacher::RemoveEdge(const NodeOutput &output, const NodeInput &input) +void PreviewAutoCacher::RemoveEdge(Node *output, const NodeInput &input) { - Node* our_output = copy_map_.value(output.node()); + Node* our_output = copy_map_.value(output); Node* our_input = copy_map_.value(input.node()); - Node::DisconnectEdge(NodeOutput(our_output, output.output()), NodeInput(our_input, input.input(), input.element())); + Node::DisconnectEdge(our_output, NodeInput(our_input, input.input(), input.element())); } void PreviewAutoCacher::CopyValue(const NodeInput &input) @@ -458,23 +458,23 @@ void PreviewAutoCacher::ClearVideoDownloadQueue(bool hard) void PreviewAutoCacher::NodeAdded(Node *node) { - graph_update_queue_.append({QueuedJob::kNodeAdded, node, NodeInput(), NodeOutput()}); + graph_update_queue_.append({QueuedJob::kNodeAdded, node, NodeInput(), nullptr}); UpdateGraphChangeValue(); } void PreviewAutoCacher::NodeRemoved(Node *node) { - graph_update_queue_.append({QueuedJob::kNodeRemoved, node, NodeInput(), NodeOutput()}); + graph_update_queue_.append({QueuedJob::kNodeRemoved, node, NodeInput(), nullptr}); UpdateGraphChangeValue(); } -void PreviewAutoCacher::EdgeAdded(const NodeOutput &output, const NodeInput &input) +void PreviewAutoCacher::EdgeAdded(Node *output, const NodeInput &input) { graph_update_queue_.append({QueuedJob::kEdgeAdded, nullptr, input, output}); UpdateGraphChangeValue(); } -void PreviewAutoCacher::EdgeRemoved(const NodeOutput &output, const NodeInput &input) +void PreviewAutoCacher::EdgeRemoved(Node *output, const NodeInput &input) { graph_update_queue_.append({QueuedJob::kEdgeRemoved, nullptr, input, output}); UpdateGraphChangeValue(); @@ -482,7 +482,7 @@ void PreviewAutoCacher::EdgeRemoved(const NodeOutput &output, const NodeInput &i void PreviewAutoCacher::ValueChanged(const NodeInput &input) { - graph_update_queue_.append({QueuedJob::kValueChanged, nullptr, input, NodeOutput()}); + graph_update_queue_.append({QueuedJob::kValueChanged, nullptr, input, nullptr}); UpdateGraphChangeValue(); } diff --git a/app/render/previewautocacher.h b/app/render/previewautocacher.h index af59b4cf7..eb6ed5480 100644 --- a/app/render/previewautocacher.h +++ b/app/render/previewautocacher.h @@ -87,8 +87,8 @@ private: void AddNode(Node* node); void RemoveNode(Node* node); - void AddEdge(const NodeOutput& output, const NodeInput& input); - void RemoveEdge(const NodeOutput& output, const NodeInput& input); + void AddEdge(Node *output, const NodeInput& input); + void RemoveEdge(Node *output, const NodeInput& input); void CopyValue(const NodeInput& input); void InsertIntoCopyMap(Node* node, Node* copy); @@ -130,7 +130,7 @@ private: Type type; Node* node; NodeInput input; - NodeOutput output; + Node *output; }; ViewerOutput* viewer_node_; @@ -214,9 +214,9 @@ private slots: void NodeRemoved(Node* node); - void EdgeAdded(const NodeOutput& output, const NodeInput& input); + void EdgeAdded(Node *output, const NodeInput& input); - void EdgeRemoved(const NodeOutput& output, const NodeInput& input); + void EdgeRemoved(Node *output, const NodeInput& input); void ValueChanged(const NodeInput& input); diff --git a/app/render/rendermanager.cpp b/app/render/rendermanager.cpp index ed32f20df..6d97debaf 100644 --- a/app/render/rendermanager.cpp +++ b/app/render/rendermanager.cpp @@ -102,7 +102,7 @@ void RenderManager::ClearOldDecoders() } } -QByteArray RenderManager::Hash(const Node *n, const QString& output, const VideoParams ¶ms, const rational &time) +QByteArray RenderManager::Hash(const Node *n, const Node::ValueHint &output, const VideoParams ¶ms, const rational &time) { QCryptographicHash hasher(QCryptographicHash::Sha1); diff --git a/app/render/rendermanager.h b/app/render/rendermanager.h index 816394dac..b6bd5ba8a 100644 --- a/app/render/rendermanager.h +++ b/app/render/rendermanager.h @@ -67,11 +67,7 @@ public: /** * @brief Generate a unique identifier for a certain node at a certain time */ - static QByteArray Hash(const Node *n, const QString &output, const VideoParams ¶ms, const rational &time); - static QByteArray Hash(const NodeOutput &output, const VideoParams ¶ms, const rational &time) - { - return Hash(output.node(), output.output(), params, time); - } + static QByteArray Hash(const Node *n, const Node::ValueHint &output, const VideoParams ¶ms, const rational &time); /** * @brief Asynchronously generate a frame at a given time diff --git a/app/render/renderprocessor.cpp b/app/render/renderprocessor.cpp index 3698483aa..17ab1ef05 100644 --- a/app/render/renderprocessor.cpp +++ b/app/render/renderprocessor.cpp @@ -47,10 +47,9 @@ TexturePtr RenderProcessor::GenerateTexture(const rational &time, const rational ViewerOutput* viewer = Node::ValueToPtr(ticket_->property("viewer")); NodeValueTable table; - NodeOutput texture_output = viewer->GetConnectedTextureOutput(); - if (texture_output.IsValid()) { - table = GenerateTable(texture_output.node(), texture_output.output(), - TimeRange(time, time + frame_length)); + Node *texture_output = viewer->GetConnectedTextureOutput(); + if (texture_output) { + table = GenerateTable(texture_output, viewer->GetValueHintForInput(ViewerOutput::kTextureInput, -1), TimeRange(time, time + frame_length)); } return table.Get(NodeValue::kTexture).value(); @@ -170,9 +169,9 @@ void RenderProcessor::Run() TimeRange time = ticket_->property("time").value(); NodeValueTable table; - NodeOutput texture_output = viewer->GetConnectedSampleOutput(); - if (texture_output.IsValid()) { - table = GenerateTable(texture_output.node(), texture_output.output(), time); + Node *texture_output = viewer->GetConnectedSampleOutput(); + if (texture_output) { + table = GenerateTable(texture_output, viewer->GetValueHintForInput(ViewerOutput::kSamplesInput, -1),time); } QVariant sample_variant = table.Get(NodeValue::kSamples); @@ -263,7 +262,7 @@ NodeValueTable RenderProcessor::GenerateBlockTable(const Track *track, const Tim int max_dest_sz = audio_params.time_to_samples(range_for_block.length()); // Destination buffer - NodeValueTable table = GenerateTable(b, Track::TransformRangeForBlock(b, range_for_block)); + NodeValueTable table = GenerateTable(b, track->GetValueHintForInput(Track::kBlockInput, track->GetArrayIndexFromBlock(b)),Track::TransformRangeForBlock(b, range_for_block)); SampleBufferPtr samples_from_this_block = table.Take(NodeValue::kSamples).value(); if (!samples_from_this_block) { diff --git a/app/task/precache/precachetask.cpp b/app/task/precache/precachetask.cpp index 4d7bd5a8f..cb1a9b608 100644 --- a/app/task/precache/precachetask.cpp +++ b/app/task/precache/precachetask.cpp @@ -47,7 +47,9 @@ PreCacheTask::PreCacheTask(Footage *footage, int index, Sequence* sequence) footage_ = static_cast(footage->copy()); footage_->setParent(project_); Node::CopyInputs(footage, footage_, false); - Node::ConnectEdge(NodeOutput(footage_, Track::Reference(Track::kVideo, index).ToString()), NodeInput(viewer(), ViewerOutput::kTextureInput)); + + Node::ConnectEdge(footage_, NodeInput(viewer(), ViewerOutput::kTextureInput)); + viewer()->SetValueHintForInput(ViewerOutput::kTextureInput, -1, {{NodeValue::kTexture}, -1, Track::Reference(Track::kVideo, index).ToString()}); SetTitle(tr("Pre-caching %1:%2").arg(footage_->filename(), QString::number(index))); } diff --git a/app/task/render/render.cpp b/app/task/render/render.cpp index ff5072d90..448ef9c12 100644 --- a/app/task/render/render.cpp +++ b/app/task/render/render.cpp @@ -91,7 +91,7 @@ bool RenderTask::Render(ColorManager* manager, } times[i] = r; - hashes[i] = RenderManager::instance()->Hash(viewer()->GetConnectedTextureOutput(), video_params_, r); + hashes[i] = RenderManager::instance()->Hash(viewer()->GetConnectedTextureOutput(), viewer()->GetValueHintForInput(ViewerOutput::kTextureInput, -1), video_params_, r); } // Filter out duplicates diff --git a/app/widget/nodeparamview/nodeparamviewitem.cpp b/app/widget/nodeparamview/nodeparamviewitem.cpp index 519ae141f..9460685f6 100644 --- a/app/widget/nodeparamview/nodeparamviewitem.cpp +++ b/app/widget/nodeparamview/nodeparamviewitem.cpp @@ -422,7 +422,7 @@ int NodeParamViewItemBody::GetElementY(NodeInput c) const return lbl_center.y(); } -void NodeParamViewItemBody::EdgeChanged(const NodeOutput& output, const NodeInput& input) +void NodeParamViewItemBody::EdgeChanged(Node *output, const NodeInput& input) { Q_UNUSED(output) diff --git a/app/widget/nodeparamview/nodeparamviewitem.h b/app/widget/nodeparamview/nodeparamviewitem.h index f312fa32d..cf6ebe465 100644 --- a/app/widget/nodeparamview/nodeparamviewitem.h +++ b/app/widget/nodeparamview/nodeparamviewitem.h @@ -148,7 +148,7 @@ private: static const int kWidgetStartColumn; private slots: - void EdgeChanged(const NodeOutput &output, const NodeInput &input); + void EdgeChanged(Node *output, const NodeInput &input); void ArrayCollapseBtnPressed(bool checked); diff --git a/app/widget/nodeparamview/nodeparamviewundo.cpp b/app/widget/nodeparamview/nodeparamviewundo.cpp index 9368dbe2d..db04ecd8d 100644 --- a/app/widget/nodeparamview/nodeparamviewundo.cpp +++ b/app/widget/nodeparamview/nodeparamviewundo.cpp @@ -201,4 +201,15 @@ void NodeParamArrayAppendCommand::undo() node_->InputArrayRemoveLast(input_, false); } +void NodeSetValueHintCommand::redo() +{ + old_hint_ = input_.node()->GetValueHintForInput(input_.input(), input_.element()); + input_.node()->SetValueHintForInput(input_.input(), input_.element(), new_hint_); +} + +void NodeSetValueHintCommand::undo() +{ + input_.node()->SetValueHintForInput(input_.input(), input_.element(), old_hint_); +} + } diff --git a/app/widget/nodeparamview/nodeparamviewundo.h b/app/widget/nodeparamview/nodeparamviewundo.h index 2e9623652..595aecaab 100644 --- a/app/widget/nodeparamview/nodeparamviewundo.h +++ b/app/widget/nodeparamview/nodeparamviewundo.h @@ -164,6 +164,38 @@ private: }; +class NodeSetValueHintCommand : public UndoCommand +{ +public: + NodeSetValueHintCommand(const NodeInput &input, const Node::ValueHint &hint) : + input_(input), + new_hint_(hint) + { + } + + NodeSetValueHintCommand(Node *node, const QString &input, int element, const Node::ValueHint &hint) : + NodeSetValueHintCommand(NodeInput(node, input, element), hint) + { + } + + virtual Project* GetRelevantProject() const override + { + return input_.node()->project(); + } + +protected: + virtual void redo() override; + + virtual void undo() override; + +private: + NodeInput input_; + + Node::ValueHint new_hint_; + Node::ValueHint old_hint_; + +}; + } #endif // NODEPARAMVIEWUNDO_H diff --git a/app/widget/nodetableview/nodetableview.cpp b/app/widget/nodetableview/nodetableview.cpp index 313a61439..9ebee87b4 100644 --- a/app/widget/nodetableview/nodetableview.cpp +++ b/app/widget/nodetableview/nodetableview.cpp @@ -43,7 +43,7 @@ void NodeTableView::SelectNodes(const QVector &nodes) { foreach (Node* n, nodes) { QTreeWidgetItem* top_item = new QTreeWidgetItem(); - top_item->setText(0, n->Name()); + top_item->setText(0, n->GetLabelAndName()); top_item->setFirstColumnSpanned(true); this->addTopLevelItem(top_item); top_level_item_map_.insert(n, top_item); @@ -70,7 +70,7 @@ void NodeTableView::SetTime(const rational &time) QTreeWidgetItem* item = i.value(); // Generate a value database for this node at this time - NodeValueDatabase db = traverser.GenerateDatabase(node, QString(), TimeRange(time, time)); + NodeValueDatabase db = traverser.GenerateDatabase(node, TimeRange(time, time)); // Delete any children of this item that aren't in this database for (int j=0; jchildCount(); j++) { @@ -81,9 +81,7 @@ void NodeTableView::SetTime(const rational &time) } // Update all inputs - NodeValueDatabase::const_iterator l; - - for (l=db.begin(); l!=db.end(); l++) { + for (auto l=db.begin(); l!=db.end(); l++) { const NodeValueTable& table = l.value(); if (!node->HasInputWithID(l.key())) { @@ -132,7 +130,7 @@ void NodeTableView::SetTime(const rational &time) // Determine source QString source_name; if (value.source()) { - source_name = value.source()->Name(); + source_name = value.source()->GetLabelAndName(); } else { source_name = tr("(unknown)"); } diff --git a/app/widget/nodeview/nodeview.cpp b/app/widget/nodeview/nodeview.cpp index 7cef6f321..c4155ab8e 100644 --- a/app/widget/nodeview/nodeview.cpp +++ b/app/widget/nodeview/nodeview.cpp @@ -20,7 +20,6 @@ #include "nodeview.h" -#include #include #include #include @@ -460,8 +459,7 @@ void NodeView::mousePressEvent(QMouseEvent *event) for (NodeViewEdge *edge_item : scene_.edges()) { if (edge_item->arrow_bounding_rect().contains(scene_pt)) { - create_edge_src_ = scene_.NodeToUIObject(edge_item->output().node()); - create_edge_src_output_ = edge_item->output().output(); + create_edge_src_ = scene_.NodeToUIObject(edge_item->output()); create_edge_ = edge_item; create_edge_already_exists_ = true; return; @@ -542,12 +540,10 @@ void NodeView::mouseMoveEvent(QMouseEvent *event) NodeValue::Type drop_edge_data_type = NodeValue::kNone; - // Run the Node and guess what type it's actually returning + // Run the Node and determine what type is being used NodeTraverser traverser; - NodeValueTable table = traverser.GenerateTable(new_drop_edge->output(), TimeRange(0, 0)); - if (table.Count() > 0) { - drop_edge_data_type = table.at(table.Count() - 1).type(); - } + NodeValue drop_edge_value = traverser.GenerateRow(new_drop_edge->output(), TimeRange(0, 0))[new_drop_edge->input().input()]; + drop_edge_data_type = drop_edge_value.type(); // Iterate through the inputs of our dragging node and see if our node has any acceptable // inputs to connect to for this type @@ -633,7 +629,7 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event) if (creating_input.IsValid()) { // Make connection if (!reconnected_to_itself) { - NodeOutput creating_output(create_edge_src_->GetNode(), create_edge_src_output_); + Node *creating_output = create_edge_src_->GetNode(); if (creating_input.IsConnected()) { Node::OutputConnection existing_edge_to_remove = {creating_input.GetConnectedOutput(), creating_input}; @@ -656,7 +652,7 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event) UpdateContextsFromEdgeRemove(command, removed_edges); } - if (added_edge.first.IsValid()) { + if (added_edge.first) { UpdateContextsFromEdgeAdd(command, added_edge, removed_edges); } @@ -994,9 +990,9 @@ void NodeView::RemoveNode(Node *node) scene_.RemoveNode(node); } -void NodeView::AddEdge(const NodeOutput &output, const NodeInput &input) +void NodeView::AddEdge(Node *output, const NodeInput &input) { - Node *output_node = output.node(); + Node *output_node = output; Node *input_node = input.node(); if (scene_.item_map().contains(output_node) && scene_.item_map().contains(input_node)) { @@ -1004,7 +1000,7 @@ void NodeView::AddEdge(const NodeOutput &output, const NodeInput &input) } } -void NodeView::RemoveEdge(const NodeOutput &output, const NodeInput &input) +void NodeView::RemoveEdge(Node *output, const NodeInput &input) { scene_.RemoveEdge(output, input); } @@ -1306,7 +1302,7 @@ void NodeView::UpdateContextsFromEdgeRemove(MultiUndoCommand *command, const Nod { // For each edge we remove, determine if we should remove the node from a context as well for (const Node::OutputConnection &edge : remove_edges) { - Node *output_node = edge.first.node(); + Node *output_node = edge.first; QVector contexts_to_remove_from; int contexts_containing = 0; @@ -1357,7 +1353,7 @@ void NodeView::RecursivelyRemoveFloatingNodeFromContext(MultiUndoCommand *comman // Remove any dependency from the context that's also floating for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) { - Node *dependency = it->second.node(); + Node *dependency = it->second; // Determine if this node happens to output to anything else in the context (which may be // another floating node that won't be removed by this operation) @@ -1376,7 +1372,7 @@ void NodeView::RecursivelyAddNodeToContext(MultiUndoCommand *command, Node *node // Add dependency for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) { - Node *dependency = it->second.node(); + Node *dependency = it->second; RecursivelyAddNodeToContext(command, dependency, context); } } @@ -1386,7 +1382,7 @@ void NodeView::UpdateContextsFromEdgeAdd(MultiUndoCommand *command, const Node:: { // Determine if node currently does NOT output to a context that it WILL after this operation QVector contexts_to_add_to; - Node *connecting_node = added_edge.first.node(); + Node *connecting_node = added_edge.first; Node *input_node = added_edge.second.node(); for (auto it=graph_->GetPositionMap().cbegin(); it!=graph_->GetPositionMap().cend(); it++) { if (it.value().contains(input_node)) { @@ -1441,7 +1437,6 @@ void NodeView::CreateNewEdge(NodeViewItem *output_item, const QPoint &mouse_pos) { create_edge_ = new NodeViewEdge(); create_edge_src_ = output_item; - create_edge_src_output_ = Node::kDefaultOutput; create_edge_already_exists_ = false; create_edge_->SetCurved(scene_.GetEdgesAreCurved()); @@ -1504,12 +1499,12 @@ void NodeView::PositionNewEdge(const QPoint &pos) if (highlight_index >= 0) { create_edge_dst_input_ = create_edge_dst_->GetInputAtIndex(highlight_index); - create_edge_->SetPoints(create_edge_src_->GetOutputPoint(Node::kDefaultOutput), + create_edge_->SetPoints(create_edge_src_->GetOutputPoint(), create_edge_dst_->GetInputPoint(create_edge_dst_input_.input(), create_edge_dst_input_.element(), create_edge_src_->pos()), true); } else { create_edge_dst_input_.Reset(); - create_edge_->SetPoints(create_edge_src_->GetOutputPoint(Node::kDefaultOutput), + create_edge_->SetPoints(create_edge_src_->GetOutputPoint(), scene_pt, false); } @@ -1606,7 +1601,7 @@ NodeViewItem *NodeView::UpdateNodeItem(Node *node, bool ignore_own_context) item = scene_.AddNode(node); for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) { - if (scene_.item_map().contains(it->second.node())) { + if (scene_.item_map().contains(it->second)) { scene_.AddEdge(it->second, it->first); } } @@ -1619,7 +1614,7 @@ NodeViewItem *NodeView::UpdateNodeItem(Node *node, bool ignore_own_context) } // Determine "view" position by averaging the Y value and "min"ing the X value of all contexts - QPointF item_pos(DBL_MAX, 0.0); + QPointF item_pos(std::numeric_limits::max(), 0.0); int average_count = 0; for (Node *context : qAsConst(filter_nodes_)) { if (context == node && ignore_own_context) { diff --git a/app/widget/nodeview/nodeview.h b/app/widget/nodeview/nodeview.h index c1aa9e095..a3b7dc4fb 100644 --- a/app/widget/nodeview/nodeview.h +++ b/app/widget/nodeview/nodeview.h @@ -211,7 +211,6 @@ private: NodeViewEdge* create_edge_; NodeViewItem* create_edge_src_; - QString create_edge_src_output_; NodeViewItem* create_edge_dst_; NodeInput create_edge_dst_input_; bool create_edge_dst_temp_expanded_; @@ -281,8 +280,8 @@ private slots: //void AddNode(Node *node); void RemoveNode(Node *node); - void AddEdge(const NodeOutput& output, const NodeInput& input); - void RemoveEdge(const NodeOutput& output, const NodeInput& input); + void AddEdge(Node *output, const NodeInput& input); + void RemoveEdge(Node *output, const NodeInput& input); void AddNodePosition(Node *node, Node *relative); void RemoveNodePosition(Node *node, Node *relative); diff --git a/app/widget/nodeview/nodeviewedge.cpp b/app/widget/nodeview/nodeviewedge.cpp index d6835ed57..42dd19e06 100644 --- a/app/widget/nodeview/nodeviewedge.cpp +++ b/app/widget/nodeview/nodeviewedge.cpp @@ -35,7 +35,7 @@ namespace olive { #define super QGraphicsPathItem -NodeViewEdge::NodeViewEdge(const NodeOutput &output, const NodeInput &input, +NodeViewEdge::NodeViewEdge(Node *output, const NodeInput &input, NodeViewItem* from_item, NodeViewItem* to_item, QGraphicsItem* parent) : super(parent), @@ -59,7 +59,7 @@ NodeViewEdge::NodeViewEdge(QGraphicsItem *parent) : void NodeViewEdge::Adjust() { // Draw a line between the two - SetPoints(from_item()->GetOutputPoint(output_.output()), + SetPoints(from_item()->GetOutputPoint(), to_item()->GetInputPoint(input_.input(), input_.element(), from_item()->pos()), to_item()->IsExpanded()); } diff --git a/app/widget/nodeview/nodeviewedge.h b/app/widget/nodeview/nodeviewedge.h index 0f90108dc..6240aeb64 100644 --- a/app/widget/nodeview/nodeviewedge.h +++ b/app/widget/nodeview/nodeviewedge.h @@ -39,13 +39,13 @@ class NodeViewItem; class NodeViewEdge : public QGraphicsPathItem { public: - NodeViewEdge(const NodeOutput& output, const NodeInput& input, + NodeViewEdge(Node *output, const NodeInput& input, NodeViewItem* from_item, NodeViewItem* to_item, QGraphicsItem* parent = nullptr); NodeViewEdge(QGraphicsItem* parent = nullptr); - const NodeOutput& output() const + Node *output() const { return output_; } @@ -124,7 +124,7 @@ private: void UpdateCurve(); - NodeOutput output_; + Node *output_; NodeInput input_; diff --git a/app/widget/nodeview/nodeviewitem.cpp b/app/widget/nodeview/nodeviewitem.cpp index c3d75cb66..73e2d8019 100644 --- a/app/widget/nodeview/nodeviewitem.cpp +++ b/app/widget/nodeview/nodeviewitem.cpp @@ -301,14 +301,6 @@ void NodeViewItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti QString node_label = node_->GetLabel(); QString node_shortname = node_->ShortName(); - if (node_label.isEmpty()) { - // If this is a track and has no user-supplied label, generate an automatic one - Track* track_cast_test = dynamic_cast(node_); - if (track_cast_test) { - node_label = Track::GetDefaultTrackName(track_cast_test->type(), track_cast_test->Index()); - } - } - int icon_size = painter->fontMetrics().height()/2; if (node_label.isEmpty()) { @@ -511,7 +503,7 @@ QPointF NodeViewItem::GetInputPoint(const QString &input, int element, const QPo return pos() + GetInputPointInternal(node_inputs_.indexOf(input), source_pos); } -QPointF NodeViewItem::GetOutputPoint(const QString& output) const +QPointF NodeViewItem::GetOutputPoint() const { switch (flow_dir_) { case NodeViewCommon::kLeftToRight: diff --git a/app/widget/nodeview/nodeviewitem.h b/app/widget/nodeview/nodeviewitem.h index a7a6854f0..3c611d481 100644 --- a/app/widget/nodeview/nodeviewitem.h +++ b/app/widget/nodeview/nodeviewitem.h @@ -80,7 +80,7 @@ public: */ QPointF GetInputPoint(const QString& input, int element, const QPointF &source_pos) const; - QPointF GetOutputPoint(const QString &output) const; + QPointF GetOutputPoint() const; /** * @brief Sets the direction nodes are flowing diff --git a/app/widget/nodeview/nodeviewscene.cpp b/app/widget/nodeview/nodeviewscene.cpp index e40db9ebe..878fd52a4 100644 --- a/app/widget/nodeview/nodeviewscene.cpp +++ b/app/widget/nodeview/nodeviewscene.cpp @@ -98,7 +98,7 @@ NodeViewItem *NodeViewScene::NodeToUIObject(Node *n) return item_map_.value(n); } -NodeViewEdge *NodeViewScene::EdgeToUIObject(const NodeOutput& output, const NodeInput& input) +NodeViewEdge *NodeViewScene::EdgeToUIObject(Node *output, const NodeInput& input) { foreach (NodeViewEdge* edge, edges_) { if (edge->output() == output && edge->input() == input) { @@ -172,18 +172,18 @@ void NodeViewScene::RemoveNode(Node *node) delete item_map_.take(node); } -NodeViewEdge* NodeViewScene::AddEdge(const NodeOutput &output, const NodeInput &input) +NodeViewEdge* NodeViewScene::AddEdge(Node *output, const NodeInput &input) { NodeViewEdge *edge = EdgeToUIObject(output, input); if (!edge) { - edge = AddEdgeInternal(output, input, NodeToUIObject(output.node()), NodeToUIObject(input.node())); + edge = AddEdgeInternal(output, input, NodeToUIObject(output), NodeToUIObject(input.node())); } return edge; } -void NodeViewScene::RemoveEdge(const NodeOutput &output, const NodeInput &input) +void NodeViewScene::RemoveEdge(Node *output, const NodeInput &input) { NodeViewEdge* edge = EdgeToUIObject(output, input); if (edge) { @@ -209,7 +209,7 @@ int NodeViewScene::DetermineWeight(Node *n) return qMax(1, weight); } -NodeViewEdge* NodeViewScene::AddEdgeInternal(const NodeOutput& output, const NodeInput& input, NodeViewItem *from, NodeViewItem *to) +NodeViewEdge* NodeViewScene::AddEdgeInternal(Node *output, const NodeInput& input, NodeViewItem *from, NodeViewItem *to) { NodeViewEdge* edge_ui = new NodeViewEdge(output, input, from, to); diff --git a/app/widget/nodeview/nodeviewscene.h b/app/widget/nodeview/nodeviewscene.h index e388af140..29cf5bbb7 100644 --- a/app/widget/nodeview/nodeviewscene.h +++ b/app/widget/nodeview/nodeviewscene.h @@ -53,7 +53,7 @@ public: * in this view/scene), this function returns nullptr. */ NodeViewItem* NodeToUIObject(Node* n); - NodeViewEdge *EdgeToUIObject(const NodeOutput &output, const NodeInput &input); + NodeViewEdge *EdgeToUIObject(Node *output, const NodeInput &input); QVector GetSelectedNodes() const; QVector GetSelectedItems() const; @@ -96,8 +96,8 @@ public slots: */ void RemoveNode(Node* node); - NodeViewEdge *AddEdge(const NodeOutput& output, const NodeInput& input); - void RemoveEdge(const NodeOutput& output, const NodeInput& input); + NodeViewEdge *AddEdge(Node *output, const NodeInput& input); + void RemoveEdge(Node *output, const NodeInput& input); /** * @brief Set whether edges in this scene should be curved or not @@ -107,7 +107,7 @@ public slots: private: static int DetermineWeight(Node* n); - NodeViewEdge* AddEdgeInternal(const NodeOutput &output, const NodeInput &input, NodeViewItem* from, NodeViewItem* to); + NodeViewEdge* AddEdgeInternal(Node *output, const NodeInput &input, NodeViewItem* from, NodeViewItem* to); void ConnectNode(Node *n); diff --git a/app/widget/nodeview/nodeviewundo.cpp b/app/widget/nodeview/nodeviewundo.cpp index 3b43a7b9a..5d7af0263 100644 --- a/app/widget/nodeview/nodeviewundo.cpp +++ b/app/widget/nodeview/nodeviewundo.cpp @@ -24,7 +24,7 @@ namespace olive { -NodeEdgeAddCommand::NodeEdgeAddCommand(const NodeOutput &output, const NodeInput &input) : +NodeEdgeAddCommand::NodeEdgeAddCommand(Node *output, const NodeInput &input) : output_(output), input_(input), remove_command_(nullptr) @@ -60,10 +60,10 @@ void NodeEdgeAddCommand::undo() Project *NodeEdgeAddCommand::GetRelevantProject() const { - return output_.node()->project(); + return output_->project(); } -NodeEdgeRemoveCommand::NodeEdgeRemoveCommand(const NodeOutput &output, const NodeInput &input) : +NodeEdgeRemoveCommand::NodeEdgeRemoveCommand(Node *output, const NodeInput &input) : output_(output), input_(input) { @@ -81,7 +81,7 @@ void NodeEdgeRemoveCommand::undo() Project *NodeEdgeRemoveCommand::GetRelevantProject() const { - return output_.node()->project(); + return output_->project(); } NodeAddCommand::NodeAddCommand(NodeGraph *graph, Node *node) : diff --git a/app/widget/nodeview/nodeviewundo.h b/app/widget/nodeview/nodeviewundo.h index f678007b1..7ed3e434e 100644 --- a/app/widget/nodeview/nodeviewundo.h +++ b/app/widget/nodeview/nodeviewundo.h @@ -35,7 +35,7 @@ namespace olive { */ class NodeEdgeRemoveCommand : public UndoCommand { public: - NodeEdgeRemoveCommand(const NodeOutput& output, const NodeInput& input); + NodeEdgeRemoveCommand(Node *output, const NodeInput& input); virtual Project* GetRelevantProject() const override; @@ -44,7 +44,7 @@ protected: virtual void undo() override; private: - NodeOutput output_; + Node *output_; NodeInput input_; }; @@ -56,7 +56,7 @@ private: */ class NodeEdgeAddCommand : public UndoCommand { public: - NodeEdgeAddCommand(const NodeOutput& output, const NodeInput& input); + NodeEdgeAddCommand(Node *output, const NodeInput& input); virtual ~NodeEdgeAddCommand() override; @@ -67,7 +67,7 @@ protected: virtual void undo() override; private: - NodeOutput output_; + Node *output_; NodeInput input_; NodeEdgeRemoveCommand* remove_command_; diff --git a/app/widget/timelinewidget/tool/import.cpp b/app/widget/timelinewidget/tool/import.cpp index 163078e38..268873bc0 100644 --- a/app/widget/timelinewidget/tool/import.cpp +++ b/app/widget/timelinewidget/tool/import.cpp @@ -34,6 +34,7 @@ #include "node/generator/matrix/matrix.h" #include "node/math/math/math.h" #include "node/project/sequence/sequence.h" +#include "widget/nodeparamview/nodeparamviewundo.h" #include "widget/nodeview/nodeviewundo.h" #include "widget/timelinewidget/undo/timelineundopointer.h" #include "window/mainwindow/mainwindow.h" @@ -385,8 +386,6 @@ void ImportTool::DropGhosts(bool insert) TimelineViewGhostItem::AttachedFootage footage_stream = ghost->GetData(TimelineViewGhostItem::kAttachedFootage).value(); - NodeOutput corresponding_output(footage_stream.footage, footage_stream.output); - ClipBlock* clip = new ClipBlock(); clip->set_media_in(ghost->GetMediaIn()); clip->set_length_and_media_out(ghost->GetLength()); @@ -405,7 +404,9 @@ void ImportTool::DropGhosts(bool insert) TransformDistortNode* transform = new TransformDistortNode(); command->add_child(new NodeAddCommand(dst_graph, transform)); - command->add_child(new NodeEdgeAddCommand(corresponding_output, NodeInput(transform, TransformDistortNode::kTextureInput))); + command->add_child(new NodeSetValueHintCommand(transform, TransformDistortNode::kTextureInput, -1, {{NodeValue::kTexture}, -1, footage_stream.output})); + + command->add_child(new NodeEdgeAddCommand(footage_stream.footage, NodeInput(transform, TransformDistortNode::kTextureInput))); command->add_child(new NodeEdgeAddCommand(transform, NodeInput(clip, ClipBlock::kBufferIn))); command->add_child(new NodeSetPositionCommand(transform, clip, QPointF(-1, 0), false)); break; @@ -415,7 +416,9 @@ void ImportTool::DropGhosts(bool insert) VolumeNode* volume_node = new VolumeNode(); command->add_child(new NodeAddCommand(dst_graph, volume_node)); - command->add_child(new NodeEdgeAddCommand(corresponding_output, NodeInput(volume_node, VolumeNode::kSamplesInput))); + command->add_child(new NodeSetValueHintCommand(volume_node, VolumeNode::kSamplesInput, -1, {{NodeValue::kSamples}, -1, footage_stream.output})); + + command->add_child(new NodeEdgeAddCommand(footage_stream.footage, NodeInput(volume_node, VolumeNode::kSamplesInput))); command->add_child(new NodeEdgeAddCommand(volume_node, NodeInput(clip, ClipBlock::kBufferIn))); command->add_child(new NodeSetPositionCommand(volume_node, clip, QPointF(-1, 0), false)); break; diff --git a/app/widget/timelinewidget/trackview/trackviewitem.cpp b/app/widget/timelinewidget/trackview/trackviewitem.cpp index ee721cb38..61a9d9db6 100644 --- a/app/widget/timelinewidget/trackview/trackviewitem.cpp +++ b/app/widget/timelinewidget/trackview/trackviewitem.cpp @@ -111,11 +111,7 @@ void TrackViewItem::LineEditCancelled() void TrackViewItem::UpdateLabel() { - if (track_->GetLabel().isEmpty()) { - label_->setText(track_->GetDefaultTrackName(track_->type(), track_->Index())); - } else { - label_->setText(track_->GetLabel()); - } + label_->setText(track_->GetLabelOrName()); } } diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index e85b72d3a..dd6f68588 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -402,8 +402,8 @@ void ViewerWidget::DecodeCachedImage(RenderTicketPtr ticket, const QString &cach bool ViewerWidget::ShouldForceWaveform() const { return GetConnectedNode() - && !GetConnectedNode()->GetConnectedTextureOutput().IsValid() - && GetConnectedNode()->GetConnectedSampleOutput().IsValid(); + && !GetConnectedNode()->GetConnectedTextureOutput() + && GetConnectedNode()->GetConnectedSampleOutput(); } void ViewerWidget::SetEmptyImage() @@ -686,7 +686,7 @@ bool ViewerWidget::FrameExistsAtTime(const rational &time) bool ViewerWidget::ViewerMightBeAStill() { - return GetConnectedNode() && GetConnectedNode()->GetConnectedTextureOutput().IsValid() && GetConnectedNode()->GetVideoLength().isNull(); + return GetConnectedNode() && GetConnectedNode()->GetConnectedTextureOutput() && GetConnectedNode()->GetVideoLength().isNull(); } void ViewerWidget::SetDisplayImage(QVariant frame, bool main_only) diff --git a/app/widget/viewer/viewerdisplay.cpp b/app/widget/viewer/viewerdisplay.cpp index dce6bb886..b43a4f3b4 100644 --- a/app/widget/viewer/viewerdisplay.cpp +++ b/app/widget/viewer/viewerdisplay.cpp @@ -401,7 +401,7 @@ void ViewerDisplayWidget::OnPaint() gt.SetCacheVideoParams(gizmo_params_); TimeRange range = GenerateGizmoTime(); - gizmo_db_ = gt.GenerateRow(gizmos_, Node::kDefaultOutput, range); + gizmo_db_ = gt.GenerateRow(gizmos_, range); QPainter p(inner_widget()); p.setWorldTransform(GenerateGizmoTransform());