diff options
author | Jacques Lucke <jacques@blender.org> | 2020-07-23 13:09:28 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2020-07-23 13:09:36 +0300 |
commit | 634585aa6875f9e6e8a2e43e283f9d530764a094 (patch) | |
tree | 837a72316887305f8e0b14c69bb1469dea4b1c7c /source/blender | |
parent | 65968911217380a7a594f8684150b5fa01866d6a (diff) |
Simulation: add depsgraph relations for ids referenced by node tree
I'll really have to refactor `ntreeUpdateTree` soon to avoid scanning
all node trees multiple times.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_simulation.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.c | 16 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/simulation.cc | 8 | ||||
-rw-r--r-- | source/blender/depsgraph/intern/builder/deg_builder_relations.cc | 19 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_simulation_types.h | 8 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_nodetree.c | 15 | ||||
-rw-r--r-- | source/blender/nodes/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/nodes/NOD_node_tree_dependencies.hh | 79 | ||||
-rw-r--r-- | source/blender/nodes/intern/node_tree_dependencies.cc | 57 | ||||
-rw-r--r-- | source/blender/simulation/SIM_simulation_update.hh | 4 | ||||
-rw-r--r-- | source/blender/simulation/intern/simulation_collect_influences.cc | 22 | ||||
-rw-r--r-- | source/blender/simulation/intern/simulation_collect_influences.hh | 21 | ||||
-rw-r--r-- | source/blender/simulation/intern/simulation_update.cc | 134 |
13 files changed, 287 insertions, 99 deletions
diff --git a/source/blender/blenkernel/BKE_simulation.h b/source/blender/blenkernel/BKE_simulation.h index 5aa71b6381d..6cbe77e8de3 100644 --- a/source/blender/blenkernel/BKE_simulation.h +++ b/source/blender/blenkernel/BKE_simulation.h @@ -32,6 +32,7 @@ void *BKE_simulation_add(struct Main *bmain, const char *name); void BKE_simulation_data_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Simulation *simulation); +void BKE_simulation_update_dependencies(struct Simulation *simulation, struct Main *bmain); SimulationState *BKE_simulation_state_add(Simulation *simulation, const char *type, diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 7dbf38657a1..ca1354e9fea 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -61,6 +61,7 @@ #include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_simulation.h" #include "BLI_ghash.h" #include "BLI_threads.h" @@ -3638,6 +3639,16 @@ void ntreeUpdateAllUsers(Main *main, ID *ngroup) FOREACH_NODETREE_END; } +static void ntreeUpdateSimulationDependencies(Main *main, bNodeTree *simulation_ntree) +{ + FOREACH_NODETREE_BEGIN (main, ntree, owner_id) { + if (GS(owner_id->name) == ID_SIM && ntree == simulation_ntree) { + BKE_simulation_update_dependencies((Simulation *)owner_id, main); + } + } + FOREACH_NODETREE_END; +} + void ntreeUpdateTree(Main *bmain, bNodeTree *ntree) { bNode *node; @@ -3695,6 +3706,11 @@ void ntreeUpdateTree(Main *bmain, bNodeTree *ntree) ntree_validate_links(ntree); } + if (bmain != NULL && ntree->typeinfo == ntreeType_Simulation && + (ntree->id.flag & LIB_EMBEDDED_DATA)) { + ntreeUpdateSimulationDependencies(bmain, ntree); + } + /* clear update flags */ for (node = ntree->nodes.first; node; node = node->next) { node->update = 0; diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc index ac9c13e157c..b1c7f50a2af 100644 --- a/source/blender/blenkernel/intern/simulation.cc +++ b/source/blender/blenkernel/intern/simulation.cc @@ -285,6 +285,14 @@ void BKE_simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulation * blender::sim::update_simulation_in_depsgraph(depsgraph, scene, simulation); } +void BKE_simulation_update_dependencies(Simulation *simulation, Main *bmain) +{ + bool dependencies_changed = blender::sim::update_simulation_dependencies(simulation); + if (dependencies_changed) { + DEG_relations_tag_update(bmain); + } +} + using StateTypeMap = blender::Map<std::string, std::unique_ptr<SimulationStateType>>; template<typename T> diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 2fb67010bb0..e0e35c88af2 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -2634,6 +2634,25 @@ void DepsgraphRelationBuilder::build_simulation(Simulation *simulation) OperationKey nodetree_key( &simulation->nodetree->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT); add_relation(nodetree_key, simulation_eval_key, "NodeTree -> Simulation", 0); + + LISTBASE_FOREACH ( + PersistentDataHandleItem *, handle_item, &simulation->persistent_data_handles) { + if (handle_item->id == nullptr) { + continue; + } + build_id(handle_item->id); + if (GS(handle_item->id->name) == ID_OB) { + Object *object = (Object *)handle_item->id; + if (handle_item->flag & SIM_HANDLE_DEPENDS_ON_TRANSFORM) { + ComponentKey object_transform_key(&object->id, NodeType::TRANSFORM); + add_relation(object_transform_key, simulation_eval_key, "Object Transform -> Simulation"); + } + if (handle_item->flag & SIM_HANDLE_DEPENDS_ON_GEOMETRY) { + ComponentKey object_geometry_key(&object->id, NodeType::GEOMETRY); + add_relation(object_geometry_key, simulation_eval_key, "Object Geometry -> Simulation"); + } + } + } } void DepsgraphRelationBuilder::build_scene_sequencer(Scene *scene) diff --git a/source/blender/makesdna/DNA_simulation_types.h b/source/blender/makesdna/DNA_simulation_types.h index 5bb0e50e089..c0be66dcb30 100644 --- a/source/blender/makesdna/DNA_simulation_types.h +++ b/source/blender/makesdna/DNA_simulation_types.h @@ -72,7 +72,7 @@ typedef struct PersistentDataHandleItem { struct PersistentDataHandleItem *prev; struct ID *id; int handle; - char _pad[4]; + int flag; } PersistentDataHandleItem; /* Simulation.flag */ @@ -80,6 +80,12 @@ enum { SIM_DS_EXPAND = (1 << 0), }; +/* PersistentDataHandleItem.flag */ +enum { + SIM_HANDLE_DEPENDS_ON_TRANSFORM = (1 << 0), + SIM_HANDLE_DEPENDS_ON_GEOMETRY = (1 << 1), +}; + #define SIM_TYPE_NAME_PARTICLE_SIMULATION "Particle Simulation" #define SIM_TYPE_NAME_PARTICLE_MESH_EMITTER "Particle Mesh Emitter" diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 6f0192bb810..0359b2ed959 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -38,6 +38,7 @@ #include "BKE_animsys.h" #include "BKE_image.h" #include "BKE_node.h" +#include "BKE_simulation.h" #include "BKE_texture.h" #include "RNA_access.h" @@ -2848,6 +2849,14 @@ static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA * } } +static void rna_NodeSocketStandard_value_and_relation_update(struct bContext *C, PointerRNA *ptr) +{ + rna_NodeSocketStandard_value_update(C, ptr); + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; + Main *bmain = CTX_data_main(C); + ntreeUpdateTree(bmain, ntree); +} + /* ******** Node Types ******** */ static void rna_NodeInternalSocketTemplate_name_get(PointerRNA *ptr, char *value) @@ -8862,7 +8871,8 @@ static void rna_def_node_socket_object(BlenderRNA *brna, RNA_def_property_pointer_sdna(prop, NULL, "value"); RNA_def_property_struct_type(prop, "Object"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); + RNA_def_property_update( + prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_and_relation_update"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE); /* socket interface */ @@ -8896,7 +8906,8 @@ static void rna_def_node_socket_image(BlenderRNA *brna, RNA_def_property_pointer_sdna(prop, NULL, "value"); RNA_def_property_struct_type(prop, "Image"); RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); + RNA_def_property_update( + prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_and_relation_update"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE); /* socket interface */ diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 80720f5206a..bb2aaf35e52 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -278,6 +278,7 @@ set(SRC intern/node_common.c intern/node_exec.c intern/node_socket.cc + intern/node_tree_dependencies.cc intern/node_tree_multi_function.cc intern/node_tree_ref.cc intern/node_util.c @@ -292,6 +293,7 @@ set(SRC NOD_composite.h NOD_derived_node_tree.hh NOD_function.h + NOD_node_tree_dependencies.hh NOD_node_tree_multi_function.hh NOD_node_tree_ref.hh NOD_shader.h diff --git a/source/blender/nodes/NOD_node_tree_dependencies.hh b/source/blender/nodes/NOD_node_tree_dependencies.hh new file mode 100644 index 00000000000..ca7059caa5f --- /dev/null +++ b/source/blender/nodes/NOD_node_tree_dependencies.hh @@ -0,0 +1,79 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __NOD_NODE_TREE_DEPENDENCIES_H__ +#define __NOD_NODE_TREE_DEPENDENCIES_H__ + +#include "BLI_vector_set.hh" + +#include "DNA_ID.h" +#include "DNA_object_types.h" + +struct bNodeTree; + +namespace blender::nodes { + +class NodeTreeDependencies { + private: + VectorSet<Object *> transform_deps_; + VectorSet<Object *> geometry_deps_; + VectorSet<ID *> id_deps_; + + public: + void add_transform_dependency(Object *object) + { + if (object == nullptr) { + return; + } + transform_deps_.add(object); + id_deps_.add(&object->id); + } + + void add_geometry_dependency(Object *object) + { + if (object == nullptr) { + return; + } + geometry_deps_.add(object); + id_deps_.add(&object->id); + } + + bool depends_on(ID *id) const + { + return id_deps_.contains(id); + } + + Span<Object *> transform_dependencies() + { + return transform_deps_; + } + + Span<Object *> geometry_dependencies() + { + return geometry_deps_; + } + + Span<ID *> id_dependencies() + { + return id_deps_; + } +}; + +NodeTreeDependencies find_node_tree_dependencies(bNodeTree &ntree); + +} // namespace blender::nodes + +#endif /* __NOD_NODE_TREE_DEPENDENCIES_H__ */ diff --git a/source/blender/nodes/intern/node_tree_dependencies.cc b/source/blender/nodes/intern/node_tree_dependencies.cc new file mode 100644 index 00000000000..efe75a10f7e --- /dev/null +++ b/source/blender/nodes/intern/node_tree_dependencies.cc @@ -0,0 +1,57 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "NOD_node_tree_dependencies.hh" + +#include "DNA_node_types.h" + +#include "BKE_node.h" + +namespace blender::nodes { + +static void add_dependencies_of_node_tree(bNodeTree &ntree, NodeTreeDependencies &r_dependencies) +{ + /* TODO: Do a bit more sophisticated parsing to see which dependencies are really required. */ + LISTBASE_FOREACH (bNode *, node, &ntree.nodes) { + LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { + if (socket->type == SOCK_OBJECT) { + Object *object = ((bNodeSocketValueObject *)socket->default_value)->value; + if (object != nullptr) { + r_dependencies.add_transform_dependency(object); + if (object->type == OB_MESH) { + r_dependencies.add_geometry_dependency(object); + } + } + } + } + + if (node->type == NODE_GROUP) { + bNodeTree *group = (bNodeTree *)node->id; + if (group != nullptr) { + add_dependencies_of_node_tree(*group, r_dependencies); + } + } + } +} + +NodeTreeDependencies find_node_tree_dependencies(bNodeTree &ntree) +{ + NodeTreeDependencies dependencies; + add_dependencies_of_node_tree(ntree, dependencies); + return dependencies; +} + +} // namespace blender::nodes diff --git a/source/blender/simulation/SIM_simulation_update.hh b/source/blender/simulation/SIM_simulation_update.hh index 40b62bfb58a..efdfde8a4de 100644 --- a/source/blender/simulation/SIM_simulation_update.hh +++ b/source/blender/simulation/SIM_simulation_update.hh @@ -27,6 +27,8 @@ void update_simulation_in_depsgraph(Depsgraph *depsgraph, Scene *scene_cow, Simulation *simulation_cow); -} +bool update_simulation_dependencies(Simulation *simulation); + +} // namespace blender::sim #endif /* __SIM_SIMULATION_UPDATE_HH__ */ diff --git a/source/blender/simulation/intern/simulation_collect_influences.cc b/source/blender/simulation/intern/simulation_collect_influences.cc index bbc28077dff..876d0b50fc1 100644 --- a/source/blender/simulation/intern/simulation_collect_influences.cc +++ b/source/blender/simulation/intern/simulation_collect_influences.cc @@ -436,28 +436,10 @@ static void prepare_particle_attribute_builders(nodes::MFNetworkTreeMap &network } } -static void find_used_persistent_data(const nodes::DerivedNodeTree &tree, - UsedPersistentData &r_used_persistent_data) -{ - const bNodeSocketType *socktype = nodeSocketTypeFind("NodeSocketObject"); - BLI_assert(socktype != nullptr); - - for (const nodes::DInputSocket *dsocket : tree.input_sockets()) { - const bNodeSocket *bsocket = dsocket->bsocket(); - if (bsocket->typeinfo == socktype) { - Object *object = ((const bNodeSocketValueObject *)bsocket->default_value)->value; - if (object != nullptr) { - r_used_persistent_data.add(DEG_get_original_id(&object->id)); - } - } - } -} - void collect_simulation_influences(Simulation &simulation, ResourceCollector &resources, SimulationInfluences &r_influences, - RequiredStates &r_required_states, - UsedPersistentData &r_used_persistent_data) + RequiredStates &r_required_states) { nodes::NodeTreeRefMap tree_refs; const nodes::DerivedNodeTree tree{simulation.nodetree, tree_refs}; @@ -481,8 +463,6 @@ void collect_simulation_influences(Simulation &simulation, for (const nodes::DNode *dnode : get_particle_simulation_nodes(tree)) { r_required_states.add(dnode_to_path(*dnode), SIM_TYPE_NAME_PARTICLE_SIMULATION); } - - find_used_persistent_data(tree, r_used_persistent_data); } } // namespace blender::sim diff --git a/source/blender/simulation/intern/simulation_collect_influences.hh b/source/blender/simulation/intern/simulation_collect_influences.hh index 13744c3bc1a..42cbea6977e 100644 --- a/source/blender/simulation/intern/simulation_collect_influences.hh +++ b/source/blender/simulation/intern/simulation_collect_influences.hh @@ -58,29 +58,10 @@ class RequiredStates { } }; -class UsedPersistentData { - private: - VectorSet<ID *> used_ids_; - - public: - void add(ID *id) - { - BLI_assert(id != nullptr); - BLI_assert((id->tag & LIB_TAG_NO_MAIN) == 0); - used_ids_.add(id); - } - - const VectorSet<ID *> &used_ids() const - { - return used_ids_; - } -}; - void collect_simulation_influences(Simulation &simulation, ResourceCollector &resources, SimulationInfluences &r_influences, - RequiredStates &r_required_states, - UsedPersistentData &r_used_persistent_data); + RequiredStates &r_required_states); } // namespace blender::sim diff --git a/source/blender/simulation/intern/simulation_update.cc b/source/blender/simulation/intern/simulation_update.cc index 9258d9cac07..3303145b891 100644 --- a/source/blender/simulation/intern/simulation_update.cc +++ b/source/blender/simulation/intern/simulation_update.cc @@ -33,6 +33,8 @@ #include "BLI_set.hh" #include "BLI_vector.hh" +#include "NOD_node_tree_dependencies.hh" + #include "particle_function.hh" #include "simulation_collect_influences.hh" #include "simulation_solver.hh" @@ -90,56 +92,6 @@ static void update_simulation_state_list(Simulation *simulation, add_missing_states(simulation, required_states); } -/* TODO: It might be better to do this as part of ntreeUpdateTree, so that the information - * about referenced data blocks is available when building the depsgraph. */ -static void update_persistent_data_handles(Simulation &simulation_orig, - const UsedPersistentData &used_persistent_data) -{ - Set<ID *> contained_ids; - Set<int> used_handles; - - /* Remove handles that have been invalidated. */ - LISTBASE_FOREACH_MUTABLE ( - PersistentDataHandleItem *, handle_item, &simulation_orig.persistent_data_handles) { - if (handle_item->id == nullptr) { - BLI_remlink(&simulation_orig.persistent_data_handles, handle_item); - MEM_freeN(handle_item); - continue; - } - if (!used_persistent_data.used_ids().contains(handle_item->id)) { - id_us_min(handle_item->id); - BLI_remlink(&simulation_orig.persistent_data_handles, handle_item); - MEM_freeN(handle_item); - continue; - } - contained_ids.add_new(handle_item->id); - used_handles.add_new(handle_item->handle); - } - - /* Add new handles that are not in the list yet. */ - int next_handle = 0; - for (ID *id : used_persistent_data.used_ids()) { - if (contained_ids.contains(id)) { - continue; - } - - /* Find the next available handle. */ - while (used_handles.contains(next_handle)) { - next_handle++; - } - used_handles.add_new(next_handle); - - PersistentDataHandleItem *handle_item = (PersistentDataHandleItem *)MEM_callocN( - sizeof(*handle_item), AT); - /* Cannot store const pointers in DNA. */ - id_us_plus(id); - handle_item->id = id; - handle_item->handle = next_handle; - - BLI_addtail(&simulation_orig.persistent_data_handles, handle_item); - } -} - void update_simulation_in_depsgraph(Depsgraph *depsgraph, Scene *scene_cow, Simulation *simulation_cow) @@ -159,11 +111,8 @@ void update_simulation_in_depsgraph(Depsgraph *depsgraph, ResourceCollector resources; SimulationInfluences influences; RequiredStates required_states; - UsedPersistentData used_persistent_data; - collect_simulation_influences( - *simulation_cow, resources, influences, required_states, used_persistent_data); - update_persistent_data_handles(*simulation_orig, used_persistent_data); + collect_simulation_influences(*simulation_cow, resources, influences, required_states); bke::PersistentDataHandleMap handle_map; LISTBASE_FOREACH ( @@ -191,4 +140,81 @@ void update_simulation_in_depsgraph(Depsgraph *depsgraph, } } +/* Returns true when dependencies have changed. */ +bool update_simulation_dependencies(Simulation *simulation) +{ + nodes::NodeTreeDependencies dependencies = nodes::find_node_tree_dependencies( + *simulation->nodetree); + + ListBase *handle_list = &simulation->persistent_data_handles; + + bool dependencies_changed = false; + + Map<ID *, PersistentDataHandleItem *> handle_item_by_id; + Map<PersistentDataHandleItem *, int> old_flag_by_handle_item; + Set<int> used_handles; + + /* Remove unused handle items and clear flags that are reinitialized later. */ + LISTBASE_FOREACH_MUTABLE (PersistentDataHandleItem *, handle_item, handle_list) { + if (dependencies.depends_on(handle_item->id)) { + handle_item_by_id.add_new(handle_item->id, handle_item); + used_handles.add_new(handle_item->handle); + old_flag_by_handle_item.add_new(handle_item, handle_item->flag); + handle_item->flag &= ~(SIM_HANDLE_DEPENDS_ON_TRANSFORM | SIM_HANDLE_DEPENDS_ON_GEOMETRY); + } + else { + if (handle_item->id != nullptr) { + id_us_min(handle_item->id); + } + BLI_remlink(handle_list, handle_item); + MEM_freeN(handle_item); + dependencies_changed = true; + } + } + + /* Add handle items for new id dependencies. */ + int next_handle = 0; + for (ID *id : dependencies.id_dependencies()) { + handle_item_by_id.lookup_or_add_cb(id, [&]() { + while (used_handles.contains(next_handle)) { + next_handle++; + } + used_handles.add_new(next_handle); + + PersistentDataHandleItem *handle_item = (PersistentDataHandleItem *)MEM_callocN( + sizeof(*handle_item), AT); + id_us_plus(id); + handle_item->id = id; + handle_item->handle = next_handle; + BLI_addtail(handle_list, handle_item); + + return handle_item; + }); + } + + /* Set appropriate dependency flags. */ + for (Object *object : dependencies.transform_dependencies()) { + PersistentDataHandleItem *handle_item = handle_item_by_id.lookup(&object->id); + handle_item->flag |= SIM_HANDLE_DEPENDS_ON_TRANSFORM; + } + for (Object *object : dependencies.geometry_dependencies()) { + PersistentDataHandleItem *handle_item = handle_item_by_id.lookup(&object->id); + handle_item->flag |= SIM_HANDLE_DEPENDS_ON_GEOMETRY; + } + + if (!dependencies_changed) { + /* Check if any flags have changed. */ + LISTBASE_FOREACH (PersistentDataHandleItem *, handle_item, handle_list) { + int old_flag = old_flag_by_handle_item.lookup_default(handle_item, 0); + int new_flag = handle_item->flag; + if (old_flag != new_flag) { + dependencies_changed = true; + break; + } + } + } + + return dependencies_changed; +} + } // namespace blender::sim |