diff options
Diffstat (limited to 'source/blender/modifiers/intern/MOD_nodes.cc')
-rw-r--r-- | source/blender/modifiers/intern/MOD_nodes.cc | 152 |
1 files changed, 93 insertions, 59 deletions
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index c5ee4b9fb52..f16fc8ff764 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -141,56 +141,85 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(nmd, DNA_struct_default_get(NodesModifierData), modifier); } -static void addIdsUsedBySocket(const ListBase *sockets, Set<ID *> &ids) +static void add_used_ids_from_sockets(const ListBase &sockets, Set<ID *> &ids) { - LISTBASE_FOREACH (const bNodeSocket *, socket, sockets) { - if (socket->type == SOCK_OBJECT) { - Object *object = ((bNodeSocketValueObject *)socket->default_value)->value; - if (object != nullptr) { - ids.add(&object->id); + LISTBASE_FOREACH (const bNodeSocket *, socket, &sockets) { + switch (socket->type) { + case SOCK_OBJECT: { + if (Object *object = ((bNodeSocketValueObject *)socket->default_value)->value) { + ids.add(&object->id); + } + break; } - } - else if (socket->type == SOCK_COLLECTION) { - Collection *collection = ((bNodeSocketValueCollection *)socket->default_value)->value; - if (collection != nullptr) { - ids.add(&collection->id); + case SOCK_COLLECTION: { + if (Collection *collection = + ((bNodeSocketValueCollection *)socket->default_value)->value) { + ids.add(&collection->id); + } + break; } - } - else if (socket->type == SOCK_MATERIAL) { - Material *material = ((bNodeSocketValueMaterial *)socket->default_value)->value; - if (material != nullptr) { - ids.add(&material->id); + case SOCK_MATERIAL: { + if (Material *material = ((bNodeSocketValueMaterial *)socket->default_value)->value) { + ids.add(&material->id); + } + break; } - } - else if (socket->type == SOCK_TEXTURE) { - Tex *texture = ((bNodeSocketValueTexture *)socket->default_value)->value; - if (texture != nullptr) { - ids.add(&texture->id); + case SOCK_TEXTURE: { + if (Tex *texture = ((bNodeSocketValueTexture *)socket->default_value)->value) { + ids.add(&texture->id); + } + break; } - } - else if (socket->type == SOCK_IMAGE) { - Image *image = ((bNodeSocketValueImage *)socket->default_value)->value; - if (image != nullptr) { - ids.add(&image->id); + case SOCK_IMAGE: { + if (Image *image = ((bNodeSocketValueImage *)socket->default_value)->value) { + ids.add(&image->id); + } + break; } } } } -static void find_used_ids_from_nodes(const bNodeTree &tree, Set<ID *> &ids) +/** + * \note We can only check properties here that cause the dependency graph to update relations when + * they are changed, otherwise there may be a missing relation after editing. So this could check + * more properties like whether the node is muted, but we would have to accept the cost of updating + * relations when those properties are changed. + */ +static bool node_needs_own_transform_relation(const bNode &node) +{ + if (node.type == GEO_NODE_COLLECTION_INFO) { + const NodeGeometryCollectionInfo &storage = *static_cast<const NodeGeometryCollectionInfo *>( + node.storage); + return storage.transform_space == GEO_NODE_TRANSFORM_SPACE_RELATIVE; + } + + if (node.type == GEO_NODE_OBJECT_INFO) { + const NodeGeometryObjectInfo &storage = *static_cast<const NodeGeometryObjectInfo *>( + node.storage); + return storage.transform_space == GEO_NODE_TRANSFORM_SPACE_RELATIVE; + } + + return false; +} + +static void process_nodes_for_depsgraph(const bNodeTree &tree, + Set<ID *> &ids, + bool &needs_own_transform_relation) { Set<const bNodeTree *> handled_groups; LISTBASE_FOREACH (const bNode *, node, &tree.nodes) { - addIdsUsedBySocket(&node->inputs, ids); - addIdsUsedBySocket(&node->outputs, ids); + add_used_ids_from_sockets(node->inputs, ids); + add_used_ids_from_sockets(node->outputs, ids); if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP)) { const bNodeTree *group = (bNodeTree *)node->id; if (group != nullptr && handled_groups.add(group)) { - find_used_ids_from_nodes(*group, ids); + process_nodes_for_depsgraph(*group, ids, needs_own_transform_relation); } } + needs_own_transform_relation |= node_needs_own_transform_relation(*node); } } @@ -240,37 +269,43 @@ static void add_object_relation(const ModifierUpdateDepsgraphContext *ctx, Objec static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) { NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md); - DEG_add_modifier_to_transform_relation(ctx->node, "Nodes Modifier"); - if (nmd->node_group != nullptr) { - DEG_add_node_tree_output_relation(ctx->node, nmd->node_group, "Nodes Modifier"); - - Set<ID *> used_ids; - find_used_ids_from_settings(nmd->settings, used_ids); - find_used_ids_from_nodes(*nmd->node_group, used_ids); - for (ID *id : used_ids) { - switch ((ID_Type)GS(id->name)) { - case ID_OB: { - Object *object = reinterpret_cast<Object *>(id); - add_object_relation(ctx, *object); - break; - } - case ID_GR: { - Collection *collection = reinterpret_cast<Collection *>(id); - add_collection_relation(ctx, *collection); - break; - } - case ID_IM: - case ID_TE: { - DEG_add_generic_id_relation(ctx->node, id, "Nodes Modifier"); - } - default: { - /* Purposefully don't add relations for materials. While there are material sockets, - * the pointers are only passed around as handles rather than dereferenced. */ - break; - } + if (nmd->node_group == nullptr) { + return; + } + + DEG_add_node_tree_output_relation(ctx->node, nmd->node_group, "Nodes Modifier"); + + bool needs_own_transform_relation = false; + Set<ID *> used_ids; + find_used_ids_from_settings(nmd->settings, used_ids); + process_nodes_for_depsgraph(*nmd->node_group, used_ids, needs_own_transform_relation); + for (ID *id : used_ids) { + switch ((ID_Type)GS(id->name)) { + case ID_OB: { + Object *object = reinterpret_cast<Object *>(id); + add_object_relation(ctx, *object); + break; + } + case ID_GR: { + Collection *collection = reinterpret_cast<Collection *>(id); + add_collection_relation(ctx, *collection); + break; + } + case ID_IM: + case ID_TE: { + DEG_add_generic_id_relation(ctx->node, id, "Nodes Modifier"); + } + default: { + /* Purposefully don't add relations for materials. While there are material sockets, + * the pointers are only passed around as handles rather than dereferenced. */ + break; } } } + + if (needs_own_transform_relation) { + DEG_add_modifier_to_transform_relation(ctx->node, "Nodes Modifier"); + } } static bool check_tree_for_time_node(const bNodeTree &tree, @@ -1691,7 +1726,6 @@ ModifierTypeInfo modifierType_Nodes = { /* deformVertsEM */ nullptr, /* deformMatricesEM */ nullptr, /* modifyMesh */ modifyMesh, - /* modifyHair */ nullptr, /* modifyGeometrySet */ modifyGeometrySet, /* initData */ initData, |