Fix: Nodes: Inaccurate placement of framed nodes in swap operators
The swap operators use `Node.location` for location calculations. This expresses a node's location relative to their parent frames. This can lead to inaccurate location calculations if nodes have different parent frames. This was partly addressed by using the custom `temporary_unframe` context manager. However, that method is sensitive to the order of steps executed by the operator, making it easy to accidentally let a few location bugs go through. This patch fixes the issue by using `Node.location_absolute` which gives the node's absolute location. This also gets rid of the need for `temporary_unframe`, and makes the location calculations more straightforward. Pull Request: https://projects.blender.org/blender/blender/pulls/147424
This commit is contained in:
committed by
Jacques Lucke
parent
b24cc091f0
commit
1a6d932fbd
@@ -43,24 +43,6 @@ switch_nodes = {
|
||||
}
|
||||
|
||||
|
||||
# A context manager for temporarily un-parenting nodes from their frames.
|
||||
# This gets rid of issues with framed nodes using relative coordinates.
|
||||
class temporary_unframe:
|
||||
def __init__(self, nodes):
|
||||
self.parent_dict = {}
|
||||
for node in nodes:
|
||||
if node.parent is not None:
|
||||
self.parent_dict[node] = node.parent
|
||||
node.parent = None
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, _type, _value, _traceback):
|
||||
for node, parent in self.parent_dict.items():
|
||||
node.parent = parent
|
||||
|
||||
|
||||
def cast_value(source, target):
|
||||
source_type = source.type
|
||||
target_type = target.type
|
||||
@@ -492,16 +474,14 @@ class NODE_OT_swap_node(NodeSwapOperator, Operator):
|
||||
|
||||
new_node = self.create_node(context, self.type)
|
||||
self.apply_node_settings(new_node)
|
||||
self.transfer_node_properties(old_node, new_node)
|
||||
|
||||
if self.visible_output:
|
||||
for socket in new_node.outputs:
|
||||
if socket.name != self.visible_output:
|
||||
socket.hide = True
|
||||
|
||||
with temporary_unframe((old_node,)):
|
||||
new_node.location = old_node.location
|
||||
new_node.select = True
|
||||
new_node.location_absolute = old_node.location_absolute
|
||||
new_node.select = True
|
||||
|
||||
zone_pair = self.get_zone_pair(tree, old_node)
|
||||
|
||||
@@ -509,10 +489,9 @@ class NODE_OT_swap_node(NodeSwapOperator, Operator):
|
||||
input_node, output_node = zone_pair
|
||||
|
||||
if input_node.select and output_node.select:
|
||||
with temporary_unframe((input_node, output_node)):
|
||||
new_node.location = (input_node.location + output_node.location) / 2
|
||||
new_node.select = True
|
||||
new_node.location_absolute = (input_node.location_absolute + output_node.location_absolute) / 2
|
||||
|
||||
self.transfer_node_properties(old_node, new_node)
|
||||
self.transfer_input_values(input_node, new_node)
|
||||
|
||||
self.transfer_links(tree, input_node, new_node, is_input=True)
|
||||
@@ -521,6 +500,8 @@ class NODE_OT_swap_node(NodeSwapOperator, Operator):
|
||||
for node in zone_pair:
|
||||
nodes_to_delete.add(node)
|
||||
else:
|
||||
self.transfer_node_properties(old_node, new_node)
|
||||
|
||||
if (old_node.bl_idname in switch_nodes) and (new_node.bl_idname in switch_nodes):
|
||||
self.transfer_switch_data(old_node, new_node)
|
||||
|
||||
@@ -770,9 +751,8 @@ class NODE_OT_swap_zone(ZoneOperator, NodeSwapOperator, Operator):
|
||||
if zone_pair is not None:
|
||||
old_input_node, old_output_node = zone_pair
|
||||
|
||||
with temporary_unframe((old_input_node, old_output_node)):
|
||||
input_node.location = old_input_node.location
|
||||
output_node.location = old_output_node.location
|
||||
input_node.location_absolute = old_input_node.location_absolute
|
||||
output_node.location_absolute = old_output_node.location_absolute
|
||||
|
||||
self.transfer_node_properties(old_input_node, input_node)
|
||||
self.transfer_node_properties(old_output_node, output_node)
|
||||
@@ -789,12 +769,8 @@ class NODE_OT_swap_zone(ZoneOperator, NodeSwapOperator, Operator):
|
||||
for node in zone_pair:
|
||||
nodes_to_delete.add(node)
|
||||
else:
|
||||
with temporary_unframe((old_node,)):
|
||||
input_node.location = old_node.location
|
||||
output_node.location = old_node.location
|
||||
|
||||
input_node.location -= Vector(self.offset)
|
||||
output_node.location += Vector(self.offset)
|
||||
input_node.location_absolute = (old_node.location_absolute - Vector(self.offset))
|
||||
output_node.location_absolute = (old_node.location_absolute + Vector(self.offset))
|
||||
|
||||
self.transfer_node_properties(old_node, input_node)
|
||||
self.transfer_node_properties(old_node, output_node)
|
||||
|
||||
Reference in New Issue
Block a user