From a94c7169f2f81d2a7a9ca96614dc8499e602ddb2 Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Fri, 19 Nov 2021 17:14:56 -0800 Subject: [PATCH] store expanded status in context --- app/core.cpp | 2 +- app/node/node.cpp | 18 +++-- app/node/node.h | 71 ++++++++++++++++--- app/node/nodecopypaste.cpp | 8 +-- app/node/project/project.cpp | 17 +++-- app/node/project/project.h | 4 +- app/widget/nodeview/nodeview.cpp | 100 +++++++++++++-------------- app/widget/nodeview/nodeviewitem.cpp | 8 ++- 8 files changed, 143 insertions(+), 85 deletions(-) diff --git a/app/core.cpp b/app/core.cpp index 82a6b98fc..1db15b4fa 100644 --- a/app/core.cpp +++ b/app/core.cpp @@ -437,7 +437,7 @@ void Core::CreateNewSequence() command->add_child(new NodeAddCommand(active_project, new_sequence)); command->add_child(new FolderAddChild(GetSelectedFolderInActiveProject(), new_sequence)); - command->add_child(new NodeSetPositionCommand(new_sequence, new_sequence, QPointF(0, 0))); + command->add_child(new NodeSetPositionCommand(new_sequence, new_sequence, Node::Position())); // Create and connect default nodes to new sequence new_sequence->add_default_nodes(command); diff --git a/app/node/node.cpp b/app/node/node.cpp index b1b45ccf6..ddabc5a61 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -243,12 +243,16 @@ QIcon Node::icon() const return icon::New; } -QPointF Node::GetNodePositionInContext(Node *node) +bool Node::SetNodePositionInContext(Node *node, const QPointF &pos) { - return context_positions_.value(node); + Position p = context_positions_.value(node); + + p.position = pos; + + return SetNodePositionInContext(node, p); } -bool Node::SetNodePositionInContext(Node *node, const QPointF &pos) +bool Node::SetNodePositionInContext(Node *node, const Position &pos) { bool added = !ContextContainsNode(node); context_positions_.insert(node, pos); @@ -257,7 +261,7 @@ bool Node::SetNodePositionInContext(Node *node, const QPointF &pos) emit NodeAddedToContext(node); } - emit NodePositionInContextChanged(node, pos); + emit NodePositionInContextChanged(node, pos.position); return added; } @@ -2350,13 +2354,13 @@ Project *Node::ArrayResizeCommand::GetRelevantProject() const void NodeSetPositionCommand::redo() { if (!(added_ = !context_->ContextContainsNode(node_))) { - old_pos_ = context_->GetNodePositionInContext(node_); + old_pos_ = context_->GetNodePositionDataInContext(node_); } if (added_) { context_->SetNodePositionInContext(node_, pos_); } else { - move(context_, node_, pos_ - old_pos_, move_deps_); + move(context_, node_, pos_.position - old_pos_.position, move_deps_); } } @@ -2365,7 +2369,7 @@ void NodeSetPositionCommand::undo() if (added_) { context_->RemoveNodeFromContext(node_); } else { - move(context_, node_, old_pos_ - pos_, move_deps_); + move(context_, node_, old_pos_.position - pos_.position, move_deps_); } } diff --git a/app/node/node.h b/app/node/node.h index fceb08d1c..ca3f7f43c 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -208,21 +208,77 @@ public: return HasInputWithID(id); } - using PositionMap = QHash; + struct Position + { + Position(const QPointF &p = QPointF(0, 0), bool e = false) + { + position = p; + expanded = e; + } + + QPointF position; + bool expanded; + + inline Position &operator+=(const Position &p) + { + position += p.position; + return *this; + } + + inline Position &operator-=(const Position &p) + { + position -= p.position; + return *this; + } + + friend inline const Position operator+(Position a, const Position &b) + { + a += b; + return a; + } + + friend inline const Position operator-(Position a, const Position &b) + { + a -= b; + return a; + } + }; + + using PositionMap = QHash; const PositionMap &GetContextPositions() const { return context_positions_; } + bool IsNodeExpandedInContext(Node *node) const + { + return context_positions_.value(node).expanded; + } + bool ContextContainsNode(Node *node) const { return context_positions_.contains(node); } - QPointF GetNodePositionInContext(Node *node); + Position GetNodePositionDataInContext(Node *node) + { + return context_positions_.value(node); + } + + QPointF GetNodePositionInContext(Node *node) + { + return GetNodePositionDataInContext(node).position; + } bool SetNodePositionInContext(Node *node, const QPointF &pos); + bool SetNodePositionInContext(Node *node, const Position &pos); + + void SetNodeExpandedInContext(Node *node, bool e) + { + context_positions_[node].expanded = e; + } + bool RemoveNodeFromContext(Node *node); /** @@ -1006,11 +1062,6 @@ protected: } signals: - /** - * @brief Signal emitted whenever the position is set through SetPosition() - */ - void PositionChanged(const QPointF& pos); - /** * @brief Signal emitted when SetLabel() is called */ @@ -1394,7 +1445,7 @@ using NodePtr = std::shared_ptr; class NodeSetPositionCommand : public UndoCommand { public: - NodeSetPositionCommand(Node* node, Node* context, const QPointF& pos, bool move_dependencies_relatively = false) + NodeSetPositionCommand(Node* node, Node* context, const Node::Position& pos, bool move_dependencies_relatively = false) { node_ = node; context_ = context; @@ -1417,8 +1468,8 @@ private: Node* node_; Node* context_; - QPointF pos_; - QPointF old_pos_; + Node::Position pos_; + Node::Position old_pos_; bool added_; bool move_deps_; diff --git a/app/node/nodecopypaste.cpp b/app/node/nodecopypaste.cpp index 0de513820..e9c0a4d0e 100644 --- a/app/node/nodecopypaste.cpp +++ b/app/node/nodecopypaste.cpp @@ -92,7 +92,7 @@ QVector NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph, QVector pasted_nodes; XMLNodeData xml_node_data; - QMap > pasted_contexts; + QMap > pasted_contexts; while (XMLReadNextStartElement(&reader)) { if (reader.name() == QStringLiteral("olive")) { @@ -131,7 +131,7 @@ QVector NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph, while (XMLReadNextStartElement(&reader)) { if (reader.name() == QStringLiteral("context")) { // Get context ptr - QMap map; + QMap map; quintptr context_ptr = 0; XMLAttributeLoop((&reader), attr) { if (attr.name() == QStringLiteral("ptr")) { @@ -144,7 +144,7 @@ QVector NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph, while (XMLReadNextStartElement(&reader)) { if (reader.name() == QStringLiteral("node")) { quintptr node_ptr; - QPointF node_pos; + Node::Position node_pos; if (Project::LoadPosition(&reader, &node_ptr, &node_pos)) { map.insert(node_ptr, node_pos); @@ -216,7 +216,7 @@ QVector NodeCopyPasteService::PasteNodesFromClipboard(NodeGraph *graph, for (auto it=pasted_contexts.cbegin(); it!=pasted_contexts.cend(); it++) { Node *context = xml_node_data.node_ptrs.value(it.key()); if (context) { - const QMap &map = it.value(); + auto map = it.value(); for (auto jt=map.cbegin(); jt!=map.cend(); jt++) { Node *subnode = xml_node_data.node_ptrs.value(jt.key()); if (subnode) { diff --git a/app/node/project/project.cpp b/app/node/project/project.cpp index 64d7cb107..ba118ba50 100644 --- a/app/node/project/project.cpp +++ b/app/node/project/project.cpp @@ -158,7 +158,7 @@ void Project::Load(QXmlStreamReader *reader, MainWindowLayoutInfo* layout, uint while (XMLReadNextStartElement(reader)) { if (reader->name() == QStringLiteral("node")) { quintptr node_ptr; - QPointF node_pos; + Node::Position node_pos; if (LoadPosition(reader, &node_ptr, &node_pos)) { Node *node = xml_node_data.node_ptrs.value(node_ptr); @@ -350,7 +350,7 @@ void Project::RegenerateUuid() uuid_ = QUuid::createUuid(); } -bool Project::LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr, QPointF *pos) +bool Project::LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr, Node::Position *pos) { bool got_node_ptr = false; bool got_pos_x = false; @@ -366,11 +366,13 @@ bool Project::LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr, QPointF while (XMLReadNextStartElement(reader)) { if (reader->name() == QStringLiteral("x")) { - pos->setX(reader->readElementText().toDouble()); + pos->position.setX(reader->readElementText().toDouble()); got_pos_x = true; } else if (reader->name() == QStringLiteral("y")) { - pos->setY(reader->readElementText().toDouble()); + pos->position.setY(reader->readElementText().toDouble()); got_pos_y = true; + } else if (reader->name() == QStringLiteral("expanded")) { + pos->expanded = reader->readElementText().toInt(); } else { reader->skipCurrentElement(); } @@ -379,12 +381,13 @@ bool Project::LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr, QPointF return got_node_ptr && got_pos_x && got_pos_y; } -void Project::SavePosition(QXmlStreamWriter *writer, Node *node, const QPointF &pos) +void Project::SavePosition(QXmlStreamWriter *writer, Node *node, const Node::Position &pos) { writer->writeAttribute(QStringLiteral("ptr"), QString::number(reinterpret_cast(node))); - writer->writeTextElement(QStringLiteral("x"), QString::number(pos.x())); - writer->writeTextElement(QStringLiteral("y"), QString::number(pos.y())); + writer->writeTextElement(QStringLiteral("x"), QString::number(pos.position.x())); + writer->writeTextElement(QStringLiteral("y"), QString::number(pos.position.y())); + writer->writeTextElement(QStringLiteral("expanded"), QString::number(pos.expanded)); } void Project::ColorManagerValueChanged(const NodeInput &input, const TimeRange &range) diff --git a/app/node/project/project.h b/app/node/project/project.h index 3dbceb2bf..ef2e3e192 100644 --- a/app/node/project/project.h +++ b/app/node/project/project.h @@ -82,8 +82,8 @@ public: void RegenerateUuid(); - static bool LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr, QPointF *pos); - static void SavePosition(QXmlStreamWriter *writer, Node *node, const QPointF &pos); + static bool LoadPosition(QXmlStreamReader *reader, quintptr *node_ptr, Node::Position *pos); + static void SavePosition(QXmlStreamWriter *writer, Node *node, const Node::Position &pos); signals: void NameChanged(); diff --git a/app/widget/nodeview/nodeview.cpp b/app/widget/nodeview/nodeview.cpp index 5cb1d767c..e805d7eda 100644 --- a/app/widget/nodeview/nodeview.cpp +++ b/app/widget/nodeview/nodeview.cpp @@ -523,7 +523,6 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event) } Core::instance()->undo_stack()->pushIfHasChildren(command); - return; } MultiUndoCommand* command = new MultiUndoCommand(); @@ -539,64 +538,63 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event) } } - if (!context) { - QToolTip::showText(QCursor::pos(), tr("Nodes must be placed inside a context.")); - return; - } - - if (paste_command_) { - // We've already "done" this command, but MultiUndoCommand prevents "redoing" twice, so we - // add it to this command (which may have extra commands added too) so that it all gets undone - // in the same action - command->add_child(paste_command_); - paste_command_ = nullptr; - } - - { - MultiUndoCommand *add_command = new MultiUndoCommand(); - - foreach (const AttachedItem &ai, attached_items_) { - // Add node to the same graph that the context is in - add_command->add_child(new NodeAddCommand(context->parent(), ai.item->GetNode())); - - // Add node to the context - add_command->add_child(new NodeSetPositionCommand(ai.item->GetNode(), context, scene_.context_map().value(context)->MapScenePosToNodePosInContext(ai.item->pos()))); + if (context) { + if (paste_command_) { + // We've already "done" this command, but MultiUndoCommand prevents "redoing" twice, so we + // add it to this command (which may have extra commands added too) so that it all gets undone + // in the same action + command->add_child(paste_command_); + paste_command_ = nullptr; } - if (add_command->child_count()) { - add_command->redo_now(); - command->add_child(add_command); - } else { - delete add_command; - } - } + { + MultiUndoCommand *add_command = new MultiUndoCommand(); - { - // Dropped attached item onto an edge, connect it between them - MultiUndoCommand *drop_edge_command = new MultiUndoCommand(); - if (attached_items_.size() == 1) { - Node* dropping_node = attached_items_.first().item->GetNode(); + foreach (const AttachedItem &ai, attached_items_) { + // Add node to the same graph that the context is in + add_command->add_child(new NodeAddCommand(context->parent(), ai.item->GetNode())); - if (drop_edge_) { - // Remove old edge - drop_edge_command->add_child(new NodeEdgeRemoveCommand(drop_edge_->output(), drop_edge_->input())); - - // Place new edges - drop_edge_command->add_child(new NodeEdgeAddCommand(drop_edge_->output(), drop_input_)); - drop_edge_command->add_child(new NodeEdgeAddCommand(dropping_node, drop_edge_->input())); + // Add node to the context + add_command->add_child(new NodeSetPositionCommand(ai.item->GetNode(), context, scene_.context_map().value(context)->MapScenePosToNodePosInContext(ai.item->pos()))); } - drop_edge_ = nullptr; + if (add_command->child_count()) { + add_command->redo_now(); + command->add_child(add_command); + } else { + delete add_command; + } } - if (drop_edge_command->child_count()) { - drop_edge_command->redo_now(); - command->add_child(drop_edge_command); - } else { - delete drop_edge_command; - } - } - DetachItemsFromCursor(); + { + // Dropped attached item onto an edge, connect it between them + MultiUndoCommand *drop_edge_command = new MultiUndoCommand(); + if (attached_items_.size() == 1) { + Node* dropping_node = attached_items_.first().item->GetNode(); + + if (drop_edge_) { + // Remove old edge + drop_edge_command->add_child(new NodeEdgeRemoveCommand(drop_edge_->output(), drop_edge_->input())); + + // Place new edges + drop_edge_command->add_child(new NodeEdgeAddCommand(drop_edge_->output(), drop_input_)); + drop_edge_command->add_child(new NodeEdgeAddCommand(dropping_node, drop_edge_->input())); + } + + drop_edge_ = nullptr; + } + if (drop_edge_command->child_count()) { + drop_edge_command->redo_now(); + command->add_child(drop_edge_command); + } else { + delete drop_edge_command; + } + } + + DetachItemsFromCursor(); + } else { + QToolTip::showText(QCursor::pos(), tr("Nodes must be placed inside a context.")); + } } for (auto it=dragging_items_.cbegin(); it!=dragging_items_.cend(); it++) { diff --git a/app/widget/nodeview/nodeviewitem.cpp b/app/widget/nodeview/nodeviewitem.cpp index 1c645601e..3ea29ff5a 100644 --- a/app/widget/nodeview/nodeviewitem.cpp +++ b/app/widget/nodeview/nodeviewitem.cpp @@ -85,9 +85,8 @@ NodeViewItem::NodeViewItem(Node* n, Node *context, QGraphicsItem *parent) : if (context_) { SetNodePosition(context_->GetNodePositionInContext(node_)); + SetExpanded(context_->IsNodeExpandedInContext(node_)); } - - SetExpanded(node_->property("expanded").toBool()); } QPointF NodeViewItem::GetNodePosition() const @@ -236,7 +235,10 @@ void NodeViewItem::SetExpanded(bool e, bool hide_titlebar) expanded_ = e; hide_titlebar_ = hide_titlebar; - node_->setProperty("expanded", e); + + if (context_) { + context_->SetNodeExpandedInContext(node_, e); + } if (expanded_ && !node_inputs_.isEmpty()) { // Create new rect