added preference for duplicating dependencies

Fixes #1320
This commit is contained in:
itsmattkc
2020-11-16 16:32:15 +11:00
parent 1b9bf6d92c
commit 81450044e0
8 changed files with 145 additions and 52 deletions
+1
View File
@@ -89,6 +89,7 @@ void Config::SetDefaults()
SetEntryInternal(QStringLiteral("RectifiedWaveforms"), NodeParam::kBoolean, false);
SetEntryInternal(QStringLiteral("DropWithoutSequenceBehavior"), NodeParam::kInt, ImportTool::kDWSAsk);
SetEntryInternal(QStringLiteral("Loop"), NodeParam::kBoolean, false);
SetEntryInternal(QStringLiteral("SplitClipsCopyNodes"), NodeParam::kBoolean, true);
SetEntryInternal(QStringLiteral("AutoCacheInterval"), NodeParam::kInt, 250);
@@ -99,6 +99,11 @@ PreferencesBehaviorTab::PreferencesBehaviorTab()
AddItem(tr("Auto-Scale By Default"),
QStringLiteral("AutoscaleByDefault"),
node_group);
AddItem(tr("Splitting Clips Copies Dependencies"),
QStringLiteral("SplitClipsCopyNodes"),
tr("Multiple clips can share the same nodes. Disable this to automatically share node "
"dependencies among clips when copying or splitting them."),
node_group);
}
void PreferencesBehaviorTab::Accept()
+61
View File
@@ -29,6 +29,7 @@
#include "project/project.h"
#include "project/item/footage/footage.h"
#include "project/item/footage/videostream.h"
#include "widget/nodeview/nodeviewundo.h"
OLIVE_NAMESPACE_ENTER
@@ -239,6 +240,66 @@ TimeRange Node::OutputTimeAdjustment(NodeInput *, const TimeRange &input_time) c
return input_time;
}
QVector<Node *> Node::CopyDependencyGraph(const QVector<Node *> &nodes, QUndoCommand* command)
{
int nb_nodes = nodes.size();
QVector<Node*> copies(nb_nodes);
for (int i=0; i<nb_nodes; i++) {
// Create another of the same node
Node* c = nodes.at(i)->copy();;
// Copy the values, but NOT the connections, since we'll be connecting to our own clones later
Node::CopyInputs(nodes.at(i), c, false);
// Add to graph
NodeGraph* graph = static_cast<NodeGraph*>(nodes.at(i)->parent());
if (command) {
new NodeAddCommand(graph, c, command);
} else {
graph->AddNode(c);
}
// Store in array at the same index as source
copies[i] = c;
}
CopyDependencyGraph(nodes, copies, command);
return copies;
}
void Node::CopyDependencyGraph(const QVector<Node *> &src, const QVector<Node *> &dst, QUndoCommand *command)
{
int nb_nodes = src.size();
for (int i=0; i<nb_nodes; i++) {
// Find any interconnections
QVector<NodeInput*> inputs = src.at(i)->GetInputsIncludingArrays();
for (int j=0; j<nb_nodes; j++) {
if (i == j) {
continue;
}
foreach (NodeInput* input, inputs) {
if (input->get_connected_node() == src.at(j)) {
// Found a connection
NodeOutput* copy_output = dst.at(j)->GetOutputWithID(input->get_connected_output()->id());
NodeInput* copy_input = dst.at(i)->GetInputWithID(input->id());
if (command) {
new NodeEdgeAddCommand(copy_output, copy_input, command);
} else {
NodeParam::ConnectEdge(copy_output, copy_input);
}
}
}
}
}
}
void Node::SendInvalidateCache(const TimeRange &range, NodeInput *source)
{
// Loop through all parameters (there should be no children that are not NodeParams)
+6
View File
@@ -346,6 +346,12 @@ public:
*/
static void CopyInputs(Node* source, Node* destination, bool include_connections = true);
/**
* @brief Clones a set of nodes and connects the new ones the way the old ones were
*/
static QVector<Node*> CopyDependencyGraph(const QVector<Node*>& nodes, QUndoCommand *command);
static void CopyDependencyGraph(const QVector<Node*>& src, const QVector<Node*>& dst, QUndoCommand *command);
/**
* @brief Return whether this Node can be deleted or not
*/
+2 -34
View File
@@ -288,43 +288,11 @@ void NodeView::Duplicate()
QUndoCommand* command = new QUndoCommand();
QList<Node*> duplicated_nodes;
foreach (Node* n, selected) {
Node* copy = n->copy();
Node::CopyInputs(n, copy, false);
duplicated_nodes.append(copy);
new NodeAddCommand(graph_, copy, command);
}
for (int i=0;i<selected.size();i++) {
Node* src = selected.at(i);
for (int j=0;j<selected.size();j++) {
if (i == j) {
continue;
}
Node* dst = selected.at(j);
foreach (NodeEdgePtr edge, src->output()->edges()) {
if (edge->input()->parentNode() == dst) {
new NodeEdgeAddCommand(duplicated_nodes.at(i)->output(),
duplicated_nodes.at(j)->GetInputWithID(edge->input()->id()),
command);
}
}
}
}
QVector<Node*> duplicated_nodes = Node::CopyDependencyGraph(selected, command);
Core::instance()->undo_stack()->pushIfHasChildren(command);
if (!duplicated_nodes.isEmpty()) {
AttachNodesToCursor(duplicated_nodes);
}
AttachNodesToCursor(duplicated_nodes);
}
void NodeView::ItemsChanged()
+15 -5
View File
@@ -610,13 +610,23 @@ void PointerTool::FinishDrag(TimelineViewMouseEvent *event)
if (duplicate_clips) {
// Duplicate rather than move
Node* copy = block->copy();
Node* copy;
new NodeAddCommand(static_cast<NodeGraph*>(block->parent()),
copy,
command);
if (Config::Current()[QStringLiteral("SplitClipsCopyNodes")].toBool()) {
QVector<Node*> nodes_to_clone;
nodes_to_clone.append(block);
nodes_to_clone.append(block->GetDependencies());
QVector<Node*> duplicated = Node::CopyDependencyGraph(nodes_to_clone, command);
copy = duplicated.first();
} else {
copy = block->copy();
new NodeCopyInputsCommand(block, copy, true, command);
new NodeAddCommand(static_cast<NodeGraph*>(block->parent()),
copy,
command);
new NodeCopyInputsCommand(block, copy, true, command);
}
// Place the copy instead of the original block
block = static_cast<Block*>(copy);
+51 -11
View File
@@ -20,6 +20,7 @@
#include "undo.h"
#include "config/config.h"
#include "core.h"
#include "node/block/clip/clip.h"
#include "node/block/transition/transition.h"
@@ -209,10 +210,21 @@ void TrackRippleRemoveAreaCommand::redo_internal()
if (splice_) {
// Split the block here
trim_in_ = static_cast<Block*>(trim_out_->copy());
splice_split_command_ = new QUndoCommand();
static_cast<NodeGraph*>(track_->parent())->AddNode(trim_in_);
Node::CopyInputs(trim_out_, trim_in_);
if (Config::Current()[QStringLiteral("SplitClipsCopyNodes")].toBool()) {
QVector<Node*> nodes_to_clone;
nodes_to_clone.append(trim_out_);
nodes_to_clone.append(trim_out_->GetDependencies());
QVector<Node*> duplicated = Node::CopyDependencyGraph(nodes_to_clone, splice_split_command_);
trim_in_ = static_cast<Block*>(duplicated.first());
} else {
trim_in_ = static_cast<Block*>(trim_out_->copy());
new NodeAddCommand(static_cast<NodeGraph*>(track_->parent()), trim_in_, splice_split_command_);
new NodeCopyInputsCommand(trim_out_, trim_in_, true, splice_split_command_);
}
splice_split_command_->redo();
trim_out_old_length_ = trim_out_->length();
trim_out_->set_length_and_media_out(in_ - trim_out_->in());
@@ -292,7 +304,8 @@ void TrackRippleRemoveAreaCommand::undo_internal()
track_->RippleRemoveBlock(trim_in_);
trim_out_->set_length_and_media_out(trim_out_old_length_);
TakeNodeFromParentGraph(trim_in_, &memory_manager_);
splice_split_command_->undo();
delete splice_split_command_;
} else {
@@ -428,8 +441,33 @@ void BlockSplitCommand::redo_internal()
{
track_->BeginOperation();
static_cast<NodeGraph*>(block_->parent())->AddNode(new_block_);
Node::CopyInputs(block_, new_block_);
NodeGraph* graph = static_cast<NodeGraph*>(block_->parent());
add_command_ = new QUndoCommand();
new NodeAddCommand(graph, new_block_, add_command_);
new NodeCopyInputsCommand(block_, new_block_, true, add_command_);
if (Config::Current()[QStringLiteral("SplitClipsCopyNodes")].toBool()) {
QVector<Node*> src_nodes;
QVector<Node*> dst_nodes;
src_nodes.append(block_);
src_nodes.append(block_->GetDependencies());
dst_nodes.resize(src_nodes.size());
dst_nodes[0] = new_block_;
for (int i=1; i<dst_nodes.size(); i++) {
dst_nodes[i] = src_nodes[i]->copy();
new NodeAddCommand(graph, dst_nodes[i], add_command_);
Node::CopyInputs(src_nodes[i], dst_nodes[i], false);
}
Node::CopyDependencyGraph(src_nodes, dst_nodes, add_command_);
}
add_command_->redo();
rational new_part_length = block_->length() - (point_ - block_->in());
@@ -451,16 +489,18 @@ void BlockSplitCommand::undo_internal()
{
track_->BeginOperation();
block_->set_length_and_media_out(old_length_);
track_->RippleRemoveBlock(new_block_);
TakeNodeFromParentGraph(new_block_, &memory_manager_);
foreach (NodeInput* transition, transitions_to_move_) {
NodeParam::DisconnectEdge(new_block_->output(), transition);
NodeParam::ConnectEdge(block_->output(), transition);
}
block_->set_length_and_media_out(old_length_);
track_->RippleRemoveBlock(new_block_);
add_command_->undo();
new_block_->setParent(&memory_manager_);
delete add_command_;
track_->EndOperation();
}
+4 -2
View File
@@ -192,6 +192,7 @@ protected:
rational out_;
bool splice_;
QUndoCommand* splice_split_command_;
Block* trim_out_;
Block* trim_in_;
@@ -329,17 +330,18 @@ protected:
private:
TrackOutput* track_;
Block* block_;
Block* new_block_;
rational new_length_;
rational old_length_;
rational point_;
Block* new_block_;
QList<NodeInput*> transitions_to_move_;
QObject memory_manager_;
QUndoCommand* add_command_;
};
class TrackSplitAtTimeCommand : public UndoCommand {