Fix: Nodes: Occasional crashing when using swap operators
Calling the swap operators can result in Blender crashing. From my testing, the behavior is inconsistent, as sometimes a crash is triggered and other times it isn't. Though notably, they seem involve nodes already linked to other nodes, or zones. The crashing stems from the operators trying to access deleted data. There were two places where this happens that were identified, one involving removed links and the other involving removed nodes. Pull Request: https://projects.blender.org/blender/blender/pulls/146909
This commit is contained in:
@@ -362,13 +362,12 @@ class NodeSwapOperator(NodeOperator):
|
||||
if new_socket.hide or not new_socket.enabled:
|
||||
continue
|
||||
|
||||
is_multi_input = link.to_socket.is_multi_input
|
||||
|
||||
new_link = tree.links.new(new_socket, link.to_socket)
|
||||
|
||||
try:
|
||||
if link.to_socket.is_multi_input:
|
||||
new_link.swap_multi_input_sort_id(link)
|
||||
except AttributeError:
|
||||
pass
|
||||
if is_multi_input:
|
||||
new_link.swap_multi_input_sort_id(link)
|
||||
|
||||
except KeyError:
|
||||
pass
|
||||
@@ -480,9 +479,10 @@ class NODE_OT_swap_node(NodeSwapOperator, Operator):
|
||||
|
||||
def execute(self, context):
|
||||
tree = context.space_data.edit_tree
|
||||
nodes_to_delete = set()
|
||||
|
||||
for old_node in context.selected_nodes[:]:
|
||||
if tree.nodes.get(old_node.name) is None:
|
||||
if old_node in nodes_to_delete:
|
||||
continue
|
||||
|
||||
if old_node.bl_idname == self.type:
|
||||
@@ -518,7 +518,7 @@ class NODE_OT_swap_node(NodeSwapOperator, Operator):
|
||||
self.transfer_links(tree, output_node, new_node, is_input=False)
|
||||
|
||||
for node in zone_pair:
|
||||
tree.nodes.remove(node)
|
||||
nodes_to_delete.add(node)
|
||||
else:
|
||||
if (old_node.bl_idname in switch_nodes) and (new_node.bl_idname in switch_nodes):
|
||||
self.transfer_switch_data(old_node, new_node)
|
||||
@@ -528,7 +528,10 @@ class NODE_OT_swap_node(NodeSwapOperator, Operator):
|
||||
self.transfer_links(tree, old_node, new_node, is_input=True)
|
||||
self.transfer_links(tree, old_node, new_node, is_input=False)
|
||||
|
||||
tree.nodes.remove(old_node)
|
||||
nodes_to_delete.add(old_node)
|
||||
|
||||
for node in nodes_to_delete:
|
||||
tree.nodes.remove(node)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
@@ -733,9 +736,10 @@ class NODE_OT_swap_zone(ZoneOperator, NodeSwapOperator, Operator):
|
||||
|
||||
def execute(self, context):
|
||||
tree = context.space_data.edit_tree
|
||||
nodes_to_delete = set()
|
||||
|
||||
for old_node in context.selected_nodes[:]:
|
||||
if tree.nodes.get(old_node.name) is None:
|
||||
if old_node in nodes_to_delete:
|
||||
continue
|
||||
|
||||
zone_pair = self.get_zone_pair(tree, old_node)
|
||||
@@ -782,7 +786,7 @@ class NODE_OT_swap_zone(ZoneOperator, NodeSwapOperator, Operator):
|
||||
self.transfer_links(tree, old_output_node, output_node, is_input=False)
|
||||
|
||||
for node in zone_pair:
|
||||
tree.nodes.remove(node)
|
||||
nodes_to_delete.add(node)
|
||||
else:
|
||||
with temporary_unframe((old_node,)):
|
||||
input_node.location = old_node.location
|
||||
@@ -799,7 +803,7 @@ class NODE_OT_swap_zone(ZoneOperator, NodeSwapOperator, Operator):
|
||||
self.transfer_links(tree, old_node, input_node, is_input=True)
|
||||
self.transfer_links(tree, old_node, output_node, is_input=False)
|
||||
|
||||
tree.nodes.remove(old_node)
|
||||
nodes_to_delete.add(old_node)
|
||||
|
||||
if tree.type == "GEOMETRY" and self.add_default_geometry_link:
|
||||
# Connect geometry sockets by default if available.
|
||||
@@ -810,6 +814,9 @@ class NODE_OT_swap_zone(ZoneOperator, NodeSwapOperator, Operator):
|
||||
if not (from_socket.is_linked or to_socket.is_linked):
|
||||
tree.links.new(to_socket, from_socket)
|
||||
|
||||
for node in nodes_to_delete:
|
||||
tree.nodes.remove(node)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user