[Bf-blender-cvs] [cb5569f849f] node-tree-update-refactor: progress
Jacques Lucke
noreply at git.blender.org
Mon Nov 15 19:09:22 CET 2021
Commit: cb5569f849f123e587d2aef4ba4fd48354741d53
Author: Jacques Lucke
Date: Mon Nov 15 17:23:22 2021 +0100
Branches: node-tree-update-refactor
https://developer.blender.org/rBcb5569f849f123e587d2aef4ba4fd48354741d53
progress
===================================================================
M source/blender/blenkernel/intern/node_tree_update.cc
===================================================================
diff --git a/source/blender/blenkernel/intern/node_tree_update.cc b/source/blender/blenkernel/intern/node_tree_update.cc
index ac81b239976..d6c60eb1b38 100644
--- a/source/blender/blenkernel/intern/node_tree_update.cc
+++ b/source/blender/blenkernel/intern/node_tree_update.cc
@@ -16,6 +16,8 @@
#include "BLI_map.hh"
#include "BLI_multi_value_map.hh"
+#include "BLI_set.hh"
+#include "BLI_vector_set.hh"
#include "DNA_modifier_types.h"
#include "DNA_node_types.h"
@@ -35,6 +37,7 @@ using ObjectModifierPair = std::pair<Object *, ModifierData *>;
struct NodeTreeRelations {
private:
Main *bmain_;
+ std::optional<Vector<IDTreePair>> all_trees_;
std::optional<MultiValueMap<bNodeTree *, TreeNodePair>> group_node_users_;
std::optional<MultiValueMap<bNodeTree *, ObjectModifierPair>> modifiers_users_;
@@ -43,19 +46,36 @@ struct NodeTreeRelations {
{
}
+ void ensure_all_trees()
+ {
+ if (all_trees_.has_value()) {
+ return;
+ }
+ all_trees_.emplace();
+ if (bmain_ == nullptr) {
+ return;
+ }
+
+ FOREACH_NODETREE_BEGIN (bmain_, ntree, id) {
+ all_trees_->append({id, ntree});
+ }
+ FOREACH_NODETREE_END;
+ }
+
void ensure_group_node_users()
{
if (group_node_users_.has_value()) {
return;
}
-
group_node_users_.emplace();
-
if (bmain_ == nullptr) {
return;
}
- FOREACH_NODETREE_BEGIN (bmain_, ntree, id) {
+ this->ensure_all_trees();
+
+ for (const IDTreePair &pair : *all_trees_) {
+ bNodeTree *ntree = pair.second;
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->id == nullptr) {
continue;
@@ -67,7 +87,6 @@ struct NodeTreeRelations {
}
}
}
- FOREACH_NODETREE_END;
}
void ensure_modifier_users()
@@ -75,9 +94,7 @@ struct NodeTreeRelations {
if (modifiers_users_.has_value()) {
return;
}
-
modifiers_users_.emplace();
-
if (bmain_ == nullptr) {
return;
}
@@ -102,9 +119,15 @@ struct NodeTreeRelations {
Span<TreeNodePair> get_group_node_users(bNodeTree *ntree)
{
- BLI_assert(group_node_users_);
+ BLI_assert(group_node_users_.has_value());
return group_node_users_->lookup(ntree);
}
+
+ Span<IDTreePair> get_all_trees()
+ {
+ BLI_assert(all_trees_.has_value());
+ return *all_trees_;
+ }
};
struct TreeUpdateResult {
@@ -174,24 +197,6 @@ class NodeTreeMainUpdater {
}
}
- Vector<bNodeTree *> trees_with_visible_changes;
- for (bNodeTree *ntree : root_ntrees) {
- const TreeUpdateResult result = this->update_tree(*ntree);
- update_result_by_tree_.add_new(ntree, result);
-
- if (result.output_changed || result.interface_changed) {
- trees_with_visible_changes.append(ntree);
- relations_.ensure_group_node_users();
- if (ntree->type == NTREE_GEOMETRY) {
- relations_.ensure_modifier_users();
- }
- }
- }
-
- if (!trees_with_visible_changes.is_empty()) {
- relations_.ensure_group_node_users();
- }
-
for (const auto &item : update_result_by_tree_.items()) {
bNodeTree *ntree = item.key;
const TreeUpdateResult &result = item.value;
@@ -229,10 +234,79 @@ class NodeTreeMainUpdater {
}
private:
+ enum class ToposortMark {
+ None,
+ Temporary,
+ Permanent,
+ };
+
+ using ToposortMarkMap = Map<bNodeTree *, ToposortMark>;
+
Vector<bNodeTree *> get_tree_update_order(Span<bNodeTree *> root_ntrees)
+ {
+ relations_.ensure_all_trees();
+ relations_.ensure_group_node_users();
+
+ Set<bNodeTree *> trees_to_update = get_trees_to_update(root_ntrees);
+
+ Vector<bNodeTree *> sorted_ntrees;
+
+ ToposortMarkMap marks;
+ for (bNodeTree *ntree : trees_to_update) {
+ marks.add_new(ntree, ToposortMark::None);
+ }
+ for (bNodeTree *ntree : trees_to_update) {
+ if (marks.lookup(ntree) == ToposortMark::None) {
+ const bool cycle_detected = !this->get_tree_update_order__visit_recursive(
+ ntree, marks, sorted_ntrees);
+ BLI_assert(!cycle_detected);
+ }
+ }
+
+ return sorted_ntrees;
+ }
+
+ bool get_tree_update_order__visit_recursive(bNodeTree *ntree,
+ ToposortMarkMap &marks,
+ Vector<bNodeTree *> &sorted_ntrees)
+ {
+ ToposortMark &mark = marks.lookup(ntree);
+ if (mark == ToposortMark::Permanent) {
+ return true;
+ }
+ if (mark == ToposortMark::Temporary) {
+ /* There is a dependency cycle. */
+ return false;
+ }
+
+ mark = ToposortMark::Temporary;
+
+ for (const TreeNodePair &pair : relations_.get_group_node_users(ntree)) {
+ this->get_tree_update_order__visit_recursive(pair.first, marks, sorted_ntrees);
+ }
+ sorted_ntrees.append(ntree);
+
+ mark = ToposortMark::Permanent;
+ return true;
+ }
+
+ Set<bNodeTree *> get_trees_to_update(Span<bNodeTree *> root_ntrees)
{
relations_.ensure_group_node_users();
- return {};
+
+ Set<bNodeTree *> reachable_trees;
+ VectorSet<bNodeTree *> trees_to_check = root_ntrees;
+
+ while (!trees_to_check.is_empty()) {
+ bNodeTree *ntree = trees_to_check.pop();
+ if (reachable_trees.add(ntree)) {
+ for (const TreeNodePair &pair : relations_.get_group_node_users(ntree)) {
+ trees_to_check.add(pair.first);
+ }
+ }
+ }
+
+ return reachable_trees;
}
TreeUpdateResult update_tree(bNodeTree &ntree)
@@ -340,6 +414,6 @@ void BKE_node_tree_update_main_rooted(Main *bmain,
is_updating = true;
blender::bke::NodeTreeMainUpdater updater{bmain, params};
- updater.update_rooted({{(ID *)ntree, ntree}});
+ updater.update_rooted({ntree});
is_updating = false;
}
More information about the Bf-blender-cvs
mailing list