From d981418c8ce0016e1cd778f4ddaf558cb7b0e724 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 4 Oct 2022 13:27:11 -0500 Subject: Fix: Crash versioning transfer node with animation data This versioning needs to be done after linking in order to affect animation data which might not be loaded in the regular "do_versions" loop. Animation data is removed in `nodeRemoveNode`. Fixes T101439 --- source/blender/blenloader/intern/versioning_300.cc | 300 +++++++++++---------- 1 file changed, 151 insertions(+), 149 deletions(-) (limited to 'source/blender/blenloader/intern') diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index 348ce168f71..8a6c73a7a5b 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -670,6 +670,147 @@ static bool seq_speed_factor_set(Sequence *seq, void *user_data) return true; } +static void version_geometry_nodes_replace_transfer_attribute_node(bNodeTree *ntree) +{ + using namespace blender; + /* Otherwise `ntree->typeInfo` is null. */ + ntreeSetTypes(NULL, ntree); + LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) { + if (node->type != GEO_NODE_TRANSFER_ATTRIBUTE_DEPRECATED) { + continue; + } + bNodeSocket *old_geometry_socket = nodeFindSocket(node, SOCK_IN, "Source"); + const NodeGeometryTransferAttribute *storage = (const NodeGeometryTransferAttribute *) + node->storage; + switch (storage->mode) { + case GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED: { + bNode *sample_nearest_surface = nodeAddStaticNode( + NULL, ntree, GEO_NODE_SAMPLE_NEAREST_SURFACE); + sample_nearest_surface->parent = node->parent; + sample_nearest_surface->custom1 = storage->data_type; + sample_nearest_surface->locx = node->locx; + sample_nearest_surface->locy = node->locy; + static auto socket_remap = []() { + Map map; + map.add_new("Attribute", "Value_Vector"); + map.add_new("Attribute_001", "Value_Float"); + map.add_new("Attribute_002", "Value_Color"); + map.add_new("Attribute_003", "Value_Bool"); + map.add_new("Attribute_004", "Value_Int"); + map.add_new("Source", "Mesh"); + map.add_new("Source Position", "Sample Position"); + return map; + }(); + node_tree_relink_with_socket_id_map(*ntree, *node, *sample_nearest_surface, socket_remap); + break; + } + case GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST: { + /* These domains weren't supported by the index transfer mode, but were selectable. */ + const eAttrDomain domain = ELEM(storage->domain, ATTR_DOMAIN_INSTANCE, ATTR_DOMAIN_CURVE) ? + ATTR_DOMAIN_POINT : + eAttrDomain(storage->domain); + + /* Use a sample index node to retrieve the data with this node's index output. */ + bNode *sample_index = nodeAddStaticNode(NULL, ntree, GEO_NODE_SAMPLE_INDEX); + NodeGeometrySampleIndex *sample_storage = static_cast( + sample_index->storage); + sample_storage->data_type = storage->data_type; + sample_storage->domain = domain; + sample_index->parent = node->parent; + sample_index->locx = node->locx + 25.0f; + sample_index->locy = node->locy; + if (old_geometry_socket->link) { + nodeAddLink(ntree, + old_geometry_socket->link->fromnode, + old_geometry_socket->link->fromsock, + sample_index, + nodeFindSocket(sample_index, SOCK_IN, "Geometry")); + } + + bNode *sample_nearest = nodeAddStaticNode(NULL, ntree, GEO_NODE_SAMPLE_NEAREST); + sample_nearest->parent = node->parent; + sample_nearest->custom1 = storage->data_type; + sample_nearest->custom2 = domain; + sample_nearest->locx = node->locx - 25.0f; + sample_nearest->locy = node->locy; + if (old_geometry_socket->link) { + nodeAddLink(ntree, + old_geometry_socket->link->fromnode, + old_geometry_socket->link->fromsock, + sample_nearest, + nodeFindSocket(sample_nearest, SOCK_IN, "Geometry")); + } + static auto sample_nearest_remap = []() { + Map map; + map.add_new("Source Position", "Sample Position"); + return map; + }(); + node_tree_relink_with_socket_id_map(*ntree, *node, *sample_nearest, sample_nearest_remap); + + static auto sample_index_remap = []() { + Map map; + map.add_new("Attribute", "Value_Vector"); + map.add_new("Attribute_001", "Value_Float"); + map.add_new("Attribute_002", "Value_Color"); + map.add_new("Attribute_003", "Value_Bool"); + map.add_new("Attribute_004", "Value_Int"); + map.add_new("Source Position", "Sample Position"); + return map; + }(); + node_tree_relink_with_socket_id_map(*ntree, *node, *sample_index, sample_index_remap); + + nodeAddLink(ntree, + sample_nearest, + nodeFindSocket(sample_nearest, SOCK_OUT, "Index"), + sample_index, + nodeFindSocket(sample_index, SOCK_IN, "Index")); + break; + } + case GEO_NODE_ATTRIBUTE_TRANSFER_INDEX: { + bNode *sample_index = nodeAddStaticNode(NULL, ntree, GEO_NODE_SAMPLE_INDEX); + NodeGeometrySampleIndex *sample_storage = static_cast( + sample_index->storage); + sample_storage->data_type = storage->data_type; + sample_storage->domain = storage->domain; + sample_storage->clamp = 1; + sample_index->parent = node->parent; + sample_index->locx = node->locx; + sample_index->locy = node->locy; + const bool index_was_linked = nodeFindSocket(node, SOCK_IN, "Index")->link != nullptr; + static auto socket_remap = []() { + Map map; + map.add_new("Attribute", "Value_Vector"); + map.add_new("Attribute_001", "Value_Float"); + map.add_new("Attribute_002", "Value_Color"); + map.add_new("Attribute_003", "Value_Bool"); + map.add_new("Attribute_004", "Value_Int"); + map.add_new("Source", "Geometry"); + map.add_new("Index", "Index"); + return map; + }(); + node_tree_relink_with_socket_id_map(*ntree, *node, *sample_index, socket_remap); + + if (!index_was_linked) { + /* Add an index input node, since the new node doesn't use an implicit input. */ + bNode *index = nodeAddStaticNode(NULL, ntree, GEO_NODE_INPUT_INDEX); + index->parent = node->parent; + index->locx = node->locx - 25.0f; + index->locy = node->locy - 25.0f; + nodeAddLink(ntree, + index, + nodeFindSocket(index, SOCK_OUT, "Index"), + sample_index, + nodeFindSocket(sample_index, SOCK_IN, "Index")); + } + break; + } + } + /* The storage must be freed manually because the node type isn't defined anymore. */ + MEM_freeN(node->storage); + nodeRemoveNode(NULL, ntree, node, false); + } +} + void do_versions_after_linking_300(Main *bmain, ReportList * /*reports*/) { if (MAIN_VERSION_ATLEAST(bmain, 300, 0) && !MAIN_VERSION_ATLEAST(bmain, 300, 1)) { @@ -933,6 +1074,16 @@ void do_versions_after_linking_300(Main *bmain, ReportList * /*reports*/) } } + if (!MAIN_VERSION_ATLEAST(bmain, 304, 1)) { + /* Split the transfer attribute node into multiple smaller nodes. */ + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_GEOMETRY) { + version_geometry_nodes_replace_transfer_attribute_node(ntree); + } + } + FOREACH_NODETREE_END; + } + /** * Versioning code until next subversion bump goes here. * @@ -1791,147 +1942,6 @@ static void version_fix_image_format_copy(Main *bmain, ImageFormatData *format) } } -static void version_geometry_nodes_replace_transfer_attribute_node(bNodeTree *ntree) -{ - using namespace blender; - /* Otherwise `ntree->typeInfo` is null. */ - ntreeSetTypes(NULL, ntree); - LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) { - if (node->type != GEO_NODE_TRANSFER_ATTRIBUTE_DEPRECATED) { - continue; - } - bNodeSocket *old_geometry_socket = nodeFindSocket(node, SOCK_IN, "Source"); - const NodeGeometryTransferAttribute *storage = (const NodeGeometryTransferAttribute *) - node->storage; - switch (storage->mode) { - case GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST_FACE_INTERPOLATED: { - bNode *sample_nearest_surface = nodeAddStaticNode( - NULL, ntree, GEO_NODE_SAMPLE_NEAREST_SURFACE); - sample_nearest_surface->parent = node->parent; - sample_nearest_surface->custom1 = storage->data_type; - sample_nearest_surface->locx = node->locx; - sample_nearest_surface->locy = node->locy; - static auto socket_remap = []() { - Map map; - map.add_new("Attribute", "Value_Vector"); - map.add_new("Attribute_001", "Value_Float"); - map.add_new("Attribute_002", "Value_Color"); - map.add_new("Attribute_003", "Value_Bool"); - map.add_new("Attribute_004", "Value_Int"); - map.add_new("Source", "Mesh"); - map.add_new("Source Position", "Sample Position"); - return map; - }(); - node_tree_relink_with_socket_id_map(*ntree, *node, *sample_nearest_surface, socket_remap); - break; - } - case GEO_NODE_ATTRIBUTE_TRANSFER_NEAREST: { - /* These domains weren't supported by the index transfer mode, but were selectable. */ - const eAttrDomain domain = ELEM(storage->domain, ATTR_DOMAIN_INSTANCE, ATTR_DOMAIN_CURVE) ? - ATTR_DOMAIN_POINT : - eAttrDomain(storage->domain); - - /* Use a sample index node to retrieve the data with this node's index output. */ - bNode *sample_index = nodeAddStaticNode(NULL, ntree, GEO_NODE_SAMPLE_INDEX); - NodeGeometrySampleIndex *sample_storage = static_cast( - sample_index->storage); - sample_storage->data_type = storage->data_type; - sample_storage->domain = domain; - sample_index->parent = node->parent; - sample_index->locx = node->locx + 25.0f; - sample_index->locy = node->locy; - if (old_geometry_socket->link) { - nodeAddLink(ntree, - old_geometry_socket->link->fromnode, - old_geometry_socket->link->fromsock, - sample_index, - nodeFindSocket(sample_index, SOCK_IN, "Geometry")); - } - - bNode *sample_nearest = nodeAddStaticNode(NULL, ntree, GEO_NODE_SAMPLE_NEAREST); - sample_nearest->parent = node->parent; - sample_nearest->custom1 = storage->data_type; - sample_nearest->custom2 = domain; - sample_nearest->locx = node->locx - 25.0f; - sample_nearest->locy = node->locy; - if (old_geometry_socket->link) { - nodeAddLink(ntree, - old_geometry_socket->link->fromnode, - old_geometry_socket->link->fromsock, - sample_nearest, - nodeFindSocket(sample_nearest, SOCK_IN, "Geometry")); - } - static auto sample_nearest_remap = []() { - Map map; - map.add_new("Source Position", "Sample Position"); - return map; - }(); - node_tree_relink_with_socket_id_map(*ntree, *node, *sample_nearest, sample_nearest_remap); - - static auto sample_index_remap = []() { - Map map; - map.add_new("Attribute", "Value_Vector"); - map.add_new("Attribute_001", "Value_Float"); - map.add_new("Attribute_002", "Value_Color"); - map.add_new("Attribute_003", "Value_Bool"); - map.add_new("Attribute_004", "Value_Int"); - map.add_new("Source Position", "Sample Position"); - return map; - }(); - node_tree_relink_with_socket_id_map(*ntree, *node, *sample_index, sample_index_remap); - - nodeAddLink(ntree, - sample_nearest, - nodeFindSocket(sample_nearest, SOCK_OUT, "Index"), - sample_index, - nodeFindSocket(sample_index, SOCK_IN, "Index")); - break; - } - case GEO_NODE_ATTRIBUTE_TRANSFER_INDEX: { - bNode *sample_index = nodeAddStaticNode(NULL, ntree, GEO_NODE_SAMPLE_INDEX); - NodeGeometrySampleIndex *sample_storage = static_cast( - sample_index->storage); - sample_storage->data_type = storage->data_type; - sample_storage->domain = storage->domain; - sample_storage->clamp = 1; - sample_index->parent = node->parent; - sample_index->locx = node->locx; - sample_index->locy = node->locy; - const bool index_was_linked = nodeFindSocket(node, SOCK_IN, "Index")->link != nullptr; - static auto socket_remap = []() { - Map map; - map.add_new("Attribute", "Value_Vector"); - map.add_new("Attribute_001", "Value_Float"); - map.add_new("Attribute_002", "Value_Color"); - map.add_new("Attribute_003", "Value_Bool"); - map.add_new("Attribute_004", "Value_Int"); - map.add_new("Source", "Geometry"); - map.add_new("Index", "Index"); - return map; - }(); - node_tree_relink_with_socket_id_map(*ntree, *node, *sample_index, socket_remap); - - if (!index_was_linked) { - /* Add an index input node, since the new node doesn't use an implicit input. */ - bNode *index = nodeAddStaticNode(NULL, ntree, GEO_NODE_INPUT_INDEX); - index->parent = node->parent; - index->locx = node->locx - 25.0f; - index->locy = node->locy - 25.0f; - nodeAddLink(ntree, - index, - nodeFindSocket(index, SOCK_OUT, "Index"), - sample_index, - nodeFindSocket(sample_index, SOCK_IN, "Index")); - } - break; - } - } - /* The storage must be freed manually because the node type isn't defined anymore. */ - MEM_freeN(node->storage); - nodeRemoveNode(NULL, ntree, node, false); - } -} - /* NOLINTNEXTLINE: readability-function-size */ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) { @@ -3574,14 +3584,6 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) } } } - - /* Split the transfer attribute node into multiple smaller nodes. */ - FOREACH_NODETREE_BEGIN (bmain, ntree, id) { - if (ntree->type == NTREE_GEOMETRY) { - version_geometry_nodes_replace_transfer_attribute_node(ntree); - } - } - FOREACH_NODETREE_END; } if (!MAIN_VERSION_ATLEAST(bmain, 304, 2)) { -- cgit v1.2.3