[Bf-blender-cvs] [c02fa53f54e] node-tree-update-refactor: progress

Jacques Lucke noreply at git.blender.org
Mon Nov 15 19:09:19 CET 2021


Commit: c02fa53f54ed7e40c0e852f0862aae8c377b747e
Author: Jacques Lucke
Date:   Wed Nov 10 17:49:32 2021 +0100
Branches: node-tree-update-refactor
https://developer.blender.org/rBc02fa53f54ed7e40c0e852f0862aae8c377b747e

progress

===================================================================

M	source/blender/blenkernel/intern/node.cc

===================================================================

diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index eb2b125e7e6..24f3671e267 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -99,6 +99,7 @@
 #define NODE_DEFAULT_MAX_WIDTH 700
 
 using blender::Array;
+using blender::Map;
 using blender::MutableSpan;
 using blender::Set;
 using blender::Span;
@@ -4527,23 +4528,117 @@ static void ntree_validate_links(bNodeTree *ntree)
   }
 }
 
+namespace blender::bke::tree_update_order {
+
+enum class Mark {
+  None,
+  Temporary,
+  Permanent,
+};
+
+static bool visit(bNodeTree *ntree,
+                  Map<bNodeTree *, Mark> &marks,
+                  Map<bNodeTree *, Set<bNodeTree *>> &dependent_trees_map,
+                  Vector<bNodeTree *> &sorted_trees)
+{
+  Mark &mark = marks.lookup(ntree);
+  if (mark == Mark::Permanent) {
+    return true;
+  }
+  if (mark == Mark::Temporary) {
+    /* Cyclic dependencies between graphs. */
+    return false;
+  }
+
+  mark = Mark::Temporary;
+
+  for (bNodeTree *dependent_tree : dependent_trees_map.lookup(ntree)) {
+    visit(dependent_tree, marks, dependent_trees_map, sorted_trees);
+  }
+
+  mark = Mark::Permanent;
+  sorted_trees.append(ntree);
+  return true;
+}
+
+static Vector<bNodeTree *> get_tree_update_order(Main *main, const Span<bNodeTree *> changed_trees)
+{
+  /* Find all dependencies between node trees. */
+  Map<bNodeTree *, Set<bNodeTree *>> dependent_trees_map;
+  FOREACH_NODETREE_BEGIN (main, ntree, owner_id) {
+    /* Ensure there is an entry for all trees which simplifies the code below. */
+    dependent_trees_map.lookup_or_add_default(ntree);
+    LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+      if (node->id == nullptr) {
+        continue;
+      }
+      if (GS(node->id->name) != ID_NT) {
+        continue;
+      }
+      bNodeTree *used_ntree = (bNodeTree *)node->id;
+      dependent_trees_map.lookup_or_add_default(used_ntree).add(ntree);
+    }
+  }
+  FOREACH_NODETREE_END;
+
+  /* Find all trees that have to be updated. */
+  Map<bNodeTree *, Mark> marks;
+  VectorSet<bNodeTree *> trees_to_check = changed_trees;
+  while (!trees_to_check.is_empty()) {
+    bNodeTree *ntree = trees_to_check.pop();
+    if (!marks.add(ntree, Mark::None)) {
+      /* Handled already. */
+      continue;
+    }
+    const Set<bNodeTree *> &dependent_trees = dependent_trees_map.lookup(ntree);
+    for (bNodeTree *dependent_tree : dependent_trees) {
+      if (marks.contains(dependent_tree)) {
+        continue;
+      }
+      trees_to_check.add(dependent_tree);
+    }
+  }
+
+  /* Sort trees that have to be updated. */
+  Vector<bNodeTree *> sorted_trees;
+  for (const auto item : marks.items()) {
+    if (item.value == Mark::None) {
+      visit(item.key, marks, dependent_trees_map, sorted_trees);
+    }
+  }
+
+  /* Above the nodes were sorted in the wrong direction to avoid inverting the dependency map. */
+  std::reverse(sorted_trees.begin(), sorted_trees.end());
+  return sorted_trees;
+}
+
+}  // namespace blender::bke::tree_update_order
+
 void ntreeUpdateAllNew(Main *main)
 {
+  Vector<bNodeTree *> new_ntrees;
+
   /* Update all new node trees on file read or append, to add/remove sockets
    * in groups nodes if the group changed, and handle any update flags that
    * might have been set in file reading or versioning. */
   FOREACH_NODETREE_BEGIN (main, ntree, owner_id) {
     if (owner_id->tag & LIB_TAG_NEW) {
-      LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
-        if (node->typeinfo->group_update_func) {
-          node->typeinfo->group_update_func(ntree, node);
-        }
-      }
-
-      ntreeUpdateTree(nullptr, ntree);
+      new_ntrees.append(ntree);
     }
   }
   FOREACH_NODETREE_END;
+
+  Vector<bNodeTree *> ntrees_to_update = blender::bke::tree_update_order::get_tree_update_order(
+      main, new_ntrees);
+  for (bNodeTree *ntree : ntrees_to_update) {
+    LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+      if (node->typeinfo->group_update_func) {
+        node->typeinfo->group_update_func(ntree, node);
+      }
+    }
+
+    ntreeUpdateTree(nullptr, ntree);
+  }
 }
 
 static FieldInferencingInterface *node_field_inferencing_interface_copy(



More information about the Bf-blender-cvs mailing list