Fix: Node Wrangler: Various fixes and cleanup

Fix error in Attributes menu in World shading mode

Node Wrangler's Attributes menu allows direct addition of attributes
to a shading node tree. It only works on objects, not World, since the
latter does not store attributes.

Fix: Update Merge Nodes operator for new node types

Nodes were deduplicated between node modes (shading, compositing,
geometry) in Blender 5.0. This commit aligns Node Wrangler's Merge
Nodes operator to the new node types.

Cleanup
- Remove unused import and variables
- Merge Nodes Operator
  - Use negative list indices instead of length - index.
  - Chain conditions instead of nesting them.

Pull Request: https://projects.blender.org/blender/blender/pulls/141508
This commit is contained in:
Damien Picard
2025-07-11 15:25:06 +02:00
committed by Nika Kutsniashvili
parent 8840aa8718
commit db39daf9e7
3 changed files with 19 additions and 39 deletions

View File

@@ -5,7 +5,7 @@
bl_info = { bl_info = {
"name": "Node Wrangler", "name": "Node Wrangler",
"author": "Bartek Skorupa, Greg Zaal, Sebastian Koenig, Christian Brinkmann, Florian Meyer", "author": "Bartek Skorupa, Greg Zaal, Sebastian Koenig, Christian Brinkmann, Florian Meyer",
"version": (3, 55), "version": (3, 56),
"blender": (4, 2, 0), "blender": (4, 2, 0),
"location": "Node Editor Toolbar or Shift-W", "location": "Node Editor Toolbar or Shift-W",
"description": "Various tools to enhance and speed up node-based workflow", "description": "Various tools to enhance and speed up node-based workflow",

View File

@@ -358,7 +358,8 @@ class NWAttributeMenu(bpy.types.Menu):
return (space.type == 'NODE_EDITOR' return (space.type == 'NODE_EDITOR'
and space.node_tree is not None and space.node_tree is not None
and space.node_tree.library is None and space.node_tree.library is None
and space.tree_type == 'ShaderNodeTree') and space.tree_type == 'ShaderNodeTree'
and space.shader_type == 'OBJECT')
def draw(self, context): def draw(self, context):
l = self.layout l = self.layout

View File

@@ -11,7 +11,6 @@ from bpy.props import (
BoolProperty, BoolProperty,
IntProperty, IntProperty,
StringProperty, StringProperty,
FloatVectorProperty,
CollectionProperty, CollectionProperty,
) )
from bpy.app.translations import ( from bpy.app.translations import (
@@ -54,8 +53,6 @@ class NWLazyMix(Operator, NWBase):
nodes, links = get_nodes_links(context) nodes, links = get_nodes_links(context)
cont = True cont = True
start_pos = [event.mouse_region_x, event.mouse_region_y]
node1 = None node1 = None
if not context.scene.NWBusyDrawing: if not context.scene.NWBusyDrawing:
node1 = node_at_pos(nodes, context, event) node1 = node_at_pos(nodes, context, event)
@@ -72,7 +69,6 @@ class NWLazyMix(Operator, NWBase):
self.mouse_path.append((event.mouse_region_x, event.mouse_region_y)) self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
elif event.type == 'RIGHTMOUSE' and event.value == 'RELEASE': elif event.type == 'RIGHTMOUSE' and event.value == 'RELEASE':
end_pos = [event.mouse_region_x, event.mouse_region_y]
bpy.types.SpaceNodeEditor.draw_handler_remove(self._handle, 'WINDOW') bpy.types.SpaceNodeEditor.draw_handler_remove(self._handle, 'WINDOW')
node2 = None node2 = None
@@ -136,8 +132,6 @@ class NWLazyConnect(Operator, NWBase):
nodes, links = get_nodes_links(context) nodes, links = get_nodes_links(context)
cont = True cont = True
start_pos = [event.mouse_region_x, event.mouse_region_y]
node1 = None node1 = None
if not context.scene.NWBusyDrawing: if not context.scene.NWBusyDrawing:
node1 = node_at_pos(nodes, context, event) node1 = node_at_pos(nodes, context, event)
@@ -154,7 +148,6 @@ class NWLazyConnect(Operator, NWBase):
self.mouse_path.append((event.mouse_region_x, event.mouse_region_y)) self.mouse_path.append((event.mouse_region_x, event.mouse_region_y))
elif event.type == 'RIGHTMOUSE' and event.value == 'RELEASE': elif event.type == 'RIGHTMOUSE' and event.value == 'RELEASE':
end_pos = [event.mouse_region_x, event.mouse_region_y]
bpy.types.SpaceNodeEditor.draw_handler_remove(self._handle, 'WINDOW') bpy.types.SpaceNodeEditor.draw_handler_remove(self._handle, 'WINDOW')
node2 = None node2 = None
@@ -766,23 +759,21 @@ class NWMergeNodes(Operator, NWBase):
nodes_list.sort(key=lambda k: k[2], reverse=True) nodes_list.sort(key=lambda k: k[2], reverse=True)
# Change the node type for math nodes in a geometry node tree. # Change the node type for math nodes in a geometry node tree.
if tree_type == 'GEOMETRY': if (
if nodes_list is selected_math or nodes_list is selected_vector or nodes_list is selected_mix: tree_type == 'GEOMETRY'
node_type = 'ShaderNode' and nodes_list in (selected_math, selected_vector, selected_mix)
if mode == 'MIX': and mode == 'MIX'):
mode = 'ADD' mode = 'ADD'
else:
node_type = 'GeometryNode'
if merge_position == 'CENTER': if merge_position == 'CENTER':
# average yloc of last two nodes (lowest two) # average yloc of last two nodes (lowest two)
loc_y = ((nodes_list[len(nodes_list) - 1][2]) + (nodes_list[len(nodes_list) - 2][2])) / 2 loc_y = ((nodes_list[-1][2]) + (nodes_list[-2][2])) / 2
if nodes_list[len(nodes_list) - 1][-1]: # if last node is hidden, mix should be shifted up a bit if nodes_list[-1][-1]: # if last node is hidden, mix should be shifted up a bit
if do_hide: if do_hide:
loc_y += 40 loc_y += 40
else: else:
loc_y += 80 loc_y += 80
else: else:
loc_y = nodes_list[len(nodes_list) - 1][2] loc_y = nodes_list[-1][2]
offset_y = 100 offset_y = 100
if not do_hide: if not do_hide:
offset_y = 200 offset_y = 200
@@ -794,13 +785,8 @@ class NWMergeNodes(Operator, NWBase):
was_multi = False was_multi = False
for i in range(the_range): for i in range(the_range):
if nodes_list == selected_mix: if nodes_list == selected_mix:
mix_name = 'Mix' add = nodes.new('ShaderNodeMix')
if tree_type == 'COMPOSITING': add.data_type = 'RGBA'
mix_name = 'MixRGB'
add_type = node_type + mix_name
add = nodes.new(add_type)
if tree_type != 'COMPOSITING':
add.data_type = 'RGBA'
add.blend_type = mode add.blend_type = mode
if mode != 'MIX': if mode != 'MIX':
add.inputs[0].default_value = 1.0 add.inputs[0].default_value = 1.0
@@ -810,12 +796,8 @@ class NWMergeNodes(Operator, NWBase):
loc_y = loc_y - 50 loc_y = loc_y - 50
first = 6 first = 6
second = 7 second = 7
if tree_type == 'COMPOSITING':
first = 1
second = 2
elif nodes_list == selected_math: elif nodes_list == selected_math:
add_type = node_type + 'Math' add = nodes.new('ShaderNodeMath')
add = nodes.new(add_type)
add.operation = mode add.operation = mode
add.hide = do_hide add.hide = do_hide
if do_hide: if do_hide:
@@ -824,16 +806,14 @@ class NWMergeNodes(Operator, NWBase):
second = 1 second = 1
elif nodes_list == selected_shader: elif nodes_list == selected_shader:
if mode == 'MIX': if mode == 'MIX':
add_type = node_type + 'MixShader' add = nodes.new('ShaderNodeMixShader')
add = nodes.new(add_type)
add.hide = do_hide_shader add.hide = do_hide_shader
if do_hide_shader: if do_hide_shader:
loc_y = loc_y - 50 loc_y = loc_y - 50
first = 1 first = 1
second = 2 second = 2
elif mode == 'ADD': elif mode == 'ADD':
add_type = node_type + 'AddShader' add = nodes.new('ShaderNodeAddShader')
add = nodes.new(add_type)
add.hide = do_hide_shader add.hide = do_hide_shader
if do_hide_shader: if do_hide_shader:
loc_y = loc_y - 50 loc_y = loc_y - 50
@@ -841,11 +821,11 @@ class NWMergeNodes(Operator, NWBase):
second = 1 second = 1
elif nodes_list == selected_geometry: elif nodes_list == selected_geometry:
if mode in ('JOIN', 'MIX'): if mode in ('JOIN', 'MIX'):
add_type = node_type + 'JoinGeometry' add_type = 'GeometryNodeJoinGeometry'
add = self.merge_with_multi_input( add = self.merge_with_multi_input(
nodes_list, merge_position, do_hide, loc_x, links, nodes, add_type, [0]) nodes_list, merge_position, do_hide, loc_x, links, nodes, add_type, [0])
else: else:
add_type = node_type + 'MeshBoolean' add_type = 'GeometryNodeMeshBoolean'
indices = [0, 1] if mode == 'DIFFERENCE' else [1] indices = [0, 1] if mode == 'DIFFERENCE' else [1]
add = self.merge_with_multi_input( add = self.merge_with_multi_input(
nodes_list, merge_position, do_hide, loc_x, links, nodes, add_type, indices) nodes_list, merge_position, do_hide, loc_x, links, nodes, add_type, indices)
@@ -853,8 +833,7 @@ class NWMergeNodes(Operator, NWBase):
was_multi = True was_multi = True
break break
elif nodes_list == selected_vector: elif nodes_list == selected_vector:
add_type = node_type + 'VectorMath' add = nodes.new('ShaderNodeVectorMath')
add = nodes.new(add_type)
add.operation = mode add.operation = mode
add.hide = do_hide add.hide = do_hide
if do_hide: if do_hide: