node: implemented convenience functions for transforming time

Implements a function that calculates the time transformation(s) only between
one node and another.
This commit is contained in:
itsmattkc
2020-03-26 00:26:13 +11:00
parent 9f3b9fdc70
commit c5d3c4ff36
4 changed files with 123 additions and 2 deletions
+9
View File
@@ -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
+2
View File
@@ -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;
+92 -2
View File
@@ -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<NodeInput *>& list)
{
foreach (NodeInput* input, array->sub_params()) {
list.append(input);
if (input->IsArray()) {
GetInputsIncludingArraysInternal(static_cast<NodeInputArray*>(input), list);
}
}
}
QList<NodeInput *> Node::GetInputsIncludingArrays() const
{
QList<NodeInput *> inputs;
foreach (NodeParam* param, params_) {
if (param->type() == NodeParam::kInput) {
NodeInput* input = static_cast<NodeInput*>(param);
inputs.append(input);
if (input->IsArray()) {
GetInputsIncludingArraysInternal(static_cast<NodeInputArray*>(input), inputs);
}
}
}
return inputs;
}
QList<NodeOutput *> 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<TimeRange> Node::TransformTimeTo(const TimeRange &time, Node *target, NodeParam::Type direction)
{
QList<TimeRange> paths_found;
if (direction == NodeParam::kInput) {
// Get list of all inputs
QList<NodeInput *> 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<NodeOutput*> 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<quintptr>(ptr);
+20
View File
@@ -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<TimeRange> TransformTimeTo(const TimeRange& time, Node* target, NodeParam::Type direction);
template<class T>
/**
* @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<NodeInput*> GetInputsIncludingArrays() const;
QList<NodeOutput*> GetOutputs() const;
protected:
void AddInput(NodeInput* input);