/*** Olive - Non-Linear Video Editor Copyright (C) 2019 Olive Team This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ***/ #include "node.h" #include #include "common/qobjectlistcast.h" Node::Node() : last_time_(-1) { } QString Node::Category() { // Return an empty category for any nodes that don't use one return QString(); } QString Node::Description() { // Return an empty string by default return QString(); } void Node::Release() { } void Node::AddParameter(NodeParam *param) { // Ensure no other param with this ID has been added to this Node (since that defeats the purpose) Q_ASSERT(!HasParamWithID(param->id())); param->setParent(this); connect(param, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SIGNAL(EdgeAdded(NodeEdgePtr))); connect(param, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SIGNAL(EdgeRemoved(NodeEdgePtr))); } void Node::RemoveParameter(NodeParam *param) { delete param; } void Node::InvalidateCache(const rational &start_range, const rational &end_range) { QList params = parameters(); // Loop through all parameters (there should be no children that are not NodeParams) foreach (NodeParam* param, params) { // If the Node is an output, relay the signal to any Nodes that are connected to it if (param->type() == NodeParam::kOutput) { foreach (NodeEdgePtr edge, param->edges()) { NodeInput* connected_input = edge->input(); Node* connected_node = connected_input->parent(); // Only send this signal if the Node isn't ignoring invalidate cache signals from this input if (!connected_node->ignore_invalid_cache_inputs_.contains(connected_input)) { connected_node->InvalidateCache(start_range, end_range); } } } } } void Node::IgnoreCacheInvalidationFrom(NodeInput *input) { ignore_invalid_cache_inputs_.append(input); } void Node::Run(const rational &time) { lock_.lock(); if (last_time_ != time) { // The results will be the same, so return here Process(time); last_time_ = time; } lock_.unlock(); } NodeParam *Node::ParamAt(int index) { return static_cast(children().at(index)); } QList Node::parameters() { return static_qobjectlist_cast(children()); } int Node::ParameterCount() { return children().size(); } int Node::IndexOfParameter(NodeParam *param) { return children().indexOf(param); } /** * @brief Recursively collects dependencies of Node `n` and appends them to QList `list` * * @param traverse * * TRUE to recursively traverse each node for a complete dependency graph. FALSE to return only the immediate * dependencies. */ void GetDependenciesInternal(Node* n, QList& list, bool traverse) { QList params = n->parameters(); foreach (NodeParam* p, params) { if (p->type() == NodeParam::kInput) { QVector param_edges = p->edges(); foreach (NodeEdgePtr edge, param_edges) { Node* connected_node = edge->output()->parent(); list.append(connected_node); if (traverse) { GetDependenciesInternal(connected_node, list, traverse); } } } } } QList Node::GetDependencies() { QList node_list; GetDependenciesInternal(this, node_list, true); return node_list; } QList Node::GetExclusiveDependencies() { QList deps = GetDependencies(); // Filter out any dependencies that are used elsewhere for (int i=0;i params = deps.at(i)->parameters(); // See if any of this Node's outputs are used outside of this dep list for (int j=0;jtype() == NodeParam::kOutput) { QVector edges = p->edges(); for (int k=0;kinput()->parent())) { deps.removeAt(i); i--; // -1 since we just removed a Node in this list j = params.size(); // No need to keep looking at this Node's params break; // Or this param's edges } } } } } return deps; } QList Node::GetImmediateDependencies() { QList node_list; GetDependenciesInternal(this, node_list, false); return node_list; } QList Node::GetImmediateDependenciesAt(const rational &time) { Q_UNUSED(time) return GetImmediateDependencies(); } bool Node::OutputsTo(Node *n) { QList params = parameters(); foreach (NodeParam* param, params) { if (param->type() == NodeParam::kOutput) { QVector edges = param->edges(); foreach (NodeEdgePtr edge, edges) { if (edge->input()->parent() == n) { return true; } } } } return false; } QVariant Node::PtrToValue(void *ptr) { return reinterpret_cast(ptr); } bool Node::HasParamWithID(const QString &id) { QList params = parameters(); foreach (NodeParam* p, params) { if (p->id() == id) { return true; } } return false; }