Fix #119554: Remove links to and from unsupported socket types
#114401 added forward compatibility code to remove unsupported socket types and avoid crashing with unknown default_value data. However, this did not update link pointers (which haven't been read at that point), so the tree can end up with dangling pointers. To fix this, removal of unsupported sockets is moved further back to a point where links have been read and can be fixed accordingly. Ported to main from #119630 Pull Request: https://projects.blender.org/blender/blender/pulls/119650
This commit is contained in:
@@ -975,17 +975,29 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
|
||||
}
|
||||
}
|
||||
|
||||
static void direct_link_node_socket_list(BlendDataReader *reader, ListBase *socket_list)
|
||||
static void remove_unsupported_sockets(ListBase *sockets, ListBase *links)
|
||||
{
|
||||
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, socket_list) {
|
||||
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, sockets) {
|
||||
if (is_node_socket_supported(sock)) {
|
||||
direct_link_node_socket(reader, sock);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
/* Remove unsupported sockets. */
|
||||
BLI_remlink(socket_list, sock);
|
||||
MEM_SAFE_FREE(sock);
|
||||
|
||||
/* First remove any link pointing to the socket. */
|
||||
if (links) {
|
||||
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, links) {
|
||||
if (link->fromsock == sock || link->tosock == sock) {
|
||||
BLI_remlink(links, link);
|
||||
if (link->tosock) {
|
||||
link->tosock->link = nullptr;
|
||||
}
|
||||
MEM_freeN(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BLI_remlink(sockets, sock);
|
||||
MEM_delete(sock->runtime);
|
||||
MEM_freeN(sock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1157,8 +1169,12 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
BLO_read_data_address(reader, &node->parent);
|
||||
|
||||
direct_link_node_socket_list(reader, &node->inputs);
|
||||
direct_link_node_socket_list(reader, &node->outputs);
|
||||
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->inputs) {
|
||||
direct_link_node_socket(reader, sock);
|
||||
}
|
||||
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->outputs) {
|
||||
direct_link_node_socket(reader, sock);
|
||||
}
|
||||
|
||||
/* Socket storage. */
|
||||
if (node->type == CMP_NODE_OUTPUT_FILE) {
|
||||
@@ -1173,8 +1189,12 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
|
||||
/* Read legacy interface socket lists for versioning. */
|
||||
BLO_read_list(reader, &ntree->inputs_legacy);
|
||||
BLO_read_list(reader, &ntree->outputs_legacy);
|
||||
direct_link_node_socket_list(reader, &ntree->inputs_legacy);
|
||||
direct_link_node_socket_list(reader, &ntree->outputs_legacy);
|
||||
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &ntree->inputs_legacy) {
|
||||
direct_link_node_socket(reader, sock);
|
||||
}
|
||||
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &ntree->outputs_legacy) {
|
||||
direct_link_node_socket(reader, sock);
|
||||
}
|
||||
|
||||
ntree->tree_interface.read_data(reader);
|
||||
|
||||
@@ -1185,6 +1205,13 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
|
||||
BLO_read_data_address(reader, &link->tosock);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
remove_unsupported_sockets(&node->inputs, &ntree->links);
|
||||
remove_unsupported_sockets(&node->outputs, &ntree->links);
|
||||
}
|
||||
remove_unsupported_sockets(&ntree->inputs_legacy, nullptr);
|
||||
remove_unsupported_sockets(&ntree->outputs_legacy, nullptr);
|
||||
|
||||
BLO_read_data_address(reader, &ntree->geometry_node_asset_traits);
|
||||
BLO_read_data_address(reader, &ntree->nested_node_refs);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user