diff --git a/app/common/xmlutils.cpp b/app/common/xmlutils.cpp index 6dcb15dc2..c80096193 100644 --- a/app/common/xmlutils.cpp +++ b/app/common/xmlutils.cpp @@ -1,5 +1,6 @@ #include "xmlutils.h" +#include "node/block/block.h" #include "node/factory.h" #include "widget/nodeview/nodeviewundo.h" @@ -31,10 +32,10 @@ Node* XMLLoadNode(QXmlStreamReader* reader) { return node; } -void XMLConnectNodes(const QHash& output_ptrs, const QList& desired_connections, QUndoCommand *command) +void XMLConnectNodes(const XMLNodeData &xml_node_data, QUndoCommand *command) { - foreach (const XMLNodeData::SerializedConnection& con, desired_connections) { - NodeOutput* out = output_ptrs.value(con.output); + foreach (const XMLNodeData::SerializedConnection& con, xml_node_data.desired_connections) { + NodeOutput* out = xml_node_data.output_ptrs.value(con.output); if (out) { if (command) { @@ -61,3 +62,15 @@ bool XMLReadNextStartElement(QXmlStreamReader *reader) return false; } + +void XMLLinkBlocks(const XMLNodeData &xml_node_data) +{ + foreach (const XMLNodeData::BlockLink& l1, xml_node_data.block_links) { + foreach (const XMLNodeData::BlockLink& l2, xml_node_data.block_links) { + if (l1.link == l2.block->property("xml_ptr")) { + Block::Link(l1.block, l2.block); + break; + } + } + } +} diff --git a/app/common/xmlutils.h b/app/common/xmlutils.h index 22b1c76b1..d549c7eb3 100644 --- a/app/common/xmlutils.h +++ b/app/common/xmlutils.h @@ -4,13 +4,14 @@ #include #include +#include "project/item/footage/stream.h" + +class Block; class Node; class NodeParam; class NodeInput; class NodeOutput; -#include "project/item/footage/stream.h" - #define XMLAttributeLoop(reader, item) \ QXmlStreamAttributes __attributes = reader->attributes(); \ foreach (const QXmlStreamAttribute& item, __attributes) @@ -28,14 +29,23 @@ struct XMLNodeData { quintptr footage; }; + struct BlockLink { + Block* block; + quintptr link; + }; + QHash output_ptrs; QList desired_connections; QHash footage_ptrs; QList footage_connections; + QList block_links; + }; -void XMLConnectNodes(const QHash &output_ptrs, const QList &desired_connections, QUndoCommand* command = nullptr); +void XMLConnectNodes(const XMLNodeData& xml_node_data, QUndoCommand* command = nullptr); bool XMLReadNextStartElement(QXmlStreamReader* reader); +void XMLLinkBlocks(const XMLNodeData& xml_node_data); + #endif // XMLREADLOOP_H diff --git a/app/node/block/block.cpp b/app/node/block/block.cpp index 37c0f219d..08cda87ba 100644 --- a/app/node/block/block.cpp +++ b/app/node/block/block.cpp @@ -198,6 +198,22 @@ rational Block::MediaToSequenceTime(const rational &media_time) const return (media_time - media_in()) / speed() + in(); } +void Block::LoadInternal(QXmlStreamReader *reader, XMLNodeData &xml_node_data) +{ + if (reader->name() == QStringLiteral("link")) { + xml_node_data.block_links.append({this, reader->readElementText().toULongLong()}); + } else { + Node::LoadInternal(reader, xml_node_data); + } +} + +void Block::SaveInternal(QXmlStreamWriter *writer) const +{ + foreach (Block* link, linked_clips_) { + writer->writeTextElement(QStringLiteral("link"), QString::number(reinterpret_cast(link))); + } +} + void Block::LengthInputChanged() { emit LengthChanged(length()); diff --git a/app/node/block/block.h b/app/node/block/block.h index 0bde06cf9..1345c47a2 100644 --- a/app/node/block/block.h +++ b/app/node/block/block.h @@ -113,6 +113,10 @@ protected: rational MediaToSequenceTime(const rational& media_time) const; + virtual void LoadInternal(QXmlStreamReader* reader, XMLNodeData& xml_node_data) override; + + virtual void SaveInternal(QXmlStreamWriter* writer) const override; + Block* previous_; Block* next_; diff --git a/app/node/node.cpp b/app/node/node.cpp index a8313980d..9a9b9857a 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -82,7 +82,7 @@ void Node::Load(QXmlStreamReader *reader, XMLNodeData& xml_node_data, const QAto param->Load(reader, xml_node_data, cancelled); } else { - reader->skipCurrentElement(); + LoadInternal(reader, xml_node_data); } } } @@ -99,6 +99,8 @@ void Node::Save(QXmlStreamWriter *writer, const QString &custom_name) const param->Save(writer); } + SaveInternal(writer); + writer->writeEndElement(); // node } @@ -219,6 +221,15 @@ void Node::DependentEdgeChanged(NodeInput *from) } } +void Node::LoadInternal(QXmlStreamReader *reader, XMLNodeData &) +{ + reader->skipCurrentElement(); +} + +void Node::SaveInternal(QXmlStreamWriter *) const +{ +} + QString Node::ReadFileAsString(const QString &filename) { QFile f(filename); diff --git a/app/node/node.h b/app/node/node.h index fa20b9450..475d55f1f 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -345,6 +345,10 @@ protected: virtual void DependentEdgeChanged(NodeInput* from); + virtual void LoadInternal(QXmlStreamReader* reader, XMLNodeData& xml_node_data); + + virtual void SaveInternal(QXmlStreamWriter* writer) const; + public slots: signals: diff --git a/app/project/item/sequence/sequence.cpp b/app/project/item/sequence/sequence.cpp index 05b9f7a1b..60989af7b 100644 --- a/app/project/item/sequence/sequence.cpp +++ b/app/project/item/sequence/sequence.cpp @@ -117,7 +117,10 @@ void Sequence::Load(QXmlStreamReader *reader, XMLNodeData& xml_node_data, const } // Make connections - XMLConnectNodes(xml_node_data.output_ptrs, xml_node_data.desired_connections); + XMLConnectNodes(xml_node_data); + + // Link blocks + XMLLinkBlocks(xml_node_data); // Ensure this and all children are in the main thread // (FIXME: Weird place for this? This should probably be in ProjectLoadManager somehow) diff --git a/app/widget/nodecopypaste/nodecopypaste.cpp b/app/widget/nodecopypaste/nodecopypaste.cpp index 64aa30f70..dcb1aa803 100644 --- a/app/widget/nodecopypaste/nodecopypaste.cpp +++ b/app/widget/nodecopypaste/nodecopypaste.cpp @@ -89,9 +89,12 @@ QList NodeCopyPasteWidget::PasteNodesFromClipboard(Sequence *graph, QUnd // Make connections if (!xml_node_data.desired_connections.isEmpty()) { - XMLConnectNodes(xml_node_data.output_ptrs, xml_node_data.desired_connections, command); + XMLConnectNodes(xml_node_data, command); } + // Link blocks + XMLLinkBlocks(xml_node_data); + // Connect footage to existing footage if it exists if (!xml_node_data.footage_connections.isEmpty()) { // Get list of all footage from project