From c9305b93686cecb2d2bde7bcd0f7583b1a04b04a Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 26 May 2021 14:25:05 +1000 Subject: [PATCH] nodeview: improved average position algorithm --- app/widget/nodeview/nodeview.cpp | 166 ++++++++----------------------- app/widget/nodeview/nodeview.h | 3 +- 2 files changed, 43 insertions(+), 126 deletions(-) diff --git a/app/widget/nodeview/nodeview.cpp b/app/widget/nodeview/nodeview.cpp index 9f72a4246..ac037f2b2 100644 --- a/app/widget/nodeview/nodeview.cpp +++ b/app/widget/nodeview/nodeview.cpp @@ -119,72 +119,33 @@ void NodeView::SetGraph(NodeGraph *graph, const QVector &nodes) if (refresh_required && nodes_visible) { - QMap > averaged_positions; - - QPointF origin(0, 0); - if (filter_mode_ == kFilterShowAll) { // FIXME: Implement } else { // Reserve an arbitrary number to reduce the amount of reallocations + qreal last_offset = 0; + int additional_spacing = 0; + foreach (void *n, filter_nodes_) { const NodeGraph::PositionMap &map = graph_->GetNodesForRelative(n); - qreal top = 0, bottom = 0; - + // First determine the total "height" of this graph and how much we need to offset it + qreal top = 0; + qreal bottom = 0; for (auto it=map.cbegin(); it!=map.cend(); it++) { - // Determine position - NodeViewItem *item = scene_.item_map().value(it.key()); - - if (item) { - QVector &averages = averaged_positions[item]; - if (averages.isEmpty()) { - averages.append(item->GetNodePosition()); - } - averages.append(origin + it.value()); - } else { - item = scene_.AddNode(it.key()); - } - - const QPointF &pos = it.value(); - top = qMin(top, pos.y()); - bottom = qMax(bottom, pos.y()); - - item->SetNodePosition(origin + pos); + const QPointF &node_pos_in_context = it.value(); + top = qMin(node_pos_in_context.y(), top); + bottom = qMax(node_pos_in_context.y(), bottom); } - origin.setY(origin.y() + 1 + (bottom - top)); - } + last_offset += (additional_spacing + (bottom - top)); + additional_spacing = 1; + context_offsets_.insert(n, QPointF(0, last_offset)); - for (auto it=averaged_positions.cbegin(); it!=averaged_positions.cend(); it++) { - const QVector &positions = it.value(); - double x = DBL_MAX; - double y = 0.0; - - // Min the X value and average the Y values - foreach (const QPointF &pos, positions) { - x = qMin(x, pos.x()); - y += pos.y(); + // Finally add all nodes + for (auto it=map.cbegin(); it!=map.cend(); it++) { + AddNodePosition(it.key(), n); } - - y /= positions.size(); - - it.key()->SetNodePosition(QPointF(x, y)); - } - - for (auto it=scene_.item_map().cbegin(); it!=scene_.item_map().cend(); it++) { - // Add edge objects - Node *node = it.key(); - for (auto jt=node->input_connections().cbegin(); jt!=node->input_connections().cend(); jt++) { - const NodeOutput &output = jt->second; - if (scene_.item_map().contains(output.node())) { - // Create edge since both input and output exist - scene_.AddEdge(output, jt->first); - } - } - - // Store view position - positions_.insert(it.value(), {it.key(), it.value()->GetNodePosition()}); } } } @@ -430,59 +391,6 @@ void NodeView::ZoomOut() ZoomFromKeyboard(0.8); } -/*void NodeView::AddNodesToFilter(const QVector &nodes) -{ - // Determine new nodes - QVector multiple_sources; - - foreach (Node* node, nodes) { - // Node is new and being added - scene_.AddNode(node); - - QList visible = graph_->GetNodesForRelative(node); - foreach (Node* v, visible) { - if (scene_.NodeToUIObject(v)) { - multiple_sources.append(v); - } else { - NodeViewItem* item = scene_.AddNode(v); - item->SetNodePosition(graph_->GetNodePosition(v, node)); - } - } - } - - filter_nodes_.append(nodes); -} - -void NodeView::RemoveNodesFromFilter(const QVector &nodes) -{ - // Determine old nodes - foreach (Node* node, nodes) { - // Node is old and being removed - QList visible = graph_->GetNodesForRelative(node); - foreach (Node* v, visible) { - bool found = false; - - foreach (Node* n, filter_nodes_) { - if (node != n) { - QList other_deps = graph_->GetNodesForRelative(n); - - if (other_deps.contains(v)) { - found = true; - break; - } - } - } - - if (!found) { - scene_.RemoveNode(v); - } - } - - scene_.RemoveNode(node); - filter_nodes_.removeOne(node); - } -}*/ - void NodeView::keyPressEvent(QKeyEvent *event) { super::keyPressEvent(event); @@ -997,29 +905,35 @@ void NodeView::RemoveEdge(const NodeOutput &output, const NodeInput &input) scene_.RemoveEdge(output, input); } -void NodeView::AddNodePosition(Node *node, void *relative, const QPointF &pos) +void NodeView::AddNodePosition(Node *node, void *relative) { - /*if (filter_mode_ == kFilterShowSelective) { + if (filter_mode_ == kFilterShowSelective) { if (filter_nodes_.contains(relative)) { + // Get UI item or create if it doesn't exist NodeViewItem *item = scene_.item_map().value(node); - if (!item) { item = scene_.AddNode(node); - - // Add input edges - for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) { - AddEdge(it->second, it->first); - } - - // Add output edges - for (auto it=node->output_connections().cbegin(); it!=node->output_connections().cend(); it++) { - AddEdge(it->first, it->second); - } } - item->SetNodePosition(pos); + // Determine "view" position by averaging the Y value and "min"ing the X value of all contexts + QPointF item_pos(DBL_MAX, 0.0); + int average_count = 0; + foreach (void *context, filter_nodes_) { + if (graph_->GetNodesForRelative(context).contains(node)) { + QPointF this_context_pos = graph_->GetNodePosition(node, context); + this_context_pos += context_offsets_.value(context); + item_pos.setX(qMin(item_pos.x(), this_context_pos.x())); + item_pos.setY(item_pos.y() + this_context_pos.y()); + average_count++; + } + } + item_pos.setY(item_pos.y() / average_count); + + // Set position + item->SetNodePosition(item_pos); + positions_.insert(item, {node, item_pos}); } - }*/ + } } void NodeView::RemoveNodePosition(Node *node, void *relative) @@ -1040,9 +954,11 @@ void NodeView::NodePositionChanged(NodeViewItem *item, const QPointF &pos) original_pos.original_item_pos = pos; foreach (void *context, filter_nodes_) { - QPointF p = graph_->GetNodePosition(node, context); - p += diff; - graph_->SetNodePosition(node, context, p); + if (graph_->GetNodesForRelative(context).contains(node)) { + QPointF p = graph_->GetNodePosition(node, context); + p += diff; + graph_->SetNodePosition(node, context, p); + } } } diff --git a/app/widget/nodeview/nodeview.h b/app/widget/nodeview/nodeview.h index b832095c7..5cf9f8502 100644 --- a/app/widget/nodeview/nodeview.h +++ b/app/widget/nodeview/nodeview.h @@ -165,6 +165,7 @@ private: FilterMode filter_mode_; QVector filter_nodes_; + QMap context_offsets_; double scale_; @@ -213,7 +214,7 @@ private slots: void AddEdge(const NodeOutput& output, const NodeInput& input); void RemoveEdge(const NodeOutput& output, const NodeInput& input); - void AddNodePosition(Node *node, void *relative, const QPointF &pos); + void AddNodePosition(Node *node, void *relative); void RemoveNodePosition(Node *node, void *relative); void NodePositionChanged(NodeViewItem *item, const QPointF &pos);