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 = {
"name": "Node Wrangler",
"author": "Bartek Skorupa, Greg Zaal, Sebastian Koenig, Christian Brinkmann, Florian Meyer",
"version": (3, 55),
"version": (3, 56),
"blender": (4, 2, 0),
"location": "Node Editor Toolbar or Shift-W",
"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'
and space.node_tree is not 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):
l = self.layout

View File

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