From 9e155eb1f0083354ab5d66f233b1067d16088d62 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 4 Jul 2019 15:04:03 +0200 Subject: Depsgraph: Add dependencies traversal which is aware of component Sometimes it is required to know which exact part of ID is being dependent on the given iD. Now it is possible. --- .../depsgraph/intern/depsgraph_query_foreach.cc | 97 ++++++++++++++++++---- 1 file changed, 79 insertions(+), 18 deletions(-) (limited to 'source/blender/depsgraph/intern/depsgraph_query_foreach.cc') diff --git a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc index 717793d60f1..f5fcdf8e5d1 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc @@ -48,25 +48,29 @@ extern "C" { /* ************************ DEG TRAVERSAL ********************* */ namespace DEG { +namespace { typedef std::deque TraversalQueue; enum { DEG_NODE_VISITED = (1 << 0), }; -static void deg_foreach_clear_flags(const Depsgraph *graph) +typedef void (*DEGForeachOperation)(OperationNode *op_node, void *user_data); + +void deg_foreach_clear_flags(const Depsgraph *graph) { for (OperationNode *op_node : graph->operations) { op_node->scheduled = false; + op_node->owner->custom_flags = 0; } for (IDNode *id_node : graph->id_nodes) { id_node->custom_flags = 0; } } -static void deg_foreach_dependent_ID(const Depsgraph *graph, +void deg_foreach_dependent_operation(const Depsgraph *graph, const ID *id, - DEGForeachIDCallback callback, + DEGForeachOperation callback, void *user_data) { /* Start with getting ID node from the graph. */ @@ -84,6 +88,7 @@ static void deg_foreach_dependent_ID(const Depsgraph *graph, for (OperationNode *op_node : comp_node->operations) { queue.push_back(op_node); op_node->scheduled = true; + op_node->owner->custom_flags |= DEG_NODE_VISITED; } } GHASH_FOREACH_END(); @@ -94,14 +99,7 @@ static void deg_foreach_dependent_ID(const Depsgraph *graph, OperationNode *op_node = queue.front(); queue.pop_front(); for (;;) { - /* Check whether we need to inform callee about corresponding ID node. */ - ComponentNode *comp_node = op_node->owner; - IDNode *id_node = comp_node->owner; - if ((id_node->custom_flags & DEG_NODE_VISITED) == 0) { - /* TODO(sergey): Is it orig or CoW? */ - callback(id_node->id_orig, user_data); - id_node->custom_flags |= DEG_NODE_VISITED; - } + callback(op_node, user_data); /* Schedule outgoing operation nodes. */ if (op_node->outlinks.size() == 1) { OperationNode *to_node = (OperationNode *)op_node->outlinks[0]->to; @@ -127,10 +125,65 @@ static void deg_foreach_dependent_ID(const Depsgraph *graph, } } -static void deg_foreach_ancestor_ID(const Depsgraph *graph, - const ID *id, - DEGForeachIDCallback callback, - void *user_data) +struct ForeachIDComponentData { + DEGForeachIDComponentCallback callback; + void *user_data; +}; + +void deg_foreach_dependent_component_callback(OperationNode *op_node, void *user_data_v) +{ + ForeachIDComponentData *user_data = reinterpret_cast(user_data_v); + ComponentNode *comp_node = op_node->owner; + if ((comp_node->custom_flags & DEG_NODE_VISITED) == 0) { + IDNode *id_node = comp_node->owner; + user_data->callback( + id_node->id_orig, nodeTypeToObjectComponent(comp_node->type), user_data->user_data); + comp_node->custom_flags |= DEG_NODE_VISITED; + } +} + +void deg_foreach_dependent_ID_component(const Depsgraph *graph, + const ID *id, + DEGForeachIDComponentCallback callback, + void *user_data) +{ + ForeachIDComponentData data; + data.callback = callback; + data.user_data = user_data; + deg_foreach_dependent_operation(graph, id, deg_foreach_dependent_component_callback, &data); +} + +struct ForeachIDData { + DEGForeachIDCallback callback; + void *user_data; +}; + +void deg_foreach_dependent_ID_callback(OperationNode *op_node, void *user_data_v) +{ + ForeachIDData *user_data = reinterpret_cast(user_data_v); + ComponentNode *comp_node = op_node->owner; + IDNode *id_node = comp_node->owner; + if ((id_node->custom_flags & DEG_NODE_VISITED) == 0) { + user_data->callback(id_node->id_orig, user_data->user_data); + id_node->custom_flags |= DEG_NODE_VISITED; + } +} + +void deg_foreach_dependent_ID(const Depsgraph *graph, + const ID *id, + DEGForeachIDCallback callback, + void *user_data) +{ + ForeachIDData data; + data.callback = callback; + data.user_data = user_data; + deg_foreach_dependent_operation(graph, id, deg_foreach_dependent_ID_callback, &data); +} + +void deg_foreach_ancestor_ID(const Depsgraph *graph, + const ID *id, + DEGForeachIDCallback callback, + void *user_data) { /* Start with getting ID node from the graph. */ IDNode *target_id_node = graph->find_id_node(id); @@ -196,15 +249,14 @@ static void deg_foreach_ancestor_ID(const Depsgraph *graph, } } -static void deg_foreach_id(const Depsgraph *depsgraph, - DEGForeachIDCallback callback, - void *user_data) +void deg_foreach_id(const Depsgraph *depsgraph, DEGForeachIDCallback callback, void *user_data) { for (const IDNode *id_node : depsgraph->id_nodes) { callback(id_node->id_orig, user_data); } } +} // namespace } // namespace DEG void DEG_foreach_dependent_ID(const Depsgraph *depsgraph, @@ -215,6 +267,15 @@ void DEG_foreach_dependent_ID(const Depsgraph *depsgraph, DEG::deg_foreach_dependent_ID((const DEG::Depsgraph *)depsgraph, id, callback, user_data); } +void DEG_foreach_dependent_ID_component(const Depsgraph *depsgraph, + const ID *id, + DEGForeachIDComponentCallback callback, + void *user_data) +{ + DEG::deg_foreach_dependent_ID_component( + (const DEG::Depsgraph *)depsgraph, id, callback, user_data); +} + void DEG_foreach_ancestor_ID(const Depsgraph *depsgraph, const ID *id, DEGForeachIDCallback callback, -- cgit v1.2.3