From c5d3c4ff36a65c365bb0f70d3b72f85c6bb940a9 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 26 Mar 2020 00:26:13 +1100 Subject: [PATCH] node: implemented convenience functions for transforming time Implements a function that calculates the time transformation(s) only between one node and another. --- app/node/block/clip/clip.cpp | 9 ++++ app/node/block/clip/clip.h | 2 + app/node/node.cpp | 94 +++++++++++++++++++++++++++++++++++- app/node/node.h | 20 ++++++++ 4 files changed, 123 insertions(+), 2 deletions(-) diff --git a/app/node/block/clip/clip.cpp b/app/node/block/clip/clip.cpp index a6d637889..281072393 100644 --- a/app/node/block/clip/clip.cpp +++ b/app/node/block/clip/clip.cpp @@ -89,6 +89,15 @@ TimeRange ClipBlock::InputTimeAdjustment(NodeInput *input, const TimeRange &inpu return Block::InputTimeAdjustment(input, input_time); } +TimeRange ClipBlock::OutputTimeAdjustment(NodeInput *input, const TimeRange &input_time) const +{ + if (input == texture_input_) { + return TimeRange(MediaToSequenceTime(input_time.in()), MediaToSequenceTime(input_time.out())); + } + + return Block::InputTimeAdjustment(input, input_time); +} + NodeValueTable ClipBlock::Value(const NodeValueDatabase &value) const { // We discard most values here except for the buffer we received diff --git a/app/node/block/clip/clip.h b/app/node/block/clip/clip.h index f341dda58..1c523f44d 100644 --- a/app/node/block/clip/clip.h +++ b/app/node/block/clip/clip.h @@ -46,6 +46,8 @@ public: virtual TimeRange InputTimeAdjustment(NodeInput* input, const TimeRange& input_time) const override; + virtual TimeRange OutputTimeAdjustment(NodeInput* input, const TimeRange& input_time) const override; + virtual NodeValueTable Value(const NodeValueDatabase& value) const override; virtual void Retranslate() override; diff --git a/app/node/node.cpp b/app/node/node.cpp index fb12a0093..7358aabd8 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -167,10 +167,15 @@ void Node::InvalidateVisible(NodeInput *from) } } -TimeRange Node::InputTimeAdjustment(NodeInput *input, const TimeRange &input_time) const +TimeRange Node::InputTimeAdjustment(NodeInput *, const TimeRange &input_time) const +{ + // Default behavior is no time adjustment at all + return input_time; +} + +TimeRange Node::OutputTimeAdjustment(NodeInput *, const TimeRange &input_time) const { // Default behavior is no time adjustment at all - Q_UNUSED(input) return input_time; } @@ -224,6 +229,42 @@ QString Node::ReadFileAsString(const QString &filename) return file_data; } +void GetInputsIncludingArraysInternal(NodeInputArray* array, QList& list) +{ + foreach (NodeInput* input, array->sub_params()) { + list.append(input); + + if (input->IsArray()) { + GetInputsIncludingArraysInternal(static_cast(input), list); + } + } +} + +QList Node::GetInputsIncludingArrays() const +{ + QList inputs; + + foreach (NodeParam* param, params_) { + if (param->type() == NodeParam::kInput) { + NodeInput* input = static_cast(param); + + inputs.append(input); + + if (input->IsArray()) { + GetInputsIncludingArraysInternal(static_cast(input), inputs); + } + } + } + + return inputs; +} + +QList Node::GetOutputs() const +{ + // The current design only uses one output per node. This function returns a list just in case that changes. + return {output_}; +} + void Node::CopyInputs(Node *source, Node *destination, bool include_connections) { Q_ASSERT(source->id() == destination->id()); @@ -487,6 +528,55 @@ void Node::DisconnectAll() } } +QList Node::TransformTimeTo(const TimeRange &time, Node *target, NodeParam::Type direction) +{ + QList paths_found; + + if (direction == NodeParam::kInput) { + // Get list of all inputs + QList inputs = GetInputsIncludingArrays(); + + // If this input is connected, traverse it to see if we stumble across the specified `node` + foreach (NodeInput* input, inputs) { + if (input->IsConnected()) { + TimeRange input_adjustment = InputTimeAdjustment(input, time); + + if (input->get_connected_node() == target) { + // We found the target, no need to keep traversing + if (!paths_found.contains(input_adjustment)) { + paths_found.append(input_adjustment); + } + } else { + // We did NOT find the target, traverse this + paths_found.append(TransformTimeTo(input_adjustment, target, direction)); + } + } + } + } else { + // Get list of all outputs + QList outputs = GetOutputs(); + + // If this input is connected, traverse it to see if we stumble across the specified `node` + foreach (NodeOutput* output, outputs) { + if (output->IsConnected()) { + foreach (NodeEdgePtr edge, output->edges()) { + Node* input_node = edge->input()->parentNode(); + + TimeRange output_adjustment = input_node->OutputTimeAdjustment(edge->input(), time); + + if (input_node == target) { + paths_found.append(output_adjustment); + } else { + paths_found.append(TransformTimeTo(output_adjustment, target, direction)); + } + } + } + } + } + + return paths_found; +} + QVariant Node::PtrToValue(void *ptr) { return reinterpret_cast(ptr); diff --git a/app/node/node.h b/app/node/node.h index b049a8618..2ec6e6c85 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -212,6 +212,11 @@ public: */ void DisconnectAll(); + /** + * @brief Transforms time from this node through the connections it takes to get to the specified node + */ + QList TransformTimeTo(const TimeRange& time, Node* target, NodeParam::Type direction); + template /** * @brief Find a node of a certain type that this Node outputs to @@ -245,8 +250,19 @@ public: */ virtual void InvalidateVisible(NodeInput *from); + /** + * @brief Adjusts time that should be sent to nodes connected to certain inputs. + * + * If this node modifies the `time` (i.e. a clip converting sequence time to media time), this function should be + * overridden to do so. Also make sure to override OutputTimeAdjustment() to provide the inverse function. + */ virtual TimeRange InputTimeAdjustment(NodeInput* input, const TimeRange& input_time) const; + /** + * @brief The inverse of InputTimeAdjustment() + */ + virtual TimeRange OutputTimeAdjustment(NodeInput* input, const TimeRange& input_time) const; + /** * @brief Copies inputs from from Node to another including connections * @@ -315,6 +331,10 @@ public: static QString ReadFileAsString(const QString& filename); + QList GetInputsIncludingArrays() const; + + QList GetOutputs() const; + protected: void AddInput(NodeInput* input);